本人第一次發帖,如果有錯誤,歡迎大家指正!!!有關按鍵消抖的話題已經有很多人提出來了,在這里我把它進行一個總結。希望能幫助到大家!
1.按鍵抖動的原因
按鍵消抖通常的按鍵所用開關為機械彈性開關,當機械觸點斷開、閉合時,由于機械觸點的彈性作用,一個按鍵開關在閉合時不會馬上穩定地接通,在斷開時也不會一下子斷開。形成以下的波形
按鍵抖動圖1.png (36.85 KB, 下載次數: 180)
下載附件
2018-8-30 19:41 上傳
按鍵抖動圖2.png (20.68 KB, 下載次數: 190)
下載附件
2018-8-30 19:41 上傳
2.按鍵抖動的原理
按鍵抖動時間的長短由按鍵的機械特性決定,一般為5ms~10ms。這是一個很重要的時間參數,在很多場合都要用到。按鍵穩定閉合時間的長短則是由操作人員的按鍵動作決定的,一般為零點幾秒至數秒。鍵抖動會引起一次按鍵被誤讀多次。為確保單片機對按鍵的一次閉合僅作一次處理,必須去除鍵抖動。在鍵閉合穩定時讀取鍵的狀態,并且必須判別到按鍵釋放到穩定狀態后再去作處理。
3.按鍵消抖的方法
(1)硬件的消抖
利用電容的充放電特性來對抖動過程中產生的電壓毛刺進行平滑處理,從而實現消抖。在按鍵的兩端并聯一個0.1uf的電容。如按鍵消抖硬件圖
。
按鍵消抖硬件圖.png (42.93 KB, 下載次數: 175)
下載附件
2018-8-31 02:07 上傳
(2)軟件的消抖
1.延時消抖
剛接觸單片機的時候,最常用的方法,利用延時,消去抖動。代碼如下:
if(按鍵是否按下)
{ //按鍵按下的條件下
Deadly_1ms(5); // 延時消去抖動
if(按鍵是否按下)
{ //按鍵再次確認按下
//執行按鍵功能
while(按鍵是否松開);
}
}
注:按鍵詳細代碼見工程文件延時消抖
2.狀態機消抖
將按鍵的狀態分為三種 是否按下,是否抖動,是否彈起。檢測到按下時,轉向判斷是否抖動,并執行按鍵功能。等按鍵功能執行完了以后直接跳到按鍵是否彈起的狀態。等彈起后,再來判斷是否按下的狀態。
在按鍵的原理圖中,將1、2相接,則構成的是4*4的矩陣鍵盤,并且矩陣鍵盤與單片機的P3口相接。
//按鍵原理圖見上傳的圖片
按鍵模塊原理圖.png (38.31 KB, 下載次數: 170)
下載附件
2018-8-31 02:07 上傳
//設置按鍵的三種狀態及按鍵接口
#define KEY P3
#define key_state_0 0 //判斷是否按下
#define key_state_1 1 //判斷是否為抖動
#define key_state_2 2 //判斷是否彈起
unsigned char key_read(void)
{
static char key_state = key_state_0;
unsigned char key_return=0, key_press;
unsigned char key1,key2;
KEY=0xf0;
key1=KEY&0xf0;
KEY=0x0f;
key2=KEY&0x0f;
key_press =key1|key2; //讀取矩陣按鍵每個按鍵的狀態,存在key_press里
switch (key_state) // 判斷按鍵狀態
{
case key_state_0: //是否按下
if (key_press!=0xff) key_state = key_state_1; //沒有按鍵按下時則讀取出的0xff,若有不同說明有按鍵按下,則跳轉到判斷是否為抖動的狀態
break;
case key_state_1:
if (key_press !=0xff) //再次確認是否按下,防止因單片機的速度過快,導致誤判。
{
switch (key_press)//根據key_press的值來執行相對應的功能
{
case 0xee: key_return = 19; //這里的0xee是怎么的來的,簡單來推一下
case 0xed: key_return = 18; //單片機的P3口初始化輸出的是高電平,先將P3口輸出0xf0,如果有按鍵按下,則P3口中的高四位的某一位的電平會被拉低,此時記錄P3口的狀態(key1)
case 0xeb: key_return = 17; //讀取了高四位的電平,之后再來讀取低四位的電平(key2) ,之后 | 在一起得到key_press,得到的key_press中一定有兩位是0;
case 0xe7: key_return = 16;//舉例 : 當我按下s19時,key1 = 0xe0;(即P3^4 = 0,高四位的第一位電平被拉低),key2 = 0x0e;(即P3^0 = 0,低四位的第一位電平被拉低),這樣key_press = key_press =key1|key2 = 0xee;
case 0xde: key_return = 15;//以此類推
case 0xdd: key_return = 14;
case 0xdb: key_return = 13;
case 0xd7: key_return = 12;
case 0xbe: key_return = 11;
case 0xbd: key_return = 10;
case 0xbb: key_return = 9;
case 0xb7: key_return = 8;
case 0x7e: key_return = 7;
case 0x7d: key_return = 6;
case 0x7b: key_return = 5;
case 0x77: key_return = 4;
}
key_state = key_state_2; //這里跳轉到判斷彈起的狀態
}
else
key_state = key_state_0;
break;
case key_state_2:
if (key_press==0xff) key_state = key_state_0; //等待按鍵完全彈起
break;
}
return key_return;
}
注:具體用法見工程狀態機消抖
3.邏輯關系消抖
將按鍵的原理圖中,將2、3相接,則構成的是獨立鍵盤(s4,s5,s6,s7),并且獨立鍵盤與單片機的P3口的低四位相接,另一端與gnd相接。
利用邏輯關系 與&、或 | 、非 !、異或 ^,來消除抖動。先貼出源代碼:
unsigned char ReadData = KEYPORT^0xff;
Trg = ReadData & (ReadData ^ Cont);
Cont = ReadData;
Trg是判斷那個按鍵按下,Cont用來判斷長按、短按的;
分析: (1)沒有按鍵按下(初始值 Trg = 0,Cont = 0)
unsigned char ReadData = P3^0xff; => ReadData = 0xff ^0xff = 0x00;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x00 & (0x00 ^0x00) = 0x00;
Cont = ReadData; =>Cont = 0x00;
結果 :
ReadData = 0x00
Trg = 0x00
Cont = 0x00
(2) s4按下
剛按下時
unsigned char ReadData = P3^0xff; => ReadData = 0xf7 ^0xff = 0x08;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x08 & (0x08^0x00) = 0x08;
Cont = ReadData; =>Cont = 0x08;
抖動時
unsigned char ReadData = P3^0xff; => ReadData = 0xff ^0xff = 0x00;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x00 & (0x00^0x08) = 0x00;
Cont = ReadData; =>Cont = 0x00;
結果 :
剛按下時:
ReadData = 0x08
Trg = 0x08
Cont = 0x08
抖動時:
ReadData = 0x00
Trg = 0x00
Cont = 0x00
(3) s4長按
unsigned char ReadData = P3^0xff; => ReadData = 0xf7 ^0xff = 0x08;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x08 & (0x08 ^0x00) = 0x00;
Cont = ReadData; =>Cont = 0x08;
結果 :
ReadData = 0x08
Trg = 0x00
Cont = 0x08
(4) s4松開
unsigned char ReadData = P3^0xff; => ReadData = 0xff ^0xff = 0x00;
Trg = ReadData & (ReadData ^ Cont); =>Trg =0x08 & (0x08 ^0x00) = 0x00;
Cont = ReadData; =>Cont = 0x00;
結果 :
ReadData = 0x00
Trg = 0x00
Cont = 0x00
將上面的數據進行匯總、分析 | ReadData | Trg | Cont | 沒有按鍵按下 | 0x00 | 0x00 | 0x00 | s4剛按下 | 0x08 | 0x08 | 0x08 | s4有抖動時 | 0x00 | 0x00 | 0x00 | s4長按 | 0x08 | 0x00 | 0x08 | s4松開 | 0x00 | 0x00 | 0x00 |
Trg只有在按鍵剛按下時有不到等于0的值,因此我們檢測到Trg 不為0時,說明有按鍵按下;
Cont 只要有按鍵按下時,它的值就不為0,因此我們定時一段時間,來檢測Cont,,若不變,則按鍵時長按的狀態。
注:具體用法見工程邏輯關系消抖
到這里只是簡單的介紹了幾種按鍵消抖,還有很多方法沒有介紹,比如,中斷消抖,門電路消抖,計時消抖…,但萬變不離其中。學會了其中一種,其他的就自然懂了。
希望這篇帖子能幫助到大家。。!
0.png (40.24 KB, 下載次數: 186)
下載附件
2018-8-31 03:38 上傳
全部資料51hei下載地址(全部程序源碼):
按鍵.rar
(68.28 KB, 下載次數: 171)
2018-8-31 02:31 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|