最為精闢和實用的按鍵處理程式

2022-12-04 01:18:03 字數 4642 閱讀 3119

1.新型的按鍵掃瞄程式

不過我在網上遊逛了很久,也看過不少源程式了,沒有發現這種按鍵處理辦法的蹤跡,所以,我將他共享出來,和廣大同僚們共勉。我非常堅信這種按鍵處理辦法的便捷和高效,你可以移植到任何一種嵌入式處理器上面,因為c語言強大的可移植性。

同時,這裡面用到了一些分層的思想,在微控制器當中也是相當有用的,也是本文的另外乙個重點。

對於老鳥,我建議直接看那兩個表示式,然後自己想想就會懂的了,也不需要聽我後面的自吹自擂了,我可沒有班門弄斧的意思,hoho~~但是對於新手,我建議將全文看完。因為這是實際專案中總結出來的經驗,學校裡面學不到的東西。

以下假設你懂c語言,因為純粹的c語言描述,所以和處理器平台無關,你可以在mcs-51,**r,pic,甚至是arm平台上面測試這個程式效能。當然,我自己也是在多個專案用過,效果非常好的。

好了,工程人員的習慣,廢話就應該少說,開始吧。以下我以**r的mega8作為平台講解,沒有其它原因,因為我手頭上只有**r的板子而已沒有51的。用51也可以,只是晶元初始化部分不同,還有暫存器名字不同而已。

核心演算法:

unsignedchartrg;

unsignedcharcont;

voidkeyread(void)

完了。有沒有一種不可思議的感覺?當然,沒有想懂之前會那樣,想懂之後就會驚嘆於這演算法的精妙!!

下面是程式解釋:

trg(triger)代表的是觸發,cont(continue)代表的是連續按下。

1:讀portb的埠資料,取反,然後送到readdata臨時變數裡面儲存起來。

2:演算法1,用來計算觸發變數的。乙個位與操作,乙個異或操作,我想學過c語言都應該懂吧?trg為全域性變數,其它程式可以直接引用。

3:演算法2,用來計算連續變數。

看到這裡,有種「知其然,不知其所以然」的感覺吧?**很簡單,但是它到底是怎麼樣實現我們的目的的呢?好,下面就讓我們繞開雲霧看青天吧。

我們最常用的按鍵接法如下:**r是有內部上拉功能的,但是為了說明問題,我是特意用外部上拉電阻。那麼,按鍵沒有按下的時候,讀埠資料為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,同樣很好理解。

如果還是想不懂的話,可以自己演算一下那兩個表示式,應該不難理解的。

因為有了這個支援,那麼按鍵處理就變得很爽了,下面看應用:

應用一:一次觸發的按鍵處理

假設pb0為蜂鳴器按鍵,按一下,蜂鳴器beep的響一聲。這個很簡單,但是大家以前是怎麼做的呢?對比一下看誰的方便?

#definekey_beep0x01

voidkeyproc(void) }

怎麼樣?夠和諧不?記得前面解釋說trg的精粹是什麼?

精粹就是只會出現一次。所以你按下按鍵的話,trg&key_beep為「真」的情況只會出現一次,所以處理起來非常的方便,蜂鳴器也不會沒事亂叫,hoho~~~

或者你會認為這個處理簡單,沒有問題,我們繼續。

應用2:長按鍵的處理

專案中經常會遇到一些要求,例如:乙個按鍵如果短按一下執行功能a,如果長按2秒不放的話會執行功能b,又或者是要求3秒按著不放,計數連加什麼什麼的功能,很實際。不知道大家以前是怎麼做的呢?

我承認以前做的很鬱悶。

但是看我們這裡怎麼處理吧,或許你會大吃一驚,原來程式可以這麼簡單

這裡具個簡單例子,為了只是說明原理,pb0是模式按鍵,短按則切換模式,pb1就是加,如果長按的話則連加(玩過電子錶吧?沒錯,就是那個!)

#definekey_mode0x01//模式按鍵

#definekey_plus0x02//加

voidkeyproc(void)

if(cont&key_plus)//如果「加」按鍵被按著不放 }

} 不知道各位感覺如何?我覺得還是挺簡單的完成了任務,當然,作為演示用**。

應用3:點觸型按鍵和開關型按鍵的混合使用

