單片機按鍵“消抖”的思考

初學單片機時,講到了一個按鍵“消抖”概念,視屏教程中只是說到要確定按鍵是不是真正按下,所以需要加一個延時來判斷。

附上延時消抖程序代碼:
代碼1

void keypros()
{
	if(k1==0)		  //檢測按鍵K1是否按下
	{	
		delay(1000);   //消除抖動 一般大約10ms
		if(k1==0)	 //再次判斷按鍵是否按下
		{
			                          //此處添加相應操作
		}
		while(!k1);	 //檢測按鍵是否鬆開
	}		
}

前不久,又瞭解到另外兩個按鍵消抖的代碼

狀態機消抖:
代碼2

#define key_input P3
#define key_state_0  0  //判斷是否按下
#define key_state_1  1 //判斷是否爲抖動
#define key_state_2  2 //判斷是否彈起

unsigned char t0count;
char key_value; 
  
char read_key(void) 
{ 
 static char key_state = 0; 
 char key_press, key_return = 0; 
 key_press = key_input&key_mask; 
 switch (key_state) 
{ 	
   case key_state_0:     
   if (key_press!=key_mask) key_state = key_state_1; 
   break; 
	 
   case key_state_1:    
   if (key_press!=key_input&key_mask) 
   { 
  	 if(key_press==0x0e) key_return = 1;  //S7
		 if(key_press==0x0d) key_return = 2;  //S6
		 if(key_press==0x0b) key_return = 3;  //S5
		 if(key_press==0x07) key_return = 4;  //S4
  	 key_state = key_state_2;  
   } 
   else 
   	 key_state = key_state_0;  
   break;  
   case key_state_2: 
   if (key_press==0x0f) key_state = key_state_0; 
   break; 
} 
return key_return; 
} 

void tm0_isr() interrupt 1
{
	TL0 = 0x18;		//設置定時初值
	TH0 = 0xFC;		//設置定時初值
	t0count++;
	if(t0count>=2)
	{
		t0count=0;
		key_value=read_key();
	}
}
...
if(key_value==...)
{
   //對於操作
}

三行代碼消抖:
代碼2

#define KEYPORT P3

typedef unsigned char u8;

u8 Trg;
u8 Cont;
u8 t0count;

void Read_key()
{
	u8 readdata=KEYPORT^0xff;                   //核心代碼1
	Trg=readdata&(readdata^Cont);              //核心代碼2
	Cont=readdata;                             //核心代碼3
}

void tm0_isr() interrupt 1
{
	TL0 = 0x18;		//設置定時初值
	TH0 = 0xFC;		//設置定時初值
	t0count++;
	if(t0count>=10)
	{
		t0count=0;
		Read_key();
	}
}
...
if(Trg==...)    //短按
{
      //對應操作
}

if(Cont==..)   //長按
{
      //對應操作
}

三種方法爲什麼都可以“消抖”?
這一問題引起了我的思考。

於是我查詢了什麼是按鍵抖動:按鍵抖動通常的按鍵所用開關爲機械彈性開關,當機械觸點斷開、閉合時,由於機械觸點的彈性作用,一個按鍵開關在閉合時不會馬上穩定地接通,在斷開時也不會一下子斷開。因而在閉合及斷開的瞬間均伴隨有一連串的抖動。

如下圖:
在這裏插入圖片描述
由於單片機的運行速度非常快,按下一次按鍵,可能在A點檢測到一次低電平,在B點檢測到一次高電平,在C點又檢測到一次低電平。同時抖動是隨機,不可測的。那麼按下一次按鍵,抖動可能對會讓單片機誤以爲按下多次按鍵。

延時消抖

最簡單的消抖原理,就是當檢測到按鍵狀態變化後,先等待一個 10ms 左右的延時時間,讓抖動消失後再進行一次按鍵狀態檢測,如果與剛纔檢測到的狀態相同,就可以確認按鍵已經穩定的動作了。

狀態機消抖

與延時消抖大同小異,間隔10ms檢測一次按鍵電位變化,狀態0時檢測到有按鍵電位變化就進入狀態1,狀態1再來確認是否還有變化,有則是按下按鍵。但是由於是利用了定時器,所以在間隔等待10ms時單片機仍可以進行其他進程。

三行代碼消抖

真的佩服。
說起來與狀態機消抖原理差不多也是利用定時器間隔10ms檢測一次按鍵。但是構思非常巧妙。
當沒有按鍵按下時,Trg與Cont均爲0x00。
當單片機執行到此程序且按鍵按下時(假設P3^0按下),Trg與Cont均爲0x01。
當單片機再次執行到此程序且按鍵按下時(假設P3^0按下),Trg爲0x00,Cont爲0x01。
而當按鍵釋放,再次檢測時,Trg與Cont又均爲0x00。(恢復到沒有按鍵按下狀態)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章