新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 第15節:矩陣鍵盤單個觸發的壓縮代碼編程

        第15節:矩陣鍵盤單個觸發的壓縮代碼編程

        作者: 時間:2016-11-22 來源:網絡 收藏
        開場白:

        上一節講了矩陣鍵盤單個觸發。這節要教會大家在不改變其它任何性能的情況下,把上一節的按鍵掃描程序壓縮一下容量。經過壓縮后,把原來1558個字節壓縮到860個字節的程序容量。

        本文引用地址:http://www.104case.com/article/201611/319794.htm

        具體內容,請看源代碼講解。

        (1)硬件平臺:基于朱兆祺51單片機學習板。。

        (2)實現功能:16個按鍵中,每按一個按鍵都能觸發一次蜂鳴器發出“滴”的一聲。

        (3)源代碼講解如下:

        #include "REG52.H"

        #define const_voice_short 40 //蜂鳴器短叫的持續時間

        #define const_key_time 20 //按鍵去抖動延時的時間

        void initial_myself();

        void initial_peripheral();

        void delay_long(unsigned int uiDelaylong);

        void T0_time(); //定時中斷函數

        void key_service(); //按鍵服務的應用程序

        void key_scan(); //按鍵掃描函數 放在定時中斷里

        sbit key_sr1=P0^0; //第一行輸入

        sbit key_sr2=P0^1; //第二行輸入

        sbit key_sr3=P0^2; //第三行輸入

        sbit key_sr4=P0^3; //第四行輸入

        sbit key_dr1=P0^4; //第一列輸出

        sbit key_dr2=P0^5; //第二列輸出

        sbit key_dr3=P0^6; //第三列輸出

        sbit key_dr4=P0^7; //第四列輸出

        sbit beep_dr=P2^7; //蜂鳴器的驅動IO口

        unsigned char ucKeyStep=1; //按鍵掃描步驟變量

        unsigned char ucKeySec=0; //被觸發的按鍵編號

        unsigned int uiKeyTimeCnt=0; //按鍵去抖動延時計數器

        unsigned char ucKeyLock=0; //按鍵觸發后自鎖的變量標志

        unsigned char ucRowRecord=1; //記錄當前掃描到第幾列了

        unsigned int uiVoiceCnt=0; //蜂鳴器鳴叫的持續時間計數器

        void main()

        {

        initial_myself();

        delay_long(100);

        initial_peripheral();

        while(1)

        {

        key_service(); //按鍵服務的應用程序

        }

        }

        void key_scan()//按鍵掃描函數 放在定時中斷里

        {

        /* 注釋一:

        * 矩陣按鍵掃描的詳細過程:

        * 先輸出某一列低電平,其它三列輸出高電平,這個時候再分別判斷輸入的四行,

        * 如果發現哪一行是低電平,就說明對應的某個按鍵被觸發。依次分別輸出另外三列

        * 中的某一列為低電平,再分別判斷輸入的四行,就可以檢測完16個按鍵。內部詳細的

        * 去抖動處理方法跟我前面講的獨立按鍵去抖動方法是一樣的。

        */

        switch(ucKeyStep)

        {

        case 1: //按鍵掃描輸出第ucRowRecord列低電平

        if(ucRowRecord==1) //第一列輸出低電平

        {

        key_dr1=0;

        key_dr2=1;

        key_dr3=1;

        key_dr4=1;

        }

        else if(ucRowRecord==2) //第二列輸出低電平

        {

        key_dr1=1;

        key_dr2=0;

        key_dr3=1;

        key_dr4=1;

        }

        else if(ucRowRecord==3) //第三列輸出低電平

        {

        key_dr1=1;

        key_dr2=1;

        key_dr3=0;

        key_dr4=1;

        }

        else //第四列輸出低電平

        {

        key_dr1=1;

        key_dr2=1;

        key_dr3=1;

        key_dr4=0;

        }

        uiKeyTimeCnt=0; //延時計數器清零

        ucKeyStep++; //切換到下一個運行步驟

        break;

        case 2: //此處的小延時用來等待剛才列輸出信號穩定,再判斷輸入信號。不是去抖動延時。

        uiKeyTimeCnt++;

        if(uiKeyTimeCnt>1)

        {

        uiKeyTimeCnt=0;

        ucKeyStep++; //切換到下一個運行步驟

        }

        break;

        case 3:

        if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==1)

        {

        ucKeyStep=1; //如果沒有按鍵按下,返回到第一個運行步驟重新開始掃描

        ucKeyLock=0; //按鍵自鎖標志清零

        uiKeyTimeCnt=0; //按鍵去抖動延時計數器清零,此行非常巧妙

        ucRowRecord++; //輸出下一列

        if(ucRowRecord>4)

        {

        ucRowRecord=1; //依次輸出完四列之后,繼續從第一列開始輸出低電平

        }

        }

        else if(ucKeyLock==0) //有按鍵按下,且是第一次觸發

        {

        if(key_sr1==0&&key_sr2==1&&key_sr3==1&&key_sr4==1)

        {

        uiKeyTimeCnt++; //去抖動延時計數器

        if(uiKeyTimeCnt>const_key_time)

        {

        uiKeyTimeCnt=0;

        ucKeyLock=1;//自鎖按鍵置位,避免一直觸發,只有松開按鍵,此標志位才會被清零

        if(ucRowRecord==1) //第一列輸出低電平

        {

        ucKeySec=1; //觸發1號鍵 對應朱兆祺學習板的S1鍵

        }

        else if(ucRowRecord==2) //第二列輸出低電平

        {

        ucKeySec=2; //觸發2號鍵 對應朱兆祺學習板的S2鍵

        }

        else if(ucRowRecord==3) //第三列輸出低電平

        {

        ucKeySec=3; //觸發3號鍵 對應朱兆祺學習板的S3鍵

        }

        else //第四列輸出低電平

        {

        ucKeySec=4; //觸發4號鍵 對應朱兆祺學習板的S4鍵

        }

        }

        }

        else if(key_sr1==1&&key_sr2==0&&key_sr3==1&&key_sr4==1)

        {

        uiKeyTimeCnt++; //去抖動延時計數器

        if(uiKeyTimeCnt>const_key_time)

        {

        uiKeyTimeCnt=0;

        ucKeyLock=1;//自鎖按鍵置位,避免一直觸發,只有松開按鍵,此標志位才會被清零

        if(ucRowRecord==1) //第一列輸出低電平

        {

        ucKeySec=5; //觸發5號鍵 對應朱兆祺學習板的S5鍵

        }

        else if(ucRowRecord==2) //第二列輸出低電平

        {

        ucKeySec=6; //觸發6號鍵 對應朱兆祺學習板的S6鍵

        }

        else if(ucRowRecord==3) //第三列輸出低電平

        {

        ucKeySec=7; //觸發7號鍵 對應朱兆祺學習板的S7鍵

        }

        else //第四列輸出低電平

        {

        ucKeySec=8; //觸發8號鍵 對應朱兆祺學習板的S8鍵

        }

        }

        }

        else if(key_sr1==1&&key_sr2==1&&key_sr3==0&&key_sr4==1)

        {

        uiKeyTimeCnt++; //去抖動延時計數器

        if(uiKeyTimeCnt>const_key_time)

        {

        uiKeyTimeCnt=0;

        ucKeyLock=1;//自鎖按鍵置位,避免一直觸發,只有松開按鍵,此標志位才會被清零

        if(ucRowRecord==1) //第一列輸出低電平

        {

        ucKeySec=9; //觸發9號鍵 對應朱兆祺學習板的S9鍵

        }

        else if(ucRowRecord==2) //第二列輸出低電平

        {

        ucKeySec=10; //觸發10號鍵 對應朱兆祺學習板的S10鍵

        }

        else if(ucRowRecord==3) //第三列輸出低電平

        {

        ucKeySec=11; //觸發11號鍵 對應朱兆祺學習板的S11鍵

        }

        else //第四列輸出低電平

        {

        ucKeySec=12; //觸發12號鍵 對應朱兆祺學習板的S12鍵

        }

        }

        }

        else if(key_sr1==1&&key_sr2==1&&key_sr3==1&&key_sr4==0)

        {

        uiKeyTimeCnt++; //去抖動延時計數器

        if(uiKeyTimeCnt>const_key_time)

        {

        uiKeyTimeCnt=0;

        ucKeyLock=1;//自鎖按鍵置位,避免一直觸發,只有松開按鍵,此標志位才會被清零

        if(ucRowRecord==1) //第一列輸出低電平

        {

        ucKeySec=13; //觸發13號鍵 對應朱兆祺學習板的S13鍵

        }

        else if(ucRowRecord==2) //第二列輸出低電平

        {

        ucKeySec=14; //觸發14號鍵 對應朱兆祺學習板的S14鍵

        }

        else if(ucRowRecord==3) //第三列輸出低電平

        {

        ucKeySec=15; //觸發15號鍵 對應朱兆祺學習板的S15鍵

        }

        else //第四列輸出低電平

        {

        ucKeySec=16; //觸發16號鍵 對應朱兆祺學習板的S16鍵

        }

        }

        }

        }

        break;

        }

        }

        void key_service() //第三區 按鍵服務的應用程序

        {

        switch(ucKeySec) //按鍵服務狀態切換

        {

        case 1:// 1號鍵 對應朱兆祺學習板的S1鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 2:// 2號鍵 對應朱兆祺學習板的S2鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 3:// 3號鍵 對應朱兆祺學習板的S3鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 4:// 4號鍵 對應朱兆祺學習板的S4鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 5:// 5號鍵 對應朱兆祺學習板的S5鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 6:// 6號鍵 對應朱兆祺學習板的S6鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 7:// 7號鍵 對應朱兆祺學習板的S7鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 8:// 8號鍵 對應朱兆祺學習板的S8鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 9:// 9號鍵 對應朱兆祺學習板的S9鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 10:// 10號鍵 對應朱兆祺學習板的S10鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 11:// 11號鍵 對應朱兆祺學習板的S11鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 12:// 12號鍵 對應朱兆祺學習板的S12鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 13:// 13號鍵 對應朱兆祺學習板的S13鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 14:// 14號鍵 對應朱兆祺學習板的S14鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 15:// 15號鍵 對應朱兆祺學習板的S15鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        case 16:// 16號鍵 對應朱兆祺學習板的S16鍵

        uiVoiceCnt=const_voice_short; //按鍵聲音觸發,滴一聲就停。

        ucKeySec=0; //響應按鍵服務處理程序后,按鍵編號清零,避免一致觸發

        break;

        }

        }

        void T0_time() interrupt 1

        {

        TF0=0; //清除中斷標志

        TR0=0; //關中斷

        key_scan(); //按鍵掃描函數

        if(uiVoiceCnt!=0)

        {

        uiVoiceCnt--; //每次進入定時中斷都自減1,直到等于零為止。才停止鳴叫

        beep_dr=0; //蜂鳴器是PNP三極管控制,低電平就開始鳴叫。

        }

        else

        {

        ; //此處多加一個空指令,想維持跟if括號語句的數量對稱,都是兩條指令。不加也可以。

        beep_dr=1; //蜂鳴器是PNP三極管控制,高電平就停止鳴叫。

        }

        TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f

        TL0=0x2f;

        TR0=1; //開中斷

        }

        void delay_long(unsigned int uiDelayLong)

        {

        unsigned int i;

        unsigned int j;

        for(i=0;i

        {

        for(j=0;j<500;j++) //內嵌循環的空指令數量

        {

        ; //一個分號相當于執行一條空語句

        }

        }

        }

        void initial_myself() //第一區 初始化單片機

        {

        beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時不叫。

        TMOD=0x01; //設置定時器0為工作方式1

        TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f

        TL0=0x2f;

        }

        void initial_peripheral() //第二區 初始化外圍

        {

        EA=1; //開總中斷

        ET0=1; //允許定時中斷

        TR0=1; //啟動定時中斷

        }

        總結陳詞:

        已經花了兩節講矩陣鍵盤的單個觸發程序。那么,矩陣鍵盤可不可以實現類似獨立按鍵的組合按鍵功能?當然可以,但是也有一些附加限制條件。欲知詳情,請聽下回分解-----矩陣鍵盤的組合按鍵觸發。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 桃江县| 汨罗市| 汝城县| 大兴区| 拉孜县| 平陆县| 碌曲县| 彩票| 乌拉特后旗| 兴和县| 饶平县| 乃东县| 石景山区| 松原市| 厦门市| 平邑县| 长汀县| 调兵山市| 永清县| 化隆| 晴隆县| 嘉祥县| 苏州市| 大城县| 双江| 雅安市| 綦江县| 阿城市| 洛川县| 宁国市| 曲麻莱县| 常山县| 清镇市| 通辽市| 安远县| 仁怀市| 张掖市| 阜新市| 古交市| 辽源市| 灵璧县|