1.依靠简单几个原则,支持起整个按键判断逻辑
2.使用C语言实现,巧妙利用位运算来实现每个按键键值的二进制记录表示,1代表按下,0代表松开
键值 | 说明 |
---|---|
0b0 | 未按下 |
0b010 | 单击 |
0b01010 | 双击 |
0b01010...n | n连击 |
0b011 | 长按开始 |
0b0111 | 长按保持 |
0b01110 | 长按结束 |
0b01011 | 短按然后长按 |
0b0101011 | 双击然后长按 |
0b01010..n11 | n连击然后长按 |
3.核心处理采取数据驱动方式,支持位运算键值匹配:
typedef struct {
key_value_type_t operand; // 操作数
kv_match_operator_type_t operator; // 操作符
key_value_type_t tar_result; // 目标结果
void (*kv_func_cb)(void*); // 符合匹配后调用的回调函数
} key_value_match_map_t;
key_value_type_t operand_origin = button->kv_match_map_ptr[i].operand;
key_value_type_t operand_result = button->kv_match_map_ptr[i].operand;
kv_match_operator_type_t operator =button->kv_match_map_ptr[i].operator;
key_value_type_t tar_result = button->kv_match_map_ptr[i].tar_result;
if(operator == KV_MATCH_OPERATOR_NULL)
operand_result = button->key_value;
else if(operator & KV_MATCH_OPERATOR_BITWISE_AND)
operand_result = (operand_origin & button->key_value);
else if(operator & KV_MATCH_OPERATOR_BITWISE_OR)
operand_result = (operand_origin | button->key_value);
else if(operator & KV_MATCH_OPERATOR_BITWISE_NOT)
operand_result = ~(button->key_value);
else if(operator & KV_MATCH_OPERATOR_BITWISE_XOR)
operand_result = (operand_origin ^ button->key_value);
if(operand_result == tar_result)
{
button->kv_match_map_ptr[i].kv_func_cb(button);
}
#define KV_MATCH_OPERATOR_NULL (0) // 无操作符,仅通过(key_value == tar_result)?判断, 默认是这个
#define KV_MATCH_OPERATOR_BITWISE_AND (1 << 0) // 按位与操作符,(operand & key_value == tar_result)?
#define KV_MATCH_OPERATOR_BITWISE_OR (1 << 1) // 按位或操作符,(operand | key_value == tar_result)?
#define KV_MATCH_OPERATOR_BITWISE_NOT (1 << 2) // 按位取反操作符,(~ key_value == tar_result)?
#define KV_MATCH_OPERATOR_BITWISE_XOR (1 << 2) // 按位异或操作符,(operand ^ key_value == tar_result)?
4.基于面向对象方式设计思路,每个按键对象单独用一份数据结构管理
// 1.包含头文件
#include "embedded_button.h"
// 2.定义按键实体
struct button_obj_t button1;
// 3.GPIO电平读取接口设置
uint8_t read_button_pin(uint8_t button_id)
{
// you can share the GPIO read function with multiple Buttons
switch(button_id)
{
case 0:
return get_button1_value(); // 用户自行实现
break;
default:
return 0;
break;
}
return 0;
}
// 4. 配置键值匹配规则(设置回调事件)
void single_click_handle(void* btn)
{
//do something...
printf("/****single click****/\r\n");
}
void double_click_handle(void* btn)
{
//do something...
printf("/****double click****/\r\n");
}
void long_press_handle(void* btn)
{
//do something...
printf("/****long press****/\r\n");
}
void single_click_then_long_press_handle(void* btn)
{
//do something...
printf("/****single click and long press****/\r\n");
}
void quintuple_click_handle(void* btn)
{
//do something...
if(check_is_repeat_click_mode(btn))
printf("/****quintuple click****/\r\n");
}
const key_value_match_map_t button1_map[] =
{
{
.tar_result = SINGLE_CLICK_KV,
.kv_func_cb = single_click_handle
},
{
.tar_result = DOUBLE_CLICK_KV,
.kv_func_cb = double_click_handle
},
{
.tar_result = LONG_PRESEE_START,
.kv_func_cb = long_press_handle
},
{
.tar_result = SINGLE_CLICK_THEN_LONG_PRESS_KV,
.kv_func_cb = single_click_then_long_press_handle
},
{
.operand = 0b1010101010,
.operator = KV_MATCH_OPERATOR_BITWISE_AND,
.tar_result = 0b1010101010,
.kv_func_cb = quintuple_click_handle
}
};
int main()
{
/************************************************
****5.初始化按键对象,参数含义分别为
****
****- 按键实体
****- 绑定按键的GPIO电平读取接口**read_button1_pin()**
****- 设置有效触发电平
****- 按键ID
****- 键值匹配规则配置表
****- 键值匹配规则配置表大小
*************************************************/
button_init(&button1, read_button_pin, 0, 0, button1_map, ARRAY_SIZE(button1_map));
// 6.启动按键
button_start(&button1);
// 7. 设置一个5ms间隔的定时器循环调用按键后台处理函数 button_ticks()
__timer_start(button_ticks, 0, 5);
while(1)
{}
}
#define EB_DEBUG_PRINTF printf
更多回帖