一个应用于单片机的按键处理模块-单片机一个按钮实现多的功能

key_board介绍

key_board用于单片机中的小巧多功能按键支持,软件采用了分层的思想,并且做到了与平台无关,用户只需要提供按键的基本信息和读写io电平的函数即可,非常方便移植,同时支持多个矩阵键盘及多个单io控制键盘。

目前已实现按下触发、弹起触发、长按自动触发、长按弹起触发、多击触发、连续触发等功能,并且能够随意组合(支持状态的同一时间轴和非同一时间轴),后续还会添加更多的功能。

使用说明

初始化相关的硬件资源。 提供一个1ms的定时器,用于周期性的调用key_check函数。 提供按键的描述及读写io的函数。 将键盘注册到系统。 具体的操作参考提供的stm32例程。 因为程序默认使用了堆内存,当发现程序运行结果不正常时,尝试增大你的程序堆空间,或者注册调试接口查看原因。 更详细的使用教程见详细使用说明或者提供的stm32例程。

已支持的键盘

矩阵键盘 一个应用于单片机的按键处理模块-单片机一个按钮实现多的功能矩阵键盘 单io按键 一个应用于单片机的按键处理模块-单片机一个按钮实现多的功能单io按键

详细使用说明

将复制key_board.c,复制key_board.h,复制key_board_config.h放进复制key_board文件夹中并包含进你的工程,添加头文件路径。

基础功能移植(以复制stm32矩阵键盘为例)

首先需要一个可使用的定时器(如果不想使用定时器也可直接放到主循环中,但不推荐,会导致时基不准确),固定为复制1ms触发一次;

准备待检测的按键的基本信息,可参考复制key_board_sample.c文件中的复制struct key_pin_t结构体,如:

复制structkey_pin_t{ GPIO_TypeDef*port;//按键端口号 uint16_tpin;//按键的引脚号 GPIO_PinStatevalid;//按键的有效电平(即按键按下时的电平) GPIO_PinStateinvalid;//按键的无效电平(即按键空闲时的电平) /* 可添加你的其它参数 */ };

定义待检测的按键信息,可参考复制key_board_sample.c文件中的复制const struct key_pin_t key_pin_sig[]结构体数组,对应头文件为复制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的相关信息,可参考复制key_board_sample.c文件中的复制const struct key_pin_t key_pin_ctrl[]结构体数组,对应头文件为复制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 }, };

实现按键io的电平读取函数,可参考复制key_board_sample.c文件中的复制pin_level_get函数,如:

复制staticinlineboolpin_level_get(constvoid*desc) { structkey_pin_t*pdesc; pdesc=(structkey_pin_t*)desc; returnHAL_GPIO_ReadPin(pdesc->port,pdesc->pin)==pdesc->valid; }

如果为矩阵键盘还需要实现按键io的电平写入函数,可参考复制key_board_sample.c文件中的复制pin_level_set函数,如:

复制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及功能结构体复制struct key_public_sig_t,可参考复制key_board_sample.c文件中的复制const struct key_public_sig_t key_public_sig[]结构体数组,对应头文件复制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), //下面的是因为使用的矩阵键盘而扩展出来的三个按键 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及功能结构体复制struct key_public_ctrl_t,可参考复制key_board_sample.c文件中的复制const struct key_public_ctrl_t key_public_ctrl[]结构体数组,对应头文件复制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函数,如:

复制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;i< ARRAY_SIZE(key_pin_sig);i++)     {         GPIO_InitStruct.Pin   = key_pin_sig[i].pin;         HAL_GPIO_Init(key_pin_sig[i].port, &GPIO_InitStruct);     }     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;     GPIO_InitStruct.Pull  = GPIO_NOPULL;     GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;     for(i=0;i< ARRAY_SIZE(key_pin_ctrl);i++)     {         GPIO_InitStruct.Pin   = key_pin_ctrl[i].pin;         HAL_GPIO_Init(key_pin_ctrl[i].port, &GPIO_InitStruct);     }     //初始化键盘 key_board_init(); //注册键盘到系统中(矩阵键盘) 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(); //初始化定时器,用于按键扫描(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 “); } } } //定时器到期回调处理函数 voidtmr_irq_callback(void) { //调用按键扫描核心函数 key_check(); }

扩展功能长按的使用

首先确保复制key_board_config.h文件中宏复制KEY_LONG_SUPPORT已处于使能状态,并且正确设置了宏复制KEY_DEFAULT_LONG_TRRIGER_TIME的值;

设置按键功能需要对长按进行检测,如:

复制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 “); }

扩展功能连按的使用

首先确保复制key_board_config.h文件中宏复制KEY_CONTINUOUS_SUPPORT已处于使能状态,并且正确设置了宏复制KEY_DEFAULT_CONTINUOUS_INIT_TRRIGER_TIME和复制KEY_DEFAULT_CONTINUOUS_PERIOD_TRRIGER_TIME的值;

设置按键功能需要对连按进行检测,如:

复制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 “); }

扩展功能多击的使用

首先确保复制key_board_config.h文件中宏复制KEY_MULTI_SUPPORT已处于使能状态,并且正确设置了宏复制KEY_DEFAULT_MULTI_INTERVAL_TIME的值;

设置按键功能需要多击进行检测,如:

复制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); }

扩展功能组合状态(同一时间轴)

感谢网友:石玉虎[@shi-yuhu]的反馈,已更正之前错误的使用案例。

使用例程:

复制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 “); }

扩展功能组合状态(非同一时间轴)

首先确保复制key_board_config.h文件中宏复制KEY_COMBINE_SUPPORT已处于使能状态,并且正确设置了宏复制KEY_DEFAULT_COMBINE_INTERVAL_TIME的值;

使用例程:

复制//用于保存注册后的组合状态id staticunsignedinttest_id1,test_id2; //定义要检测的状态 conststructkey_combine_ttest_combine1[]={ {.id=KEY_UP,.state=KEY_PRESS}, {.id=KEY_DOWN,.state=KEY_PRESS_LONG}, {.id=KEY_UP,.state=KEY_PRESS}, }; //注册组合状态 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 “); }

审核编辑 :李倩

免责声明:文章内容来自互联网,本站不对其真实性负责,也不承担任何法律责任,如有侵权等情况,请与本站联系删除。
转载请注明出处:一个应用于单片机的按键处理模块-单片机一个按钮实现多的功能 https://www.yhzz.com.cn/a/4503.html

上一篇 2023-04-11 01:28:50
下一篇 2023-04-11 01:33:21

相关推荐

联系云恒

在线留言: 我要留言
客服热线:400-600-0310
工作时间:周一至周六,08:30-17:30,节假日休息。