1 獨立按鍵的介紹
鍵盤分為編碼鍵盤和非編碼鍵盤。鍵盤上閉合鍵的識別由專用的硬件編碼器實現,並產生鍵編碼號或鍵值的稱為編碼鍵盤,如計算機鍵盤。而靠軟件編程來識別的鍵盤稱為非編碼鍵盤,在單片機組成的各種系統中,用的較多的是非編碼鍵盤。非編碼鍵盤又分為獨立鍵盤和行列式鍵盤(常說的矩陣鍵盤)。
單片機的IO口既可作為輸出也可作為輸入使用,當檢測按鍵時用的是它的輸入功能,我們把按鍵的一端接地,另一端與單片機的某個I/O口相連,開始時先給該IO口賦一高電平,然后讓單片機不斷地檢測該I/O口是杏變為低電平,當按鍵閉合時,即相當於該I/O口通過按鍵與地相連,變成低電平,程序一旦檢測到I/O口變為低電平則說明按鍵被按下,然后執行相應的指令。
注:自鎖開關:是一種常見的按鈕開關。在開關按鈕第一次按時,開關接通並保持,即自鎖,在開關按鈕第二次按時,開關斷開,同時按鈕彈出來。
2 機械按鍵的原理
由於機械觸點的彈性作用,一個按鍵開關在閉合時不會馬上就穩定的接通,在斷開時也不會一下子徹底斷開,而是在閉合和斷開的瞬間伴隨了一連串的抖動。由於單片機檢測 IO口速度非常快,超過彈片抖動的頻率,所以在檢測按鍵狀態時,要消除按鍵抖動的影響。一般認為,抖動不超過10ms。
為了避免這種現象而做的措施就是按鍵消抖,消抖方法分為:硬件消抖和軟件消抖。
(1)硬件消抖
在按鍵上並聯一個電容(RC電路),利用電容的充放電特性來對抖動過程中產生的電壓毛刺進行平滑處理,從而實現消抖。
(2)軟件消抖
當檢測到按鍵狀態變化后,先等待一個 10ms 左右的延時時間,讓抖動消失后再進行一次按鍵狀態檢測,如果與剛才檢測到的狀態相同,就可以確認按鍵已經穩定的動作了。
判斷按鍵一次按下的具體方法:
a)檢查到按鍵按下后,進行10-15ms延時,用於跳過這個抖動區域;
b)延時后再監測按鍵狀態,如果沒有按下表明是抖動或者干擾造成,如果仍舊按下,可以認為是真正的按下。並進行對應的操作。
3)同樣按鍵釋放后也要進行去抖動延時,延時后監測按鍵是否真正松開。
3 功能要求:通過開發板上的獨立按鍵K1-K4分別控制LED1-LED4指示燈亮滅。
4 硬件設計
5 軟件設計

