key_board介紹
key_board用于單片機(jī)中的小巧多功能按鍵支持,軟件采用了分層的思想,并且做到了與平臺無關(guān),用戶只需要提供按鍵的基本信息和讀寫io電平的函數(shù)即可,非常方便移植,同時(shí)支持多個(gè)矩陣鍵盤及多個(gè)單io控制鍵盤。
目前已實(shí)現(xiàn)按下觸發(fā)、彈起觸發(fā)、長按自動觸發(fā)、長按彈起觸發(fā)、多擊觸發(fā)、連續(xù)觸發(fā)等功能,并且能夠隨意組合(支持狀態(tài)的同一時(shí)間軸和非同一時(shí)間軸),后續(xù)還會添加更多的功能。
使用說明
- 初始化相關(guān)的硬件資源。
- 提供一個(gè)1ms的定時(shí)器,用于周期性的調(diào)用'key_check'函數(shù)。
- 提供按鍵的描述及讀寫io的函數(shù)。
- 將鍵盤注冊到系統(tǒng)。
- 具體的操作參考提供的stm32例程。
- 因?yàn)槌绦蚰J(rèn)使用了堆內(nèi)存,當(dāng)發(fā)現(xiàn)程序運(yùn)行結(jié)果不正常時(shí),嘗試增大你的程序堆空間,或者注冊調(diào)試接口查看原因。
- 更詳細(xì)的使用教程見詳細(xì)使用說明或者提供的stm32例程。
已支持的鍵盤
- 矩陣鍵盤

- 單io按鍵

