Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
算法优化
KEY_按键
RT-Thread一般讨论
EmbeddedButton,嵌入式按键处理框架
发布于 2024-08-07 22:44:34 浏览:367
订阅该版
[tocm]
EmbeddedButton,嵌入式按键处理框架
- [视频介绍](https://www.bilibili.com/video/BV1dRv9etEo7/?spm_id_from=333.999.0.0) - [项目链接](https://github.com/530china/EmbeddedButton)
👋 简介
EmbeddedButton是一个轻量级简单易用的嵌入式按键处理框架,可无限拓展按键; - 支持多连击、长按、短按长按等多种按键事件; - 模块通过几个简单原则完成了整个代码逻辑的支撑; - 核心处理采取数据驱动方式,支持位运算键值匹配,仅内置基本键值定义,其他键值含义由用户通过**配置键值匹配规则**自行定义,而不用侵入式修改代码,灵活性极强; ## 🌱 特性 > 1.依靠简单几个原则,支持起整个按键判断逻辑 - 只要键值非零,时间tick++ - 只要按键状态发生变化,改变一次键值(**__append_bit()**),tick时间清零(确保tick为按下或抬起的时间) - 以tick时间的长短及按键抬起作为一次状态结束的判断依据,可以很好的实现短按长按等操作; > 2.使用C语言实现,巧妙利用位运算来实现每个按键键值的二进制记录表示,1代表按下,0代表松开 键值 | 说明 --- | --- 0b0 | 未按下 0b010 | 单击 0b01010 | 双击 0b01010...n | n连击 0b011 | 长按开始 0b0111| 长按保持 0b01110|长按结束 0b01011|短按然后长按 0b0101011 | 双击然后长按 0b01010..n11 | n连击然后长按 > 3.核心处理采取数据驱动方式,支持位运算键值匹配: - 关键数据结构,键值匹配规则配置表: ```c 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; ``` - 关键算法: ```c 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); } ``` - 支持的操作符: ```c #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)使用 - 以使用callback方式为例: ```c // 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) {} } ``` ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240807/9cfaf79e6d5eb8d4a4398c053ffa0957.png.webp) ### 2)调试 - 定义EB_DEBUG_PRINTF宏后将会开启键值打印,例如下面,需要将printf换成你的打印函数: ```c #define EB_DEBUG_PRINTF printf ``` ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240807/2095a52afa18a94a98a09f7557778f34.png.webp) ## ⚡ 其他 - 本项目基于本人实际开发中遇到的一些按键驱动使用体验问题,在他人项目(见参考链接)的思想基础上,开发的此按键驱动模块,之前提到了本模块的优势,下面说下有待改进的地方:对于多按键时组合按键的表示方式,目前还没有想到比较优雅的实现方式,后续有头绪后会进一步改进,补齐这一环。最后,感谢帮助思考我的小伙伴[shawnfeng0](https://github.com/shawnfeng0)以及正在使用此模块的小伙伴,欢迎一起开发改进! - 更多高级用法见 [examples](https://github.com/530china/EmbeddedButton/blob/master/examples/README.md) ## 💬 参考链接 - [MultiButton](https://github.com/0x1abin/MultiButton) - [FlexibleButton](https://github.com/murphyzhao/FlexibleButton/tree/master) - [安富莱按键FIFO思想](https://www.armbbs.cn/forum.php?mod=viewthread&tid=111527&highlight=%B0%B4%BC%FC)
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
530china
这家伙很懒,什么也没写!
文章
2
回答
0
被采纳
0
关注TA
发私信
相关文章
1
有关动态模块加载的一篇论文
2
最近的调程序总结
3
晕掉了,这么久都不见layer2的踪影啊
4
继续K9ii的历程
5
[GUI相关] FreeType 2
6
[GUI相关]嵌入式系统中文输入法的设计
7
20081101 RT-Thread开发者聚会总结
8
嵌入式系统基础
9
linux2.4.19在at91rm9200 上的寄存器设置
10
[转]基于嵌入式Linux的通用触摸屏校准程序
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
19
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
6
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
6
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部