本帖最后由 田裕中 于 2021-11-20 14:32 編輯
按鍵的多功能觸發(fā)
概述
本文所介紹的按鍵是基于STM32F系列獨(dú)立按鍵模式,目的是使單個(gè)按鍵具備多種按鍵效果。常見的有單擊、長按等功能。為拓展功能多樣性,對(duì)按鍵驅(qū)動(dòng)進(jìn)行設(shè)計(jì),實(shí)現(xiàn)按鍵功能的多樣性,本設(shè)計(jì)已達(dá)到的功能包括單擊、長按、雙擊、三擊、四擊......等,剩余可由用戶自行添加。按鍵消息通過消息隊(duì)列進(jìn)行傳遞。
按鍵對(duì)象封裝 類似于面向?qū)ο笾蓄惖姆庋b,該結(jié)構(gòu)體包含按鍵觸發(fā)函數(shù)、硬件接口、計(jì)數(shù)器及按鍵狀態(tài)標(biāo)記。 typedef void (*KEYFUNC) (uint16_t tick_cnt_ptr);
該定義為:聲明一個(gè)函數(shù)指針,指向一個(gè)參數(shù)為uint16_t 類型的變量的函數(shù)。
typedef struct
{
KEYFUNC key_function;
KEYFUNC fast_key_fun;
GPIO_TypeDef* GPIOx;
uint16_t Pin;
uint16_t key_cnt;
uint16_t Status;
} KEYSTATUS;
按鍵事件注冊 注冊按鍵的觸發(fā)函數(shù)、初始狀態(tài)State、按鍵初始化等。聲明兩個(gè)枚舉變量進(jìn)行按鍵的開啟與關(guān)閉(DISABLE_KEY、GENERAL_KEY)。 enum
{
DISABLE_KEY,
GENERAL_KEY
};申明一個(gè)map對(duì)象,為每個(gè)按鍵引用驅(qū)動(dòng)類:
KEYSTATUS io_key_map[IOKEY_NUM];在此函數(shù)開啟之前確保按鍵引腳已成功初始化。
void ap_peripheral_key_register(INT8U type)
{
io_key_num = 0;
switch(type)
{
case DISABLE_KEY:
{
//disable all key
}
break;
case GENERAL_KEY:
{
#if IO_KEY
io_key_map[io_key_num].GPIOx = KEY_Pin_GPIO_Port;
io_key_map[io_key_num].Pin = KEY_Pin_Pin;
io_key_map[io_key_num].key_function = ap_peripheral_io_key_exe;
//io_key_map[io_key_num].fast_key_fun = ap_peripheral_io_fast_key_exe;
io_key_map[io_key_num].key_cnt = 0;
io_key_map[io_key_num++].Status = 0;
#endif
#if CHARGE
io_key_map[io_key_num].GPIOx = STAT_CHG_GPIO_Port;
io_key_map[io_key_num].Pin = STAT_CHG_Pin;
io_key_map[io_key_num].key_function = ap_peripheral_charge_exe;
io_key_map[io_key_num].key_cnt = 0;
io_key_map[io_key_num++].Status = 0;
#endif
#if IO_USB
io_key_map[io_key_num].GPIOx = USB_CH_GPIO_Port;
io_key_map[io_key_num].Pin = USB_CH_Pin;
io_key_map[io_key_num].key_function = ap_peripheral_io_usb_exe;
io_key_map[io_key_num].key_cnt = 0;
io_key_map[io_key_num++].Status = 0;
#endif
}
break;
default:
ap_peripheral_key_register(DISABLE_KEY);
break;
}
}
按鍵回調(diào)函數(shù) 按鍵事件注冊后,每個(gè)按鍵引腳功能編寫對(duì)應(yīng)的回調(diào)函數(shù),為事件注冊使用。說明:按鍵消息是基于消息隊(duì)列進(jìn)行消息傳遞,可根據(jù)用戶的需求自行設(shè)計(jì)回調(diào)函數(shù)功能! 第一個(gè)按鍵回調(diào)函數(shù): void ap_peripheral_io_key_exe(INT16U tick_cnt_ptr)
{
if(tick_cnt_ptr >= LONG_KEY_TIME)
{
msgQSend(APQ, MSG_APQ_LONG_KEY,MSG_PRI_NORMAL);
}
else if(tick_cnt_ptr == TWO_KEY_VALUE)
{
msgQSend(APQ, MSG_APQ_TWO_KEY,MSG_PRI_NORMAL);
}
else if(tick_cnt_ptr == THREE_KEY_VALUE)
{
msgQSend(APQ, MSG_APQ_THREE_KEY,MSG_PRI_NORMAL);
}
else if(tick_cnt_ptr == FOUR_KEY_VALUE)
{
msgQSend(APQ, MSG_APQ_FOUR_KEY,MSG_PRI_NORMAL);
}
else if(tick_cnt_ptr == FIVE_KEY_VALUE)
{
msgQSend(APQ, MSG_APQ_FIVE_KEY,MSG_PRI_NORMAL);
}
else
{
msgQSend(APQ, MSG_APQ_CLICK_KEY,MSG_PRI_NORMAL);
}
}
其他按鍵的回調(diào)函數(shù)與其相似,可自行設(shè)計(jì)......
按鍵掃描 按鍵掃描通過定時(shí)器中斷進(jìn)行掃描,優(yōu)點(diǎn)是有穩(wěn)定的掃描時(shí)間,可計(jì)算按鍵的持續(xù)時(shí)間及消抖,本設(shè)計(jì)是20ms掃描一次。此函數(shù)中,由按鍵事件注冊函數(shù)提供一個(gè)io_key_num為其提供掃描范圍: 總結(jié) 該獨(dú)立按鍵的多種功能設(shè)計(jì),目的是實(shí)現(xiàn)單個(gè)按鍵實(shí)現(xiàn)多種功能,就好比遙控器的上、下、左、右、確定、返回等,通過單個(gè)按鍵就可實(shí)現(xiàn)其所有功能。該按鍵功能的實(shí)現(xiàn),依賴于消息隊(duì)列進(jìn)行按鍵消息傳遞,項(xiàng)目引入消息隊(duì)列后,極大方便了按鍵回調(diào)函數(shù)的設(shè)計(jì)實(shí)現(xiàn)。 個(gè)人筆記總結(jié),若有問題,歡迎留言、批評(píng)指正! 公眾號(hào)為個(gè)人資料總結(jié),內(nèi)有資料文檔!
|