新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 新型的按鍵掃描程序,僅三行程序

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

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

        上一頁(yè) 1 2 下一頁(yè)

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 自贡市| 河北区| 巴彦淖尔市| 玉林市| 德保县| 茶陵县| 湟源县| 迁西县| 徐水县| 启东市| 昌图县| 石狮市| 泰宁县| 河曲县| 康平县| 微博| 南京市| 化德县| 成安县| 高台县| 格尔木市| 岚皋县| 合阳县| 东至县| 大名县| 醴陵市| 吐鲁番市| 东明县| 定结县| 莱芜市| 托里县| 饶阳县| 舞钢市| 勐海县| 布尔津县| 五台县| 武川县| 江西省| 获嘉县| 河南省| 闵行区|