詳細(xì)使用說明
將key_board.c
,key_board.h
,key_board_config.h
放進(jìn)key_board
文件夾中并包含進(jìn)你的工程,添加頭文件路徑。
基礎(chǔ)功能移植(以stm32
矩陣鍵盤為例)
首先需要一個(gè)可使用的定時(shí)器(如果不想使用定時(shí)器也可直接放到主循環(huán)中,但不推薦,會導(dǎo)致時(shí)基不準(zhǔn)確),固定為1ms
觸發(fā)一次;
準(zhǔn)備待檢測的按鍵的基本信息,可參考key_board_sample.c
文件中的struct key_pin_t
結(jié)構(gòu)體,如:
structkey_pin_t{
GPIO_TypeDef*port;//按鍵端口號
uint16_tpin;//按鍵的引腳號
GPIO_PinStatevalid;//按鍵的有效電平(即按鍵按下時(shí)的電平)
GPIO_PinStateinvalid;//按鍵的無效電平(即按鍵空閑時(shí)的電平)
/*
可添加你的其它參數(shù)
*/
};
定義待檢測的按鍵信息,可參考key_board_sample.c
文件中的const struct key_pin_t key_pin_sig[]
結(jié)構(gòu)體數(shù)組,對應(yīng)頭文件為key_board_sample.h
,如:
//全局變量
conststructkey_pin_tkey_pin_sig[]={
{
.port=KEY_PORT_J12,
.pin=KEY_PIN_J12,
.valid=KEY_PRESS_LEVEL_J12,
.invalid=KEY_RELEASE_LEVEL_J12
},
{
.port=KEY_PORT_J34,
.pin=KEY_PIN_J34,
.valid=KEY_PRESS_LEVEL_J34,
.invalid=KEY_RELEASE_LEVEL_J34
},
{
.port=KEY_PORT_J56,
.pin=KEY_PIN_J56,
.valid=KEY_PRESS_LEVEL_J56,
.invalid=KEY_RELEASE_LEVEL_J56
},
};
如果為矩陣鍵盤還需要定義控制io的相關(guān)信息,可參考key_board_sample.c
文件中的const struct key_pin_t key_pin_ctrl[]
結(jié)構(gòu)體數(shù)組,對應(yīng)頭文件為key_board_sample.h
,如:
conststructkey_pin_tkey_pin_ctrl[]={
{
.port=KEY_PORT_J135,
.pin=KEY_PIN_J135,
.valid=KEY_CTL_LINE_ENABLE,
.invalid=KEY_CTL_LINE_DISABLE
},
{
.port=KEY_PORT_J246,
.pin=KEY_PIN_J246,
.valid=KEY_CTL_LINE_ENABLE,
.invalid=KEY_CTL_LINE_DISABLE
},
};
實(shí)現(xiàn)按鍵io的電平讀取函數(shù),可參考key_board_sample.c
文件中的pin_level_get
函數(shù),如:
staticinlineboolpin_level_get(constvoid*desc)
{
structkey_pin_t*pdesc;
pdesc=(structkey_pin_t*)desc;
returnHAL_GPIO_ReadPin(pdesc->port,pdesc->pin)==pdesc->valid;
}
如果為矩陣鍵盤還需要實(shí)現(xiàn)按鍵io的電平寫入函數(shù),可參考key_board_sample.c
文件中的pin_level_set
函數(shù),如:
staticinlinevoidpin_level_set(constvoid*desc,boolflag)
{
structkey_pin_t*pdesc;
pdesc=(structkey_pin_t*)desc;
HAL_GPIO_WritePin(pdesc->port,pdesc->pin,flag?pdesc->valid:pdesc->invalid);
}
定義按鍵的id及功能結(jié)構(gòu)體struct key_public_sig_t
,可參考key_board_sample.c
文件中的const struct key_public_sig_t key_public_sig[]
結(jié)構(gòu)體數(shù)組,對應(yīng)頭文件key_board.h
,如:
conststructkey_public_sig_tkey_public_sig[]={
KEY_PUBLIC_SIG_DEF(KEY_UP,&key_pin_sig[0],pin_level_get,KEY_FLAG_NONE),
KEY_PUBLIC_SIG_DEF(KEY_LEFT,&key_pin_sig[1],pin_level_get,KEY_FLAG_NONE),
KEY_PUBLIC_SIG_DEF(KEY_DOWN,&key_pin_sig[2],pin_level_get,KEY_FLAG_NONE),
//下面的是因?yàn)槭褂玫木仃囨I盤而擴(kuò)展出來的三個(gè)按鍵
KEY_PUBLIC_SIG_DEF(KEY_ENTER,&key_pin_sig[0],pin_level_get,KEY_FLAG_NONE),
KEY_PUBLIC_SIG_DEF(KEY_RIGHT,&key_pin_sig[1],pin_level_get,KEY_FLAG_NONE),
KEY_PUBLIC_SIG_DEF(KEY_EXIT,&key_pin_sig[2],pin_level_get,KEY_FLAG_NONE),
};
如果為矩陣鍵盤還需要定義控制io的id及功能結(jié)構(gòu)體struct key_public_ctrl_t
,可參考key_board_sample.c
文件中的const struct key_public_ctrl_t key_public_ctrl[]
結(jié)構(gòu)體數(shù)組,對應(yīng)頭文件key_board.h
,如:
conststructkey_public_ctrl_tkey_public_ctrl[]={
KEY_PUBLIC_CTRL_DEF(&key_pin_ctrl[0],pin_level_set),
KEY_PUBLIC_CTRL_DEF(&key_pin_ctrl[1],pin_level_set),
};
初始化鍵盤,可參考key_board_sample.c
文件中的GPIO_Key_Board_Init
函數(shù),如:
voidGPIO_Key_Board_Init(void)
{
//硬件io的初始化
GPIO_InitTypeDefGPIO_InitStruct;
unsignedinti;
RCC_KEY_BOARD_CLK_ENABLE();
GPIO_InitStruct.Pull=GPIO_PULLUP;
GPIO_InitStruct.Mode=GPIO_MODE_INPUT;
for(i=0;ifor(i=0;i//初始化鍵盤
key_board_init();
//注冊鍵盤到系統(tǒng)中(矩陣鍵盤)
key_board_register(KEY_BOARD_MATRIX,key_public_sig,ARRAY_SIZE(key_public_sig),key_public_ctrl,ARRAY_SIZE(key_public_ctrl));
}
主流程偽代碼框架,更多例子參考main_test.c
文件:
intmain(void)
{
//初始化硬件io,并注冊鍵盤
GPIO_Key_Board_Init();
//初始化定時(shí)器,用于按鍵掃描(1ms)
init_tmr();
for(;;)
{
if(key_check_state(KEY_UP,KEY_RELEASE))
{
PRINTF("KEY_UPKEY_RELEASE
");
}
if(key_check_state(KEY_UP,KEY_PRESS))
{
PRINTF("KEY_UPKEY_PRESS
");
}
}
}
//定時(shí)器到期回調(diào)處理函數(shù)
voidtmr_irq_callback(void)
{
//調(diào)用按鍵掃描核心函數(shù)
key_check();
}
擴(kuò)展功能長按的使用
首先確保key_board_config.h
文件中宏KEY_LONG_SUPPORT
已處于使能狀態(tài),并且正確設(shè)置了宏KEY_DEFAULT_LONG_TRRIGER_TIME
的值;
設(shè)置按鍵功能需要對長按進(jìn)行檢測,如:
KEY_PUBLIC_SIG_DEF(KEY_UP,&key_pin_sig[0],pin_level_get,KEY_FLAG_PRESS_LONG|KEY_FLAG_RELEASE_LONG)
使用例程:
if(key_check_state(KEY_UP,KEY_PRESS_LONG))
{
PRINTF("KEY_UPKEY_PRESS_LONG
");
}
if(key_check_state(KEY_UP,KEY_RELEASE_LONG))
{
PRINTF("KEY_UPKEY_RELEASE_LONG
");
}
擴(kuò)展功能連按的使用
首先確保key_board_config.h
文件中宏KEY_CONTINUOUS_SUPPORT
已處于使能狀態(tài),并且正確設(shè)置了宏KEY_DEFAULT_CONTINUOUS_INIT_TRRIGER_TIME
和KEY_DEFAULT_CONTINUOUS_PERIOD_TRRIGER_TIME
的值;
設(shè)置按鍵功能需要對連按進(jìn)行檢測,如:
KEY_PUBLIC_SIG_DEF(KEY_UP,&key_pin_sig[0],pin_level_get,KEY_FLAG_PRESS_CONTINUOUS)
使用例程:
if(key_check_state(KEY_UP,KEY_PRESS_CONTINUOUS))
{
PRINTF("KEY_UPKEY_PRESS_CONTINUOUS
");
}
擴(kuò)展功能多擊的使用
首先確保key_board_config.h
文件中宏KEY_MULTI_SUPPORT
已處于使能狀態(tài),并且正確設(shè)置了宏KEY_DEFAULT_MULTI_INTERVAL_TIME
的值;
設(shè)置按鍵功能需要多擊進(jìn)行檢測,如:
KEY_PUBLIC_SIG_DEF(KEY_UP,&key_pin_sig[0],pin_level_get,KEY_FLAG_PRESS_MULTI|KEY_FLAG_RELEASE_MULTI)
使用例程:
unsignedintres;
res=key_check_state(KEY_UP,KEY_PRESS_MULTI);
if(res)
{
PRINTF("KEY_UPKEY_PRESS_MULTI:%d
",res);
}
res=key_check_state(KEY_UP,KEY_RELEASE_MULTI);
if(res)
{
PRINTF("KEY_UPKEY_RELEASE_MULTI:%d
",res);
}
擴(kuò)展功能組合狀態(tài)(同一時(shí)間軸)
感謝網(wǎng)友:石玉虎[@shi-yuhu]的反饋,已更正之前錯(cuò)誤的使用案例。
使用例程:
unsignedintkey_down_release_long,key_up_release_long;
key_down_release_long=key_check_state(KEY_DOWN,KEY_RELEASE_LONG);
key_up_release_long=key_check_state(KEY_UP,KEY_RELEASE_LONG);
if(key_down_release_long&&key_up_release_long)
{
PRINTF("KEY_DOWNKEY_RELEASE_LONG&&KEY_UPKEY_RELEASE_LONG
");
}
擴(kuò)展功能組合狀態(tài)(非同一時(shí)間軸)
首先確保key_board_config.h
文件中宏KEY_COMBINE_SUPPORT
已處于使能狀態(tài),并且正確設(shè)置了宏KEY_DEFAULT_COMBINE_INTERVAL_TIME
的值;
使用例程:
//用于保存注冊后的組合狀態(tài)id
staticunsignedinttest_id1,test_id2;
//定義要檢測的狀態(tài)
conststructkey_combine_ttest_combine1[]={
{.id=KEY_UP,.state=KEY_PRESS},
{.id=KEY_DOWN,.state=KEY_PRESS_LONG},
{.id=KEY_UP,.state=KEY_PRESS},
};
//注冊組合狀態(tài)
test_id1=key_combine_register(test_combine1,ARRAY_SIZE(test_combine1));
conststructkey_combine_ttest_combine2[]={
{.id=KEY_UP,.state=KEY_PRESS},
{.id=KEY_DOWN,.state=KEY_PRESS},
{.id=KEY_UP,.state=KEY_PRESS},
{.id=KEY_DOWN,.state=KEY_PRESS},
};
test_id2=key_combine_register(test_combine2,ARRAY_SIZE(test_combine2));
if(key_check_combine_state(test_id1))
{
PRINTF("combinetest_id1
");
}
if(key_check_combine_state(test_id2))
{
PRINTF("combinetest_id2
");
}
審核編輯 :李倩
-
單片機(jī)
+關(guān)注
關(guān)注
6060文章
44835瀏覽量
645205 -
STM32
+關(guān)注
關(guān)注
2287文章
10988瀏覽量
361591 -
定時(shí)器
+關(guān)注
關(guān)注
23文章
3274瀏覽量
116880 -
按鍵
+關(guān)注
關(guān)注
4文章
225瀏覽量
57900
原文標(biāo)題:一個(gè)應(yīng)用于單片機(jī)的按鍵處理模塊!
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
單片機(jī)按鍵處理總結(jié)——含程序詳解
單片機(jī)的按鍵處理框架資料和函數(shù)詳細(xì)說明

分享可應(yīng)用于單片機(jī)的內(nèi)存管理模塊mem_malloc

單片機(jī)按鍵使用程序 (51單片機(jī))

51單片機(jī)按鍵檢測--獨(dú)立按鍵與矩陣鍵盤

基于AT32(STM32)單片機(jī)的模塊化代碼之——按鍵代碼模塊化

單片機(jī)學(xué)習(xí)-矩陣按鍵

如何實(shí)現(xiàn)單片機(jī)用一個(gè)I/O采集多個(gè)按鍵信號?

評論