新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 新型的按鍵掃描程序,僅三行程序

        新型的按鍵掃描程序,僅三行程序

        作者: 時間:2016-11-29 來源:網絡 收藏
        我在網上游逛了很久,也看過不少源程序了,沒有發現這種按鍵處理辦法的蹤跡,所以,我將他共享出來,和廣大同僚們共勉。我非常堅信這種按鍵處理辦法的便捷和高效,你可以移植到任何一種嵌入式處理器上面,因為C語言強大的可移植性。
        同時,這里面用到了一些分層的思想,在單片機當中也是相當有用的,也是本文的另外一個重點。
        對于老鳥,我建議直接看那兩個表達式,然后自己想想就會懂的了,也不需要聽我后面的自吹自擂了,我可沒有班門弄斧的意思,hoho~~但是對于新手,我建議將全文看完。因為這是實際項目中總結出來的經驗,學校里面學不到的東西。
        以下假設你懂C語言,因為純粹的C語言描述,所以和處理器平臺無關,你可以在MCS-51,AVR,PIC,甚至是ARM平臺上面測試這個程序性能。當然,我自己也是在多個項目用過,效果非常好的。
        好了,工程人員的習慣,廢話就應該少說,開始吧。以下我以AVR的MEGA8作為平臺講解,沒有其它原因,因為我手頭上只有AVR的板子而已沒有51的。用51也可以,只是芯片初始化部分不同,還有寄存器名字不同而已。
        核心算法:
        unsigned char Trg;
        unsigned char Cont;
        void KeyRead( void )
        {
        unsigned char ReadData = PINB^0xff; // 1
        Trg = ReadData & (ReadData ^ Cont); // 2
        Cont = ReadData; // 3
        }
        完了。有沒有一種不可思議的感覺?當然,沒有想懂之前會那樣,想懂之后就會驚嘆于這算法的精妙!!
        下面是程序解釋:
        Trg(triger) 代表的是觸發,Cont(continue)代表的是連續按下。
        1:讀PORTB的端口數據,取反,然后送到ReadData 臨時變量里面保存起來。
        2:算法1,用來計算觸發變量的。一個位與操作,一個異或操作,我想學過C語言都應該懂吧?Trg為全局變量,其它程序可以直接引用。
        3:算法2,用來計算連續變量。
        看到這里,有種“知其然,不知其所以然”的感覺吧?代碼很簡單,但是它到底是怎么樣實現我們的目的的呢?好,下面就讓我們繞開云霧看青天吧。
        我們最常用的按鍵接法如下:AVR是有內部上拉功能的,但是為了說明問題,我是特意用外部上拉電阻。那么,按鍵沒有按下的時候,讀端口數據為1,如果按鍵按下,那么端口讀到0。下面就看看具體幾種情況之下,這算法是怎么一回事。
        (1) 沒有按鍵的時候
        端口為0xff,ReadData讀端口并且取反,很顯然,就是 0x00 了。
        Trg = ReadData & (ReadData ^ Cont); (初始狀態下,Cont也是為0的)很簡單的數學計算,因為ReadData為0,則它和任何數“相與”,結果也是為0的。
        Cont = ReadData; 保存Cont 其實就是等于ReadData,為0;
        結果就是:
        ReadData = 0;
        Trg = 0;
        Cont = 0;
        (2) 第一次PB0按下的情況
        端口數據為0xfe,ReadData讀端口并且取反,很顯然,就是 0x01 了。
        Trg = ReadData & (ReadData ^ Cont); 因為這是第一次按下,所以Cont是上次的值,應為為0。那么這個式子的值也不難算,也就是 Trg = 0x01 & (0x01^0x00) = 0x01
        Cont = ReadData = 0x01;
        結果就是:
        ReadData = 0x01;
        Trg = 0x01;Trg只會在這個時候對應位的值為1,其它時候都為0
        Cont = 0x01;
        (3) PB0按著不松(長按鍵)的情況
        端口數據為0xfe,ReadData讀端口并且取反是 0x01 了。
        Trg = ReadData & (ReadData ^ Cont); 因為這是連續按下,所以Cont是上次的值,應為為0x01。那么這個式子就變成了 Trg = 0x01 & (0x01^0x01) = 0x00
        Cont = ReadData = 0x01;
        結果就是:
        ReadData = 0x01;
        Trg = 0x00;
        Cont = 0x01;
        因為現在按鍵是長按著,所以MCU會每個一定時間(20ms左右)不斷的執行這個函數,那么下次執行的時候情況會是怎么樣的呢?
        ReadData = 0x01;這個不會變,因為按鍵沒有松開
        Trg = ReadData & (ReadData ^ Cont) = 0x01 & (0x01 ^ 0x01) = 0 ,只要按鍵沒有松開,這個Trg值永遠為 0 !!!
        Cont = 0x01;只要按鍵沒有松開,這個值永遠是0x01!!
        (4) 按鍵松開的情況
        端口數據為0xff,ReadData讀端口并且取反是 0x00 了。
        Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) = 0x00
        Cont = ReadData = 0x00;
        結果就是:
        ReadData = 0x00;
        Trg = 0x00;
        Cont = 0x00;
        很顯然,這個回到了初始狀態,也就是沒有按鍵按下的狀態。
        總結一下,不知道想懂了沒有?其實很簡單,答案如下:
        Trg 表示的就是觸發的意思,也就是跳變,只要有按鍵按下(電平從1到0的跳變),那么Trg在對應按鍵的位上面會置一,我們用了PB0則Trg的值為0x01,類似,如果我們PB7按下的話,Trg 的值就應該為 0x80 ,這個很好理解,還有,最關鍵的地方,Trg 的值每次按下只會出現一次,然后立刻被清除,完全不需要人工去干預。所以按鍵功能處理程序不會重復執行,省下了一大堆的條件判斷,這個可是精粹哦!!Cont代表的是長按鍵,如果PB0按著不放,那么Cont的值就為 0x01,相對應,PB7按著不放,那么Cont的值應該為0x80,同樣很好理解。
        如果還是想不懂的話,可以自己演算一下那兩個表達式,應該不難理解的。

        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 江安县| 沾化县| 沅江市| 东莞市| 滨海县| 宁海县| 双桥区| 舒城县| 盐边县| 铜鼓县| 分宜县| 通辽市| 青海省| 北海市| 闽侯县| 阿鲁科尔沁旗| 阳新县| 尉犁县| 平度市| 宁南县| 溧水县| 酉阳| 江源县| 南丰县| 雅江县| 景洪市| 镶黄旗| 多伦县| 嵊州市| 夏邑县| 个旧市| 商南县| 高平市| 元江| 武定县| 黄石市| 鄂伦春自治旗| 承德县| 庄浪县| 自治县| 遂平县|