EmbeddedButton嵌入式按键驱动设计实现
EmbeddedButton
简介
(资料图片仅供参考)
EmbeddedButton是一个轻量级简单易用的嵌入式按键驱动模块,可无限拓展按键,支持多连击、长按、短按长按等多种按键事件;该模块通过异步回调方式来简化程序结构,根据几个简单原则完成了整个代码逻辑的支撑。
使用方法
1.定义按键实体
struct button_obj_t button1;
2.建立键值映射表(设置回调事件)
const key_value_map_t button1_map[] = { { .key_value = SINGLE_CLICK_KV, .kv_func_cb = single_press_handle }, { .key_value = LONG_PRESEE_START, .kv_func_cb = long_press_handle }, { .key_value = SINGLE_CLICK_THEN_LONG_PRESS_KV, .kv_func_cb = single_press_then_long_press_handle }, };
3.初始化按键对象,参数含义分别为
按键实体 绑定按键的GPIO电平读取接口read_button1_pin() 设置有效触发电平 按键ID 键值映射表 键值映射表大小 button_init(&button1, read_button1_pin, 0, 0, button1_map, ARRAY_SIZE(button1_map));
4.启动按键
button_start(&button1); 5.设置一个5ms间隔的定时器循环调用按键后台处理函数
while(1) { ... if(timer_ticks == 5) { timer_ticks = 0; button_ticks(); } }
特性
1.依靠简单几个原则,支持起整个按键判断逻辑
只要键值非零,时间tick++ 只要按键状态发生变化,改变一次键值(__append_bit()),tick时间清零(确保tick为按下或抬起的时间) 以tick时间的长短及按键抬起作为一次状态结束的判断依据,可以很好的实现短按长按等操作;
2.使用C语言实现,巧妙利用位运算来实现每个按键键值的二进制记录表示,1代表按下,0代表松开
3.利用数据驱动思想完成对应按键事件的调用:
typedef struct { key_value_type_t key_value; void ( kv_func_cb)(void); } key_value_map_t; const key_value_map_t button1_map[] = { { .key_value = SINGLE_CLICK_KV, .kv_func_cb = single_press_handle }, { .key_value = LONG_PRESEE_START, .kv_func_cb = long_press_handle }, { .key_value = SINGLE_CLICK_THEN_LONG_PRESS_KV, .kv_func_cb = single_press_then_long_press_handle }, }; for(size_t i = 0; i < button->map_size; i++) { if((button->map_ptr[i].key_value == button->key_value) && (button->map_ptr[i].kv_func_cb)) { button->map_ptr[i].kv_func_cb(button); } }
4.基于面向对象方式设计思路,每个按键对象单独用一份数据结构管理:
typedef struct button_obj_t { uint8_t debounce_cnt : 4; uint8_t active_level : 1; uint8_t read_level : 1; uint8_t read_level_update : 1; uint8_t event_analyze_en : 1; uint8_t id; uint16_t ticks; state_bits_type_t state_bits; key_value_type_t key_value; uint8_t (* read_button_func_ptr)(uint8_t button_id); const key_value_map_t map_ptr; size_t map_size; struct button_obj_tnext; }button_obj_t; Examples #include "embedded_button.h" struct button_obj_t button1; uint8_t read_button_pin(uint8_t button_id) { // you canshare the GPIO read function with multiple Buttons switch(button_id) { case 0: return get_button1_value(); //Require self implementation break; default: return 0; break; } return 0; } void single_click_handle(void* btn) { //do something... printf("/ single click/rn"); } void double_click_handle(void* btn) { //do something... printf("/ double click/rn"); } void long_press_handle(void* btn) { //do something... printf("/ long press/rn"); } void single_click_then_long_press_handle(void* btn) { //do something... printf("/ single click and long press/rn"); } void double_click_then_long_press_handle(void* btn) { //do something... printf("/ double click and long press/rn"); } const key_value_map_t button1_map[] = { { .key_value = SINGLE_CLICK_KV, .kv_func_cb = single_click_handle }, { .key_value = DOUBLE_CLICK_KV, .kv_func_cb = double_click_handle }, { .key_value = LONG_PRESEE_START, .kv_func_cb = long_press_handle }, { .key_value = SINGLE_CLICK_THEN_LONG_PRESS_KV, .kv_func_cb = single_click_then_long_press_handle }, { .key_value = DOUBLE_CLICK_THEN_LONG_PRESS_KV, .kv_func_cb = double_click_then_long_press_handle } }; ... int main() { button_init(&button1, read_button_pin, 0, 0, button1_map, ARRAY_SIZE(button1_map)); button_start(&button1); //make the timer invoking the button_ticks() interval 5ms. //This function is implemented by yourself. __timer_start(button_ticks, 0, 5); while(1) {} }
标签: