<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        單片機矩陣按鍵定時器消抖程序源碼

        作者:寒竹子   來源:本站原創   點擊數:  更新時間:2014年03月18日   【字體:

        芯片是采用的stc89c51單片機.

        下面是矩陣鍵盤的電路圖,矩陣鍵盤是接在p2口的.

        下面是單片機部分的圖,數碼管顯示等完整的原理圖可以從 http://www.thefapper.com/f/ks51.pdf  這里下載

         


        下面是程序源碼:

        /********矩陣按鍵定時器消抖**************/
        /**
        *時間:2014年3月18日20:27:23
        *作者:寒竹子
        *工程寫法:用定時器為按鍵消抖不占用cpu的時間
        **/

        #include <reg52.h>

        typedef unsigned int uint;
        typedef unsigned char uchar;

        //138
        sbit ADDR0 = P1^0;
        sbit ADDR1 = P1^1;
        sbit ADDR2 = P1^2;
        sbit ADDR3 = P1^3;
        sbit ENLED = P1^4;

        //KeyIn
        sbit KeyIn1 = P2^4;
        sbit KeyIn2 = P2^5;
        sbit KeyIn3 = P2^6;
        sbit KeyIn4 = P2^7;

        //KeyOut
        sbit KeyOut1 = P2^3;
        sbit KeyOut2 = P2^2;
        sbit KeyOut3 = P2^1;
        sbit KeyOut4 = P2^0;

        //數碼管編碼
        uchar code table[] = { 
        0xC0,  //"0"
                        0xF9,  //"1"
                        0xA4,  //"2"
                        0xB0,  //"3"
                        0x99,  //"4"
                        0x92,  //"5"
                        0x82,  //"6"
                        0xF8,  //"7"
                        0x80,  //"8"
                        0x90,  //"9"
                        0x88,  //"A"
                        0x83,  //"B"
                        0xC6,  //"C"
                        0xA1,  //"D"
                        0x86,  //"E"
                        0x8E   //"F"
        };

        uchar key = 0;

        //16個按鍵初始化1
        uchar keysta[4][4] =
        {
        {1, 1, 1, 1}, //K1 - K4
        {1, 1, 1, 1}, //K5 - K8
        {1, 1, 1, 1}, //K9 - K 12
        {1, 1, 1, 1} //K13 - K16
        };

        //16個按鍵的備份值初始值1
        uchar keybackup[4][4] = {
        {1, 1, 1, 1},
        {1, 1, 1, 1}, 
        {1, 1, 1, 1},
        {1, 1, 1, 1}
        };

        void keymatrixScan();
        void timer0_init();
        void refresh();
        void HC138_init();

        void main()
        {
        timer0_init();
        HC138_init();

        while (1)
        {
        keymatrixScan();
        }
        }

        /********timer0 init*************/
        void timer0_init()
        {
        TMOD |= 0x01;
        TMOD &= 0xF1; //1111 0001,配置T0方式1
        TH0 = 0xFC;
        TL0 = 0x67;//1ms
        TR0 = 1;//start T0
        EA = 1; //open main int
        ET0 = 1;//open T0 int
        }

        /***********HC138 init*********/
        void HC138_init()
        {
        ADDR3 = 1;
        ENLED = 0;//使能U3
        }

        /***********刷新數碼管************/
        void refresh()
        {
        static uchar j = 0;//刷新數碼管
        P0 = 0xFF;//消隱
        switch (j)
        {
        case 0: ADDR2 = 0; ADDR1 = 0; ADDR0 = 0;
        break;
        case 1: ADDR2 = 0; ADDR1 = 0; ADDR0 = 1;
        break;
        case 2: ADDR2 = 0; ADDR1 = 1; ADDR0 = 0;
        break;
        case 3: ADDR2 = 0; ADDR1 = 1; ADDR0 = 1;
        break;
        case 4: ADDR2 = 1; ADDR1 = 0; ADDR0 = 0;
        break;
        case 5: ADDR2 = 1; ADDR1 = 0; ADDR0 = 1;
        break;
        default:
        break;
        }
        P0 = table[key]; //在此處送入顯示的數據,很正常的顯示出來,當放到while(1)中時會出現抖動
        j++;
        if (j >= 6)
        {
        j = 0;
        }
        }

        /**********矩陣按鍵檢測***********/
        void keymatrixScan()
        {
        //16個按鍵檢測
        uchar i = 0, j = 0;
        for (i = 0; i < 4; i++) //4行
        {
        for (j = 0; j < 4; j++) //4列
        {
        if (keysta[j] != keybackup[j]) //檢測第i行第j列按鍵是否有動作
        {
        if (keybackup[j] == 0) //若第i行第j列的按鍵的前一個狀態為0,則由0-1,即按鍵彈起
        {
        key = i * 4 + j;//按鍵定位
        }
        //備份當前按鍵的值,以備下一次比較
        keybackup[j] = keysta[j];
        }
        }
        }
        }

        /**********timer0 int****************/
        void timer0_int() interrupt 1 using 3
        {
        static uchar keybuf[4][4] = {
        {0xFF, 0xFF, 0xFF, 0xFF},
        {0xFF, 0xFF, 0xFF, 0xFF},
        {0xFF, 0xFF, 0xFF, 0xFF},
        {0xFF, 0xFF, 0xFF, 0xFF}
        };//16個按鍵的掃描緩沖區
        static uchar keyout = 0;//按鍵的列,即KeyOut1 - KeyOut4
        uchar i = 0;
        TH0 = 0xFC;
        TL0 = 0x67; //1ms

        refresh();

        //掃描第keyout列的按鍵的值
        keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KeyIn1;//將按鍵1的掃描值存入keybuf中
        keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KeyIn2;
        keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KeyIn3;
        keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KeyIn4; //每1ms掃描一列,4ms掃描四列,共掃描四位,設定掃描16ms,即每個按鍵掃描4次

        //更新消抖后按鍵的值
        for (i = 0; i < 4; i++) //4行, 一列4個按鍵
        {
        if ((keybuf[keyout] & 0x0F) == 0x00) //按鍵的緩沖區的低四位都是0,因為16ms只掃描了4次,移入了四位狀態值
        {
        keysta[keyout] = 0;//按鍵按下
        }
        else if ((keybuf[keyout] & 0x0F) == 0x0F) //按鍵的緩沖區的第四位都是1
        {
        keysta[keyout] = 1;//第keyout列第i行的按鍵彈起
        }
        }

        //列++
        keyout++;
        //keyout 0-3
        /*if (keyout >= 4)
        keyout = 0;
        */
        keyout &= 0x03;//當keyout到4則會等于3
        //通過keyout列數選中列
        switch (keyout)
        {
        case 0: KeyOut1 = 0; KeyOut4 = 1; KeyOut2 = 1; KeyOut3 = 1; //選中第一列,開發板上的第一行
        break;
        case 1: KeyOut2 = 0; KeyOut1 = 1; KeyOut3 = 1; KeyOut4 = 1;
        break;
        case 2: KeyOut3 = 0; KeyOut1 = 1; KeyOut2 = 1; KeyOut4 = 1;
        break;
        case 3: KeyOut4 = 0; KeyOut1 = 1; KeyOut2 = 1; KeyOut3 = 1;
        break;
        default:
        break;
        }
        }

         

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