點觸形按鍵估計用的最多,特別是微控制器。開關型其實也很常見,例如家裡的電燈,那些按下就不鬆開,除非關。這是兩種按鍵形式的處理原理也沒啥特別,但是你有沒有想過,如果乙個系統裡面這兩種按鍵是怎麼處理的?

我想起了我以前的處理,分開兩個非常類似的處理程式,現在看起來真的是笨的不行了,但是也沒有辦法啊,結構決定了程式。不過現在好了,用上面介紹的辦法,很輕鬆就可以搞定。

原理麼?可能你也會想到,對於點觸開關,按照上面的辦法處理一次按下和長按,對於開關型,我們只需要處理cont就ok了,為什麼?很簡單嘛,把它當成是乙個長按鍵,這樣就找到了共同點,遮蔽了所有的細節。

程式就不給了,完全就是應用2的內容,在這裡提為了就是說明原理~~

好了,這個好用的按鍵處理算是說完了。可能會有朋友會問,為什麼不說延時消抖問題?哈哈,被看穿了。

果然不能偷懶。下面談談這個問題,順便也就非常簡單的談談我自己用時間片輪辦法,以及是如何消抖的。

延時消抖的辦法是非常傳統,也就是第一次判斷有按鍵,延時一定的時間(一般習慣是20ms)再讀埠,如果兩次讀到的資料一樣,說明了是真正的按鍵,而不是抖動,則進入按鍵處理程式。

當然,不要跟我說你delay(20)那樣去死迴圈去,真是那樣的話,我衷心的建議你先放下手上所有的東西,好好的去了解一下作業系統的分時工作原理,大概知道思想就可以,不需要詳細看原理,否則你永遠逃不出「菜鳥」這個圈子。當然我也是菜鳥。我的意思是,真正的微控制器入門,是從學會處理多工開始的,這個也是學校程式跟公司程式的最大差別。

當然,本文不是專門說這個的,所以也不獻醜了。

我的主程式架構是這樣的:

volatileunsignedcharintrcnt;

voidinterrupthandle()//中斷服務程式

voidmain(void) }

} }貌似扯遠了,回到我們剛才的問題,也就是怎麼做按鍵消抖處理。我們將讀按鍵的程式放在了主迴圈,也就是說,每20ms我們會執行一次keyread()函式來得到新的trg和cont值。好了,下面是我的消抖部分:

很簡單基本架構如上,我自己比較喜歡的,一直在用。當然,和這個配合,每個子程式必須執行時間不長,更加不能死迴圈,一般採用有限狀態機的辦法來實現,具體參考其它資料咯。

懂得基本原理之後,至於怎麼用就大家慢慢思考了,我想也難不到聰明的工程師們。例如還有一些處理,

怎麼判斷按鍵釋放?很簡單,trg和cont都為0則肯定已經釋放了。

32按鍵紅外線發射 接收的實用遙控電路圖

圖示是完整的 32 按鍵紅外線發射 接收的實用遙控電路圖.發射部分使用 3 支紅外線發射管併聯,可以把發射距離提高到 10 公尺以上.接收部分使用一體化紅外線接收頭,微控制器為 sn2501 接收部分可以正確顯示按鍵碼 1 32 以及通過 2 只 hc154 電路低電平有效的 32 線分離輸出.顯示...

有關道德修養的精闢名言 至理名言 實用

人在智慧型上應當是明豁的,道德上應該是清白的,身體上應該是清潔的。下面是小編為您收集整理的有關道德修養的精闢名言,歡迎閱讀 1 感情有著極大的鼓舞力量,因此,它是一切道德行為的重要前提。凱洛夫 2 道德教育成功的 秘訣 在於,當乙個人還在少年時代的時候,就應該在巨集偉的社會生活背景上給他展示整個世界...

推和拉的實用教案

9 推和拉教學設計 教學目標 1 能 物體受到推和拉時會發生什麼變化。2 能夠在老師的指導下通過實驗體驗 出力有大小和方向,推和拉都是力。3 會按照製作方法說明製作紙蝙蝠。教學重點 感受推力和拉力。教學方法 教師講授與學生活動相結合的互動教學法。材料與用具 紙 彩筆 剪刀等。課時 1課時。教學過程 ...