在使用按鍵時,我們想按一次按鍵,但在實際中卻經(jīng)常發(fā)現(xiàn)我們要的”一次“,實際上去并不是”一次“而可能是多次。為什么呢?這是因為,我們使用的機械按鍵,在我們按下時,并非只是接觸一次,因為存在機械抖動,導致接觸多次。因此,按鍵檢測去抖動就很有必要了。下面,我就向大家介紹按鍵去抖動的方法。
一、STC15W408AS按鍵電路
二、按鍵按下和松開時的波形
下面的圖形中顯示的是按鍵按下和松開時的理想狀態(tài)和實際狀態(tài)。
三、按鍵去抖動方法
理想波形:沒有按下為高電平,按下之后為低電平,松開之后又為高電平。
實際波形:按下之后,存在機械抖動,需要過一段時間才會穩(wěn)定成低電平,然后,松開時又會產(chǎn)生機械抖動。機械式按鍵在按下或者釋放時,由于機械彈性的影響,通常會伴隨有一定的時間觸電機械抖動,然后其觸電才穩(wěn)定下來。在觸點抖動期間檢測按鍵的通與斷,可能會導致錯誤,也就是有可能被認為進行了多次操作,這種情況是不允許出現(xiàn)的。
因此,在單片機檢測鍵盤是否按下都要加上去抖動操作,按鍵少時,可采用硬件消抖,按鍵較多時,采用軟件消抖。
我們在編寫單片機的按鍵檢測程序時,一般在檢測按下時加入去抖動延時(10~20ms即可),也就是當檢測到按鍵輸入口是低電平時,延時20MS再檢測一次按鍵的狀態(tài)是不是還是低電平。如果還是低電平,則認為按鍵被真正按下一次。
四、按鍵檢測去抖動關鍵代碼
if(!GetKey_High()) //如果檢測到按鍵低電平
{
Delay20ms(); //延時20MS
if(!GetKey_High()) //如果還是檢測到按鍵低電平
{
bKeyDown=TRUE; //確認按鍵已按下
mNum++; //按鍵次數(shù)加1
}
while(!GetKey_High()); //等待按鍵松開
}
* //1MS定時中斷函數(shù)Timer0_ISR()
void Timer0_ISR (void) interrupt 1
{
if(mDelay >0)//如果mDelay >0
{
mDelay--; //則中斷到來時,mDelay減1
}
}
* //20MS延時函數(shù)Delay20ms()
void Delay20ms(void)
{
mDelay=20; //設置mDelay的值為20
while(mDelay >0); //等待mDelay在中斷中減到0
}
* //500MS延時函數(shù)Delay500ms()
void Delay500ms(void)
{
mDelay=500;
while(mDelay >0);
}
五、本例完整源程序
#define FOSC 11059200L
#define T1MS (65536-FOSC/1000) // 1 T模式
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
#define TRUE 1
#define FALSE 0
#define Pin_LED P32
#define Pin_LED_M1 P3M1
#define Pin_LED_M0 P3M0
#define Pin_LED_BIT BIT2
#define PinLed_High() Pin_LED=1
#define PinLed_Low() Pin_LED=0
#define Pin_KEY P12
#define Pin_KEY_M1 P1M1
#define Pin_KEY_M0 P1M0
#define Pin_KEY_BIT BIT2
#define GetKey_High() Pin_KEY==1
#define BOOL unsigned char
#define UINT unsigned int
void PinLED_DirOut(void);
void PinKEY_DirIn(void);
void Timer0_Init(void);
void Delay20ms(void);
void Delay500ms(void);
void LedFlash(UINT num);
BOOL bKeyDown=FALSE;
UINT mDelay=0;
UINT mNum=0;
void main(void)
{
PinKEY_DirIn();
PinLED_DirOut();
PinLed_High();
Timer0_Init();
while(TRUE)
{
if(!GetKey_High())
{
Delay20ms();
if(!GetKey_High())
{
mNum++;
bKeyDown=TRUE;
}
while(!GetKey_High());
}
if(bKeyDown)
{
bKeyDown=FALSE;
LedFlash(mNum);
}
}
}
void PinKEY_DirIn(void)
{
Pin_KEY_M1 &=~Pin_KEY_BIT;
Pin_KEY_M0 &=~Pin_KEY_BIT;
}
void PinLED_DirOut(void)
{
Pin_LED_M1 &=~Pin_LED_BIT;
Pin_LED_M0 |=Pin_LED_BIT;
}
void Timer0_Init(void)
{
AUXR |= 0x80; //定時器0為1T模式
TMOD = 0x00; //設置定時器為模式0(16位自動重裝載)
TL0 = T1MS; //初始化計時值
TH0 = T1MS > > 8;
TR0 = 1; //定時器0開始計時
ET0 = 1; //使能定時器0中斷
EA = 1;
}
// 1ms
void Timer0_ISR (void) interrupt 1
{
if(mDelay >0)
{
mDelay--;
}
}
void Delay20ms(void)
{
mDelay=20;
while(mDelay >0);
}
void Delay500ms(void)
{
mDelay=500;
while(mDelay >0);
}
//為了方便檢驗效果,我寫了下面這個LED閃動函數(shù),第1次按下,LED閃動1次,第2次按下,LED閃動2次,依次類推。
void LedFlash(UINT num)
{
UINT i;
for(i=0;i< num;i++)
{
PinLed_Low();
Delay500ms();
PinLed_High();
Delay500ms();
}
}
-
單片機
+關注
關注
6037文章
44558瀏覽量
635217 -
去抖動
+關注
關注
0文章
2瀏覽量
6343 -
按鍵電路
+關注
關注
1文章
35瀏覽量
21774 -
按鍵檢測
+關注
關注
0文章
23瀏覽量
4836
發(fā)布評論請先 登錄
相關推薦
評論