在使用按鍵時(shí),我們想按一次按鍵,但在實(shí)際中卻經(jīng)常發(fā)現(xiàn)我們要的”一次“,實(shí)際上去并不是”一次“而可能是多次。為什么呢?這是因?yàn)椋覀兪褂玫?a href="http://www.xsypw.cn/v/tag/1472/" target="_blank">機(jī)械按鍵,在我們按下時(shí),并非只是接觸一次,因?yàn)榇嬖跈C(jī)械抖動(dòng),導(dǎo)致接觸多次。因此,按鍵檢測去抖動(dòng)就很有必要了。下面,我就向大家介紹按鍵去抖動(dòng)的方法。
一、STC15W408AS按鍵電路
二、按鍵按下和松開時(shí)的波形
下面的圖形中顯示的是按鍵按下和松開時(shí)的理想狀態(tài)和實(shí)際狀態(tài)。
三、按鍵去抖動(dòng)方法
理想波形:沒有按下為高電平,按下之后為低電平,松開之后又為高電平。
實(shí)際波形:按下之后,存在機(jī)械抖動(dòng),需要過一段時(shí)間才會(huì)穩(wěn)定成低電平,然后,松開時(shí)又會(huì)產(chǎn)生機(jī)械抖動(dòng)。機(jī)械式按鍵在按下或者釋放時(shí),由于機(jī)械彈性的影響,通常會(huì)伴隨有一定的時(shí)間觸電機(jī)械抖動(dòng),然后其觸電才穩(wěn)定下來。在觸點(diǎn)抖動(dòng)期間檢測按鍵的通與斷,可能會(huì)導(dǎo)致錯(cuò)誤,也就是有可能被認(rèn)為進(jìn)行了多次操作,這種情況是不允許出現(xiàn)的。
因此,在單片機(jī)檢測鍵盤是否按下都要加上去抖動(dòng)操作,按鍵少時(shí),可采用硬件消抖,按鍵較多時(shí),采用軟件消抖。
我們在編寫單片機(jī)的按鍵檢測程序時(shí),一般在檢測按下時(shí)加入去抖動(dòng)延時(shí)(10~20ms即可),也就是當(dāng)檢測到按鍵輸入口是低電平時(shí),延時(shí)20MS再檢測一次按鍵的狀態(tài)是不是還是低電平。如果還是低電平,則認(rèn)為按鍵被真正按下一次。
四、按鍵檢測去抖動(dòng)關(guān)鍵代碼
if(!GetKey_High()) //如果檢測到按鍵低電平
{
Delay20ms(); //延時(shí)20MS
if(!GetKey_High()) //如果還是檢測到按鍵低電平
{
bKeyDown=TRUE; //確認(rèn)按鍵已按下
mNum++; //按鍵次數(shù)加1
}
while(!GetKey_High()); //等待按鍵松開
}
* //1MS定時(shí)中斷函數(shù)Timer0_ISR()
void Timer0_ISR (void) interrupt 1
{
if(mDelay >0)//如果mDelay >0
{
mDelay--; //則中斷到來時(shí),mDelay減1
}
}
* //20MS延時(shí)函數(shù)Delay20ms()
void Delay20ms(void)
{
mDelay=20; //設(shè)置mDelay的值為20
while(mDelay >0); //等待mDelay在中斷中減到0
}
* //500MS延時(shí)函數(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; //定時(shí)器0為1T模式
TMOD = 0x00; //設(shè)置定時(shí)器為模式0(16位自動(dòng)重裝載)
TL0 = T1MS; //初始化計(jì)時(shí)值
TH0 = T1MS > > 8;
TR0 = 1; //定時(shí)器0開始計(jì)時(shí)
ET0 = 1; //使能定時(shí)器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);
}
//為了方便檢驗(yàn)效果,我寫了下面這個(gè)LED閃動(dòng)函數(shù),第1次按下,LED閃動(dòng)1次,第2次按下,LED閃動(dòng)2次,依次類推。
void LedFlash(UINT num)
{
UINT i;
for(i=0;i< num;i++)
{
PinLed_Low();
Delay500ms();
PinLed_High();
Delay500ms();
}
}
-
單片機(jī)
+關(guān)注
關(guān)注
6037文章
44558瀏覽量
635233 -
去抖動(dòng)
+關(guān)注
關(guān)注
0文章
2瀏覽量
6343 -
按鍵電路
+關(guān)注
關(guān)注
1文章
35瀏覽量
21774 -
按鍵檢測
+關(guān)注
關(guān)注
0文章
23瀏覽量
4836
發(fā)布評論請先 登錄
相關(guān)推薦
評論