目錄
一、相關(guān)說明
二、分析
三、模塊代碼
三、代碼講解
四、作者的話
一、相關(guān)說明
??????? 1.需要的資源:一個定時器,一個按鍵。
??????? 2.相關(guān)設(shè)置:利用定時器計時中斷,10ms進行一次按鍵掃描。
??????? 3.使用說明:定時器中斷的優(yōu)先級要設(shè)置高一點,相關(guān)的宏定義可以自行定義。
??????? 4.實現(xiàn)功能:區(qū)分單個按鍵的單擊,雙擊,長按。
??????? 5.規(guī)定:雙擊:2次按下的間隔不超過200ms屬于雙擊。
????????????????????? 單擊:第一次按下持續(xù)時間小于1s屬于單擊。
????????????????????? 長按:第一次按下持續(xù)時間不小于1s屬于長按。
??????? (時間長短可自己調(diào)整)
??????? 6.目標(biāo):幫助理解按鍵的狀態(tài)機。
二、分析
??????? 1.時間線分析和狀態(tài)概覽
??????? 2.狀態(tài)分析和編程思路
???????? 說明:一般按鍵有兩種狀態(tài),按下和彈起,這里將按鍵按下的狀態(tài)拆分為兩種狀態(tài),以長按1s的標(biāo)志觸發(fā)為斷點,拆分為按鍵按下到標(biāo)志觸發(fā)狀態(tài)和標(biāo)志觸發(fā)到按鍵彈起的狀態(tài)。而對于單擊和雙擊可直接理解為按下狀態(tài),只是形式上作了拆分。而且按下抖動的狀態(tài)實際編程中沒有編寫,有興趣的小伙伴可以嘗試添加。
那為什么要拆分按鍵按下的狀態(tài)?
定時器會10ms進行實時檢測。
長按標(biāo)志到時會實時清零,如果不拆分狀態(tài)只能等待按鍵彈起進入1狀態(tài),但此時長按標(biāo)志已被清零,系統(tǒng)錯亂,誤判為單擊。
要想長按標(biāo)志不被清零,就不能在按下狀態(tài)動態(tài)清零,所以只能設(shè)計為松手反饋。
而拆分狀態(tài)后可將1s前要做的事和1s后要做的事拆分開,1s到時即可實時反饋。
三、模塊代碼
1.相關(guān)宏
#define KEY GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5)
#define KEY_Up 1 //按鍵彈起
#define KEY_DownShake 2 //按下抖動
#define KEY_Down 3 //按鍵按下
#define KEY_wait 4 //等待狀態(tài)
#define SHORT_KEY 1 //短按反饋
#define LONG_KEY 2 //長按反饋
#define DOUBLE_CLICK 3 //雙擊反饋
#define FALSE 0
#define TRUE 1
2.函數(shù)主體
/**
* @brief KEY_Scan();// 按鍵檢測
* @note 按鍵檢測,返回單擊,雙擊,長按
* @param 無
* @retval 無
* @author 常州工學(xué)院電子協(xié)會22級團體
PS:key_return屬于外部全局變量,用于接受反饋信息
*/
void KEY_Scan(void)
{
//反饋系統(tǒng)
static uint8_t Click_Buf = FALSE; //第一次彈起標(biāo)志,用與區(qū)分雙擊的第一次按下和第二次按下
static uint8_t KEY_flag= FALSE;//標(biāo)志觸發(fā)判斷標(biāo)志位,用于在反饋結(jié)束后統(tǒng)一清零
static uint8_t Click = FALSE;//單擊判斷標(biāo)志位
static uint8_t Long_Press = FALSE; //長按判斷標(biāo)志位
static uint8_t Double_Click = FALSE;//雙擊判斷標(biāo)志位
//計時系統(tǒng)
//定時器10ms進入一次函數(shù)
static uint8_t Long_Cnt = 100;//長按計時時長1s
static uint8_t Twice_Cnt = 20;//雙擊間隔計時時長200ms
Long_Cnt--;
Twice_Cnt--;
//狀態(tài)系統(tǒng)
switch(key_state)
{
/*狀態(tài)1:空閑狀態(tài)(單擊)和按鍵彈起后(雙擊)*/
case KEY_Up:
{
if(KEY == 0)
{
key_state = KEY_Down;//切換到狀態(tài)3
Long_Cnt = 100;//長按計時開始
}
else
{
//判斷是否為按鍵彈起狀態(tài)
if(Click_Buf == TRUE)
{
//彈起時間超過200ms,雙擊判定時間失效,且一定不為長按,直接判斷為單擊
if(Twice_Cnt<=0)
{
KEY_flag = TRUE;
Click = TRUE;
}
}
}
break;
}
// /*狀態(tài)2:按下抖動(過渡狀態(tài))*/
// case KEY_DownShake:
// {
// if(KEY == 0)
// key_state = KEY_Down;//確認(rèn)按下,切換到狀態(tài)3
// break;
// }
/*狀態(tài)3:按鍵按下到長按標(biāo)志觸發(fā)狀態(tài)*/
case KEY_Down:
{
if(KEY == 1)
{
key_state = KEY_Up;//切換到狀態(tài)4
//不是長按操作,則判斷是不是雙擊操作
if(Long_Press == FALSE)
{
//雙擊檢測
//前面已經(jīng)單擊一次,這次就判斷為雙擊操作
if(Click_Buf == TRUE)
{
KEY_flag = TRUE;
Double_Click = TRUE;
}
else
{
//這是單擊或雙擊的第一次點擊,標(biāo)志位置1
Click_Buf = TRUE;
//雙擊計時器開始計時
Twice_Cnt = 20;
}
}
}
else
{
//長按檢測(一直在按下,第一次彈起不會觸發(fā))
if(Long_Press == FALSE&&Click_Buf == FALSE)
{
//1s時間到就判斷為長按
if(Long_Cnt<=0)
{
key_state = KEY_wait;//切換到狀態(tài)4
KEY_flag = TRUE;
Long_Press = TRUE;
}
}
}
break;
}
/*狀態(tài)4:標(biāo)志觸發(fā)到等待按鍵彈起狀態(tài)*/
case KEY_wait:
{
if(KEY == 1)
key_state = KEY_Up;//完成一次按鍵動作,切換到狀態(tài)1
break;
}
default:
key_state = KEY_Up;//默認(rèn)情況都切換到狀態(tài)1
break;
}
//標(biāo)志觸發(fā),反饋結(jié)果
//PS:key_return屬于外部全局變量,用于接受反饋信息
if(KEY_flag == TRUE)
{
//單擊動作
if(Click == TRUE)
key_return = SHORT_KEY;
//長按動作
else if(Long_Press == TRUE)
key_return = LONG_KEY;
//雙擊動作
else if(Double_Click == TRUE)
key_return = DOUBLE_CLICK;
//按鍵狀態(tài)位清零,為下一次按下準(zhǔn)備
KEY_flag= FALSE;
Click_Buf = FALSE;
Click = FALSE;
Long_Press = FALSE;
Double_Click = FALSE;
}
}
三、代碼講解
為了使代碼更加清晰,可讀性更強,我將按鍵狀態(tài)機的代碼做了分區(qū),分成了三個系統(tǒng),分別是反饋系統(tǒng),計時系統(tǒng),狀態(tài)系統(tǒng)。
理解要點:梳理好狀態(tài)之間的切換關(guān)系,特別關(guān)注按鍵按下和彈起在狀態(tài)機中是怎么檢測的。
難點:1.Click_Buf的實際意義不是按鍵按下的標(biāo)志,是按鍵彈起的標(biāo)志。
?????????? 2.要區(qū)分狀態(tài)和動作,按下既可以是狀態(tài)也可以是動作,空閑是一種狀態(tài),彈起是一種動作。
在理解代碼的時候可以把單擊,雙擊,長按的路線走幾遍,有助于理解。
四、作者的話
我們團隊在學(xué)習(xí)狀態(tài)機很痛苦,因為比較抽象難以理解,所以我們將學(xué)習(xí)經(jīng)驗分享,希望能對剛學(xué)習(xí)這方面內(nèi)容的人有所幫助。文章來源:http://www.zghlxwxcb.cn/news/detail-721949.html
本人自學(xué)小白,如果有紕漏和錯誤,希望大佬們多多指教,歡迎大家一起交流。文章來源地址http://www.zghlxwxcb.cn/news/detail-721949.html
到了這里,關(guān)于按鍵狀態(tài)機(實現(xiàn)單擊,長按,雙擊)的模塊分享的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!