1 #include "reg52.h" 2 3 typedef unsigned char u8; 4 typedef unsigned int u16; 5 6 //定義獨立按鍵控制管腳,輸入信號 7 sbit KEY1 = P3^1; 8 sbit KEY2 = P3^0; 9 sbit KEY3 = P3^2; 10 sbit KEY4 = P3^3; 11 12 //定義LED控制管腳,輸出信號 13 sbit LED1 = P2^0; 14 sbit LED2 = P2^1; 15 sbit LED3 = P2^2; 16 sbit LED4 = P2^3; 17 18 //使用宏定義獨立按鍵按下的鍵值,區別哪一個按鍵 19 #define KEY1_PRESS 1 20 #define KEY2_PRESS 2 21 #define KEY3_PRESS 3 22 #define KEY4_PRESS 4 23 #define KEY_UNPRESS 0 24 25 //延時函數,當ten_us=1時,大約延時10us 26 void delay_10us(u16 ten_us) 27 { 28 while(ten_us--); 29 } 30 31 //按鍵監測函數,用來監測四個按鍵中哪一個按鍵按下,它會返回一個值 32 u8 key_scan(u8 mode) 33 { 34 static u8 key = 1; //靜態變量,可以保持上一次的值 35 36 if(mode) key = 1; //mode=1,連續掃描按鍵(長按);mode=1, 單次掃描按鍵(短按) 37 38 if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0)) //任意按鍵按下 39 { 40 delay_10us(1000); //延遲10ns,濾除按下抖動過程 41 key = 0; 42 if(KEY1 == 0) 43 return KEY1_PRESS; //消抖后,再次監測到KEY1按下,返回按鍵1的碼值 44 else if(KEY2 == 0) 45 return KEY2_PRESS; 46 else if(KEY3 == 0) 47 return KEY3_PRESS; 48 else if(KEY4 == 0) 49 return KEY4_PRESS; 50 } 51 else if(KEY1==1 && KEY2==1 && KEY3==1 && KEY4==1) //沒有按鍵按下,同時都為高電平 52 { 53 key = 1; //為按鍵下次操作 54 } 55 return KEY_UNPRESS; 56 } 57 58 void main() 59 { 60 u8 key_value = 0; 61 62 while(1) 63 { 64 key_value = key_scan(0); 65 66 if(key_value == KEY1_PRESS) //監測到KEY1按下,控制LED1狀態翻轉 67 LED1 = !LED1; 68 else if(key_value == KEY2_PRESS) 69 LED2 = !LED2; 70 else if(key_value == KEY3_PRESS) 71 LED3 = !LED3; 72 else if(key_value == KEY4_PRESS) 73 LED4 = !LED4; 74 } 75 }
6 實驗現象
使用USB線將開發板和電腦連接成功后(電腦能識別開發板上CH340串口),把編譯后產生的.HEX文件燒入芯片內,現象如下:當按下K1鍵,LED1指示燈亮;再按下K1鍵,LED1指示燈滅,如此循環。
7 其他
獨立按鍵的四大要素:
“自鎖”:按鍵一旦進入到低電平,就要“自鎖”起來,避免不斷觸發按鍵,只有當按鍵被松開變成高電平的時候,才及時“解鎖”為下一次觸發做准備。
“消抖”:按鍵是一個機械觸點器件,在接觸的瞬間必然存在微觀上的機械抖動,反饋到電平的瞬間就是“高,低,高,低…”這種不穩定的電平狀態是一種干擾,但是,按鍵一旦按下去穩定了之后,這種狀態就消失,電平就一直保持穩定的低電平。消抖的本質就是濾波,要把這種接觸的瞬間抖動過濾掉,避免按鍵的“一按多觸發”。
“非阻塞”:在處理消抖的時候,必須用到延時,如果此時用阻塞的delay延時就會影響其它任務的運行效率,因此,用非阻塞的定時延時更加有優越性。
“清零式濾波”:在消抖的時候,有兩種境界,第一種境界是判斷兩次電平的狀態,中間插入“固定的時間”延時,這種方法前后一共判斷了兩次,第一次是識別到低電平就進入延時的狀態,第二次是延時后再確認一次是否繼續是低電平的狀態,這種方法的不足是,“固定的時間”全憑經驗值,但是不同的按鍵它們的抖動時間長度是不同的,除此之外,前后才判斷了兩次,在軟件的抗干擾能力上也弱了很多,“密碼等級”不夠高。第二種境界就是“清零式濾波”,“清零式濾波”非常巧妙,抗擾能力超強,它能自動過濾不同按鍵的“抖動時間”,然后再進入一個“穩定時間”的“N次識別判斷”,更加巧妙的是,在“抖動時間”和“穩定時間”兩者時間內,只要發現一次是高電平的干擾,就馬上自動清零計時器,重新開始計時。“穩定時間”一般取20ms到30ms之間,而“抖動時間”是隱藏的,在代碼上並沒有直接描寫出來,但是卻無形地融入了代碼之中,只有慢慢體會才能發現它的存在。
8 參考資料