8 6 微控制器按鍵消抖

2021-07-14 11:26:28 字數 2987 閱讀 4883

通常按鍵所用的開關都是機械彈性開關,當機械觸點斷開、閉合時,由於機械觸點的彈性作用,乙個按鍵開關在閉合時不會馬上就穩定的接通,在斷開時也不會一下子徹底斷開,而是在閉合和斷開的瞬間伴隨了一連串的抖動,如圖 8-10 所示。

圖 8-10  按鍵抖動狀態圖

按鍵穩定閉合時間長短是由操作人員決定的,通常都會在 100ms 以上,刻意快速按的話能達到 40-50ms 左右,很難再低了。抖動時間是由按鍵的機械特性決定的,一般都會在 10ms以內,為了確保程式對按鍵的一次閉合或者一次斷開只響應一次,必須進行按鍵的消抖處理。當檢測到按鍵狀態變化時,不是立即去響應動作,而是先等待閉合或斷開穩定後再進行處理。按鍵消抖可分為硬體消抖和軟體消抖。

硬體消抖就是在按鍵上併聯乙個電容,如圖 8-11 所示,利用電容的充放電特性來對抖動過程中產生的電壓毛刺進行平滑處理,從而實現消抖。但實際應用中,這種方式的效果往往不是很好,而且還增加了成本和電路複雜度,所以實際中使用的並不多。

圖 8-11  硬體電容消抖

在絕大多數情況下,我們是用軟體即程式來實現消抖的。最簡單的消抖原理,就是當檢測到按鍵狀態變化後,先等待乙個 10ms 左右的延時時間,讓抖動消失後再進行一次按鍵狀態檢測,如果與剛才檢測到的狀態相同,就可以確認按鍵已經穩定的動作了。將上乙個的程式稍加改動,得到新的帶消抖功能的程式如下。

#include

sbit

addr0 = p1^0;

sbit

addr1 = p1^1;

sbit

addr2 = p1^2;

sbit

addr3 = p1^3;

sbit

enled = p1^4;

sbit

key1 = p2^4;

sbit

key2 = p2^5;

sbit

key3 = p2^6;

sbit

key4 = p2^7;

unsigned

char

code

ledchar=;

void

delay

();void

main

()p0 = ledchar[cnt];

//計數值顯示到數碼管上

}backup = keybuf;

//更新備份為當前值,以備進行下次比較}}

}}/* 軟體延時函式,延時約 10ms */

void

delay

()

這個程式用了乙個簡單的演算法實現了按鍵的消抖。作為這種很簡單的演示程式,我們可以這樣來寫,但是實際做專案開發的時候,程式量往往很大,各種狀態值也很多, while(1)這個主迴圈要不停的掃瞄各種狀態值是否有發生變化,及時的進行任務排程,如果程式中間加了這種 delay 延時操作後,很可能某一事件發生了,但是我們程式還在進行 delay 延時操作中,當這個事件發生完了,程式還在 delay 操作中,當我們 delay 完事再去檢查的時候,已經晚了,已經檢測不到那個事件了。為了避免這種情況的發生,我們要盡量縮短 while(1)迴圈一次所用的時間,而需要進行長時間延時的操作,必須想其它的辦法來處理。

那麼消抖操作所需要的延時該怎麼處理呢?其實除了這種簡單的延時,我們還有更優異的方法來處理按鍵抖動問題。舉個例子:我們啟用乙個定時中斷,每 2ms 進一次中斷,掃瞄一次按鍵狀態並且儲存起來,連續掃瞄 8 次後,看看這連續 8 次的按鍵狀態是否是一致的。8 次按鍵的時間大概是 16ms,這 16ms 內如果按鍵狀態一直保持一致,那就可以確定現在按鍵處於穩定的階段,而非處於抖動的階段,如圖 8-12。

圖 8-12  按鍵連續掃瞄判斷

假如左邊時間是起始 0 時刻,每經過 2ms 左移一次,每移動一次,判斷當前連續的 8 次按鍵狀態是不是全 1 或者全 0,如果是全 1 則判定為彈起,如果是全 0 則判定為按下,如果0 和 1 交錯,就認為是抖動,不做任何判定。想一下,這樣是不是比簡單的延時更加可靠?

利用這種方法,就可以避免通過延時消抖占用微控制器執行時間,而是轉化成了一種按鍵狀態判定而非按鍵過程判定,我們只對當前按鍵的連續 16ms 的 8 次狀態進行判斷,而不再關心它在這 16ms 內都做了什麼事情,那麼下面就按照這種思路用程式實現出來,同樣只以k4 為例。

#include

sbit

addr0 = p1^0;

sbit

addr1 = p1^1;

sbit

addr2 = p1^2;

sbit

addr3 = p1^3;

sbit

enled = p1^4;

sbit

key1 = p2^4;

sbit

key2 = p2^5;

sbit

key3 = p2^6;

sbit

key4 = p2^7;

unsigned

char

code

ledchar=;

bitkeysta =1;

//當前按鍵狀態

void

main

()p0 = ledchar[cnt];

//計數值顯示到數碼管上

}//更新備份為當前值,以備進行下次比較

backup = keysta;}}

}/* t0 中斷服務函式,用於按鍵狀態的掃瞄並消抖 */

void

interrupttimer0

() interrupt 1

else

if(keybuf ==

0xff

)else

}

這個演算法是我們在實際工程中經常使用按鍵所總結的乙個比較好的方法,介紹給大家,今後都可以用這種方法消抖了。當然,按鍵消抖也還有其它的方法,程式實現更是多種多樣,大家也可以再多考慮下其它的演算法,拓展下思路。

微控制器之按鍵消抖

我們前面在電子中的學習中就接觸過按鍵,但是我們只清楚其電路圖代表的含義,卻不明白真正操作起來會遇到的一系列問題,由於機械觸點的彈性,乙個按鍵開關在閉合後不會馬上穩定接通,斷開時也不會馬上斷開,如果不處理的話,會導致按鍵識別為多下,故我們就來研究一下按鍵消抖 針對的是k1 k2 k3 實驗原理 這個電...

51微控制器按鍵消抖

二 矩陣鍵盤 define key state 0 0 判斷按鍵是否按下 define key state 1 1 判斷按鍵是否抖動 define key state 2 2 判斷按鍵是否彈起 define key input p3 define key mask 0x0f void key rea...

微控制器學習筆記 按鍵消抖

按鍵是我們學習微控制器時乙個重要的器件,我們在按下按鍵時,難免會一位手抖動或者接觸不穩定,但如果不消抖,按鍵按下的瞬間將會產生成百上千次按鍵有效的結果,最終的現象不可預料,所以有必要進行消抖。一 消抖原理 原理 使用定時器計時產生中斷,只要在一定次數的中斷內,按鍵按下有效的次數達到一定次數,就可以認...