最近做一任務需要使用一個按鍵實現三種功能,分別是按鍵單擊功能,按鍵雙擊功能和按鍵長按功能,可能之前沒有接觸過這類按鍵復用情況,頂多也只是簡單識別單擊和長按,沒有想過雙擊以上按鍵功能,也是絞盡腦汁,想了半天,又上網看了些例程,算是對於按鍵的識別有點小小的了解,感覺這個功能挺實用,在此做個隨筆。
一、思路
1.識別長按操作思路:我們使用系統定時器定時,然后讓系統每過一段時間去掃描按鍵I/O口狀態,當掃描到按鍵按下I/O口狀態超過設定長按時間的閥值,就判定這次按鍵操作為“長按”操作;
2.識別單擊操作思路:當系統掃描按鍵按下的I/O口時間小於我們設定的長按閥值,這時就可能出現兩種情況,情況1.可能是單擊;情況2.可能是雙擊;首先我們來說情況1,單擊操作,這時我們可以檢測按鍵按下后,按鍵彈起的時間到下次按鍵按下的時間間隔,當按鍵按下彈起到下次按鍵按下的時間超過某個值,則我們判定這次操作為“單擊”操作;
3.識別雙擊操作思路:上面剛說的情況1,這次來說情況2,:雙擊操作,當我們檢測按鍵按彈起后在一定時間閥值內,又檢測到按鍵I/O口有電平變化,則我們判斷這次操作為“雙擊”操作
二、程序部分
unsigned char scan_key() { /* 值key_return如下: 1---------單擊 2---------雙擊 3---------長按 */ static unsigned char key_state=0; //按鍵狀態 static unsigned char state=0; static unsigned char time,time1,time2; static unsigned char key_up_flag=0; //按鍵彈起標志位 static unsigned char key_return; if(Key==0) //按鍵按下消抖 { delay(50); if(Key==0) { key_state=0; } } else { delay(50); //按鍵松開消抖 if(Key==1) { key_state=1; key_up_flag=0; } } if((state==0)&&(key_state==0)&&(key_up_flag==0)) //這里主要防止,按鍵在識別長按后,又會執行一遍單擊操作 { state=1; time=key_time; //記錄按鍵按下的時間為多少,做標記 } if(state==1) { time1=key_time; time2=time1-time; //計算按鍵按下時長 if(time2>50) //長按判斷 { state=2; } if(key_state==1) //按鍵彈起 { state=3; time=key_time; //標志什么時間按鍵彈起的 } } if(state==2) //長按 { state=0; //重置狀態 key_up_flag=1; key_return=3; } if((state==3)&&(key_up_flag==0)) { time1=key_time; time2=time1-time; //計算按鍵彈起后時間 if(time2>6) //判斷按鍵彈起后的時間,超過300ms,則說明為單擊 { state=0; key_return=1; } else if(key_state==0) //按鍵彈起后,300ms內又有按鍵按下 { state=4; } } if(state==4) { if(key_state==1) //按鍵彈起 { state=0; key_return=2; } } return key_return; } void timer0() interrupt 1 //定時器T0中斷函數入口 { TH0=0X9E; //初值重載 TL0=0X57; //定時50ms=50000us; 50000/2=25000 key_time++; //50MS++ }