新聞中心

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

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

        作者: 時間:2016-11-29 來源:網絡 收藏

        因為有了這個支持,那么按鍵處理就變得很爽了,下面看應用:
        應用一:一次觸發的按鍵處理
        假設PB0為蜂鳴器按鍵,按一下,蜂鳴器beep的響一聲。這個很簡單,但是大家以前是怎么做的呢?對比一下看誰的方便?
        #define KEY_BEEP 0x01
        void KeyProc(void)
        {
        if (Trg & KEY_BEEP) // 如果按下的是KEY_BEEP
        {
        Beep(); // 執行蜂鳴器處理函數
        }
        }
        怎么樣?夠和諧不?記得前面解釋說Trg的精粹是什么?精粹就是只會出現一次。所以你按下按鍵的話,Trg & KEY_BEEP 為“真”的情況只會出現一次,所以處理起來非常的方便,蜂鳴器也不會沒事亂叫,hoho~~~
        或者你會認為這個處理簡單,沒有問題,我們繼續。
        應用2:長按鍵的處理
        項目中經常會遇到一些要求,例如:一個按鍵如果短按一下執行功能A,如果長按2秒不放的話會執行功能B,又或者是要求3秒按著不放,計數連加什么什么的功能,很實際。不知道大家以前是怎么做的呢?我承認以前做的很郁悶。
        但是看我們這里怎么處理吧,或許你會大吃一驚,原來程序可以這么簡單
        這里具個簡單例子,為了只是說明原理,PB0是模式按鍵,短按則切換模式,PB1就是加,如果長按的話則連加(玩過電子表吧?沒錯,就是那個?。?br />#define KEY_MODE 0x01 // 模式按鍵
        #define KEY_PLUS 0x02 // 加
        void KeyProc(void)
        {
        if (Trg & KEY_MODE) // 如果按下的是KEY_MODE,而且你常按這按鍵也沒有用,
        { //它是不會執行第二次的哦 , 必須先松開再按下
        Mode++; // 模式寄存器加1,當然,這里只是演示,你可以執行你想
        // 執行的任何代碼
        }
        if (Cont & KEY_PLUS) // 如果“加”按鍵被按著不放
        {
        cnt_plus++; // 計時
        if (cnt_plus > 100) // 20ms*100 = 2S 如果時間到
        {
        Func(); // 你需要的執行的程序
        }
        }
        }
        不知道各位感覺如何?我覺得還是挺簡單的完成了任務,當然,作為演示用代碼。
        應用3:點觸型按鍵和開關型按鍵的混合使用
        點觸形按鍵估計用的最多,特別是單片機。開關型其實也很常見,例如家里的電燈,那些按下就不松開,除非關。這是兩種按鍵形式的處理原理也沒啥特別,但是你有沒有想過,如果一個系統里面這兩種按鍵是怎么處理的?我想起了我以前的處理,分開兩個非常類似的處理程序,現在看起來真的是笨的不行了,但是也沒有辦法啊,結構決定了程序。不過現在好了,用上面介紹的辦法,很輕松就可以搞定。
        原理么?可能你也會想到,對于點觸開關,按照上面的辦法處理一次按下和長按,對于開關型,我們只需要處理Cont就OK了,為什么?很簡單嘛,把它當成是一個長按鍵,這樣就找到了共同點,屏蔽了所有的細節。程序就不給了,完全就是應用2的內容,在這里提為了就是說明原理~~
        好了,這個好用的按鍵處理算是說完了。可能會有朋友會問,為什么不說延時消抖問題?哈哈,被看穿了。果然不能偷懶。下面談談這個問題,順便也就非常簡單的談談我自己用時間片輪辦法,以及是如何消抖的。
        延時消抖的辦法是非常傳統,也就是 第一次判斷有按鍵,延時一定的時間(一般習慣是20ms)再讀端口,如果兩次讀到的數據一樣,說明了是真正的按鍵,而不是抖動,則進入按鍵處理程序。
        當然,不要跟我說你delay(20)那樣去死循環去,真是那樣的話,我衷心的建議你先放下手上所有的東西,好好的去了解一下操作系統的分時工作原理,大概知道思想就可以,不需要詳細看原理,否則你永遠逃不出“菜鳥”這個圈子。當然我也是菜鳥。我的意思是,真正的單片機入門,是從學會處理多任務開始的,這個也是學校程序跟公司程序的最大差別。當然,本文不是專門說這個的,所以也不獻丑了。
        我的主程序架構是這樣的:
        volatile unsigned char Intrcnt;
        void InterruptHandle() // 中斷服務程序
        {
        Intrcnt++; // 1ms 中斷1次,可變
        }
        void main(void)
        {
        SysInit();
        while(1) // 每20ms 執行一次大循環
        {
        KeyRead(); // 將每個子程序都掃描一遍
        KeyProc();
        Func1();
        Funt2();


        while(1)
        {
        if (Intrcnt>20) // 一直在等,直到20ms時間到
        {
        Intrcnt="0";
        break; // 返回主循環
        }
        }
        }
        }
        貌似扯遠了,回到我們剛才的問題,也就是怎么做按鍵消抖處理。我們將讀按鍵的程序放在了主循環,也就是說,每20ms我們會執行一次KeyRead()函數來得到新的Trg 和 Cont 值。好了,下面是我的消抖部分:很簡單
        基本架構如上,我自己比較喜歡的,一直在用。當然,和這個配合,每個子程序必須執行時間不長,更加不能死循環,一般采用有限狀態機的辦法來實現,具體參考其它資料咯。
        懂得基本原理之后,至于怎么用就大家慢慢思考了,我想也難不到聰明的工程師們。例如還有一些處理,
        怎么判斷按鍵釋放?很簡單,Trg 和Cont都為0 則肯定已經釋放了。

        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 革吉县| 红安县| 福海县| 奈曼旗| 城固县| 卢湾区| 昌都县| 通道| 广平县| 且末县| 庄河市| 新河县| 安泽县| 都兰县| 湖南省| 友谊县| 新闻| 景泰县| 色达县| 海盐县| 延庆县| 株洲县| 精河县| 太和县| 西盟| 顺平县| 分宜县| 牟定县| 汽车| 修水县| 佛山市| 三原县| 澎湖县| 抚松县| 南丰县| 嘉定区| 潞城市| 育儿| 海原县| 日土县| 信宜市|