按鍵是一種電子開關,使用時,按下按鈕,則開關接通,鬆開手時, 開關斷開。開發板上使用的按鍵及內部簡易圖如下圖所示:
按鍵管腳兩端距離長的表示預設是導通狀態(1、2),距離短的預設是斷開狀態(1、3), 如果按鍵按下,初始導通狀態變為斷開,初始斷開狀態變為導通。 通常的按鍵所用開關為機械彈性開關,當機械觸點斷開、閉合時,電壓訊號如下圖所示:
由於機械點的彈性作用,按鍵開關在閉合時不會馬上穩定的接通,在斷開時也不會一下子斷開,因而在閉合和斷開的瞬間均伴隨著一連串的抖動。抖動時間的長短由按鍵的機械特性決定的,一般為 5ms 到 10ms。按鍵穩定閉合時間的長短則由操作人員的按鍵動作決定的,一般為零點幾秒至數秒。按鍵抖動會引起按鍵被誤讀多次。為了確保 CPU 對按鍵的一次閉合僅作一次處理,必須進行消抖。
按鍵消抖有兩種方式,一種是硬體消抖,另一種是軟體消抖。為了使電路更加簡單,通常採用軟體消抖。本文使用的開發板也是採用軟體消抖。通常而言,一個簡單的按鍵消抖就是先讀取按鍵的狀態,如果讀取到按鍵按下之後,延時 10ms,再次讀取按鍵的狀態,如果按鍵還是按下狀態,那麼說明按鍵已經按下。其中延時 10ms 就是軟體消抖處理。至於硬體消抖,此處不多做贅述。微控制器常用的軟體去抖動方法:
- 先設定 IO 口為高電平(由於開發板 IO 都有上拉電阻,所以預設 IO 為高電平)
- 讀取 IO 口電平確認是否有按鍵按下。
- 如有 IO 電平為低電平後,延時幾個毫秒。
- 再讀取該 IO 電平,如果仍然為低電平,說明按鍵按下。
- 執行按鍵控制程式。
獨立按鍵電路構成是由各個按鍵的一個管腳連線在一起接地,按鍵其他引腳分別接到微控制器 IO 口。
微控制器的 IO 口既可作為輸出也可作為輸入使用,當檢測按鍵時用的是它的輸入功能,獨立按鍵的一端接地, 另一端與微控制器的 I/O 口相連,開始時先給該 IO 口賦一高電平,然後讓微控制器不斷地檢測該 I/O 口是否變為低電平,當按鍵閉合時,即相當於該 I/O 口通過按鍵與地相連,變成低電平,程 序一旦檢測到 I/O 口變為低電平則說明按鍵被按下,然後執行相應的指令。
使用到硬體資源如下:
- LED 模組中 D1 指示燈
- K1 按鍵
獨立按鍵模組電路如下圖所示:
由上圖可知,該模組電路是獨立的,8 個獨立按鍵的控制管腳並未直接連線到 51 微控制器的 IO 上,而是連線到 JP1 端子上,所以使用任意微控制器管腳都可以,這裡使用 P3.0 口來檢測 K1 按鍵,使用 P2.0 管腳控制 D1 指示燈。
KEY_SCAN 函數帶一個形參 mode,該引數用來設定是否連續掃描按鍵,如果 mode 為 0,只能操作一次按鍵,只有當按鍵鬆開後才能觸發下次的掃描,這樣做的好處是可以防止按下一次出現多次觸發的情況。如果 mode 為 1,函數是支援連續掃描的,即使按鍵未鬆開,在函數內部有 if(mode==1)這條判斷語句,因 此 key 始終是等於 1 的,所以可以連續掃描按鍵,當按下某個按鍵,會一直返回這個按鍵的鍵值,這樣做的好處是可以很方便實現連按操作。
#include "reg52.h"
typedef unsigned int u16;//使用關鍵字 typedef 對系統預設資料型別 unsigned int 重新命名
typedef unsigned char u8;
/*定義獨立按鍵的控制腳*/
sbit KEY1=P3^1;
sbit KEY2=P3^2;
sbit KEY3=P3^3;
sbit KEY4=P3^4;
/*定義LED控制腳*/
sbit LED1=P2^1;
sbit LED2=P2^2;
sbit LED3=P2^3;
sbit LED4=P2^4;
/*使用宏定義獨立按鍵按下的鍵值*/
#define KEY1_PRESS 1 //K1按下
#define KEY2_PRESS 2 //K2按下
#define KEY3_PRESS 3 //K3按下
#define KEY4_PRESS 4 //K4按下
#define KEY_UNPRESS 0 //未有按鍵按下
void delay_10us(u16 ten_us)//延時函數,ten_us=1 時,大約延時 10us
{
while(ten_us--);
}
u8 KEY_SCAN(u8 mode)//檢測獨立按鍵是否按下,按下則返回對應鍵值給主函數
{
static u8 key=1;
if(mode) //連續掃描按鍵,防止按鍵按下無效
key=1;
if(key==1&&(KEY1==0||KEY2==0||KEY2==0||KEY3==0||KEY4==0)) //從此處開始做消抖處理,先第一次確認是否有按鍵按下
{
delay_10us(1000);//消抖
key=0;
if(KEY1==0) //再次確認是哪個按鍵按下,消抖處理結束
return KEY1_PRESS;
else if(KEY2==0)
return KEY2_PRESS;
else if(KEY3==0)
return KEY3_PRESS;
else if(KEY4==0)
return KEY4_PRESS;
}
else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
{
key=1;
}
return KEY_UNPRESS;
}
void main(void) //主函數
{
u8 DL_LED=0;
while(1)
{
DL_LED=KEY_SCAN(0); //接收函數返回的獨立按鍵按下的鍵值,用這個值來確定點亮那個LED燈
if(DL_LED==1) //檢測按鍵K1是否按下
LED1=!LED1; //LED1狀態翻轉,剛開始第一次按下按鍵,LED1埠輸出高電平,LED點亮 ,第二次按下時,狀態翻轉,輸出低電平
if(DL_LED==2) //檢測按鍵K2是否按下
LED2=!LED2; //LED2狀態翻轉
if(DL_LED==3) //檢測按鍵K3是否按下
LED3=!LED3; //LED3狀態翻轉
if(DL_LED==4) //檢測按鍵K4是否按下
LED4=!LED4; //LED4狀態翻轉
}
}
按下「獨立按鍵」模組中相應按鍵,控制對應的LED指示燈亮滅。