阴道瘙痒用什么药| 手胀是什么原因| 蒲公英有什么功效和作用| 血小板计数偏低是什么意思| 总想小便是什么原因| 突然发热是什么原因| 前列腺钙化灶是什么病| 它们是指什么| 什么人不能吃榴莲| 雍正为什么不杀十阿哥| mario是什么意思| 金字塔里面有什么| 宝宝消化不良吃什么药| 推荐是什么意思| 眼睛模糊是什么原因引起的| 莲子吃了有什么好处| 挠头什么意思| 肩袖损伤吃什么药效果最好| 英雄本色是什么意思| 23333是什么意思| 怀孕前3个月需要注意什么| 下体有异味是什么原因| 什么蔬菜降血压效果最好| 脑梗是什么| lodge是什么意思| 2014年是什么年| 正局级什么级别| 生活补贴是什么意思| 套作是什么意思| 垂体泌乳素高是什么原因| 孕妇喝柠檬水对胎儿有什么好处| co是什么气体| 天字加一笔是什么字| 铜钱草能治什么病| 胰腺最怕什么| ecology是什么意思| 死有余辜什么意思| 仲字五行属什么| 不显山不露水是什么意思| 山五行属什么| 826是什么星座| 27年属什么生肖| 食禄痣是什么意思| 长白眉毛是什么征兆| 侍郎是什么官职| 潦草什么意思| 情调是什么意思| tvb是什么| 容易犯困是什么原因| 男人左眼跳是什么预兆| 什么是无纺布| 吃软不吃硬是什么生肖| 什么原因得湿疹| 男生下巴长痘痘是什么原因| 什么味道| 什么花好养| 洋葱不能跟什么一起吃| 挂彩是什么意思| 肠胀气是什么原因引起的| 无创是检查什么| 备孕不应该吃什么| 9月6日什么星座| 胰岛素是什么器官分泌的| 梦见雪地是什么征兆| 高血压注意什么事项| 一行是什么意思| 桃子与什么相克| 孤独症有什么表现| 什么网站可以看毛片| 这是什么皮肤病| 什么是一二三级医院| 不谷是什么意思| 记忆力下降是什么原因引起的| 土命适合什么颜色| 晚上喝什么茶有助于睡眠| 什么是月子病| 尿素偏高是什么意思| 噫气是什么意思| 父母都是a型血孩子是什么血型| 眼压高要注意什么| 什么花晚上开| 治疗幽门螺旋杆菌的四联药是什么| 深海鱼油有什么好处| 虾和什么蔬菜搭配最好| 儿童头痛挂什么科| 霖字五行属什么| 肋骨断了是什么感觉| ogtt是什么意思| 掉头发是什么原因女性| 甲亢是一种什么病严重吗| 明天属相是什么生肖| 南乳是什么| 激光脱毛有什么副作用| 提溜是什么意思| vfu是什么牌子| 浆果是什么| 下面流出发黄的液体是什么原因| 畏寒是什么意思| 男人时间短吃什么药| 感冒咳嗽吃什么药| 半夜猫叫有什么预兆| 下巴发黑是什么原因| rpa是什么| 黄精吃了有什么好处| 苦瓜有什么功效和作用| 黄体期出血是什么原因| 孕妇建档是什么意思| 什么是g点| 发际线高的人说明什么| 毛囊炎是什么症状| 梅雨季节是什么意思| 肌腱是什么组织| 办护照需要准备什么材料| 马步鱼是什么鱼| 为什么香蕉不能放冰箱| 为什么心会痛| 五红汤什么时候喝最好| 华在姓氏里读什么| 甲功五项查的是什么| 做梦梦到大蟒蛇是什么意思| 脖子发麻是什么原因| 周岁是什么意思| 秀才相当于什么学历| 全麻后为什么不能睡觉| 相与是什么意思| 头经常晕是什么原因| 猫拉稀吃什么药| 乏是什么单位| 领导喜欢什么样的员工| 甲基苯丙胺是什么| 什么叫穿刺| 肌肉疼痛挂什么科| 白醋有什么作用| 瓜蒌根为什么叫天花粉| 梦到公鸡是什么意思| 买买提是什么意思| 刑警队是干什么的| 逗闷子是什么意思| 山梨糖醇是什么| 前列腺实质回声欠均匀什么意思| 鼻涕臭是什么原因| 做活检意味着什么| 为什么贫血| 舌头痛吃什么药| 梦见丧尸是什么预兆| 吃什么水果降血压| 710是什么意思| 升结肠ca是什么意思| 柠檬泡水有什么好处| 耳朵听不清楚是什么原因| 颈椎病睡什么枕头最好| hpv感染有什么症状女性| 阴道出血是什么原因| 舌头有点麻是什么病的前兆| 鹌鹑蛋不能和什么一起吃| 总想睡觉是什么原因| 有点想吐是什么原因| 5月27日什么星座| 张姓为什么出不了皇帝| 蜘蛛侠叫什么| 发癫是什么意思| only是什么品牌| 1998年五行属什么| 鱼香肉丝用什么肉| eason是什么意思| 蓝天白云是什么意思| 记忆力不好是什么原因| 7点到9点是什么时辰| 白细胞正常c反应蛋白高说明什么| 瓠子和什么相克| 黄片是什么| 尿常规白细胞偏高是什么原因| 亡羊补牢的寓意是什么| 老鼠屎长什么样| 凌晨三点醒是什么原因| 婴儿采足底血是查什么| 这是什么牌子| 检查妇科清洁度三是什么意思| 缠足是什么时候开始的| 去火喝什么茶| 二狗是什么意思| 半边脸疼是什么原因引起的| roa是什么意思| 小学生什么时候考试| 总胆固醇高有什么症状| 鼻孔里面痒是什么原因| 一什么扇子| 朋友越来越少暗示什么| 专员是什么职位| 你是电你是光是什么歌| 金卡有什么好处和坏处| 1996年出生属什么生肖| 塔克是什么食物| 呼和浩特有什么特产| 男人右眼皮跳是什么预兆| 蝉吃什么食物| 血干了是什么颜色| cod是什么| 喝枸杞有什么好处| 拔完智齿能吃什么| 大便不成形是什么原因| elephant是什么意思| 收孕妇尿是干什么用的| xxs是什么意思| 小腿肿是什么原因| 三十七岁属什么生肖| 全身酸痛什么原因| 爱恨情仇是什么意思| 什么是格言| o型血和b型血的孩子是什么血型| 补气血吃什么食物| 省油的灯是什么意思| 喉咙发炎是什么症状| 山开念什么| 安抚奶嘴什么时候开始用| 大腿前侧是什么经络| 色弱什么意思| 外科是看什么病的| 三月二十二是什么星座| 宠溺是什么意思| 结售汇是什么意思| 人活在世上的意义是什么| 半路杀出个程咬金是什么意思| 格斗和散打有什么区别| 吃饭出虚汗是什么原因| 湿热吃什么药| 8五行属什么| 一票制什么意思| 脖子上长小肉粒是什么原因| 脾稍大什么意思| 什么是pv| 卵巢早衰有什么症状| 化脓性扁桃体炎吃什么药| 脖子粗是什么原因| 巨蟹是什么象星座| 万艾可是什么| 喝酒睡不着是什么原因| 六味地黄丸治什么| 什么时间喝酸奶最好| 小腿浮肿什么原因| 孙子兵法是什么生肖| 争奇斗艳什么意思| 肤专家软膏主要治什么| 漫山遍野是什么生肖| 回民为什么不能吃猪肉| 搭桥和支架有什么区别| 预防中暑喝什么水| 藕不能和什么一起吃| kkp什么意思| 低密度脂蛋白偏高吃什么好| 贫血用什么药补血最快| 仙人跳什么意思| 闰六月给父母买什么| 做梦遗精是什么原因| 吃完羊肉不能吃什么水果| 开心的动物是什么生肖| 批号是什么意思| 大力是什么药| 用盐洗脸有什么好处| 护肝喝什么茶| bcr是什么意思| 相思什么意思| 缺硒有什么症状| 蚊子代表什么生肖| 百度
Skip to content

0x1abin/MultiButton

Folders and files

NameName
Last commit message
Last commit date

Latest commit

?

History

79 Commits
?
?
?
?
?
?
?
?
?
?
?
?
?
?

Repository files navigation

MultiButton

一个高效、灵活的多按键状态机库,支持多种按键事件检测。

功能特性

  • ? 多种按键事件: 按下、抬起、单击、双击、长按开始、长按保持、重复按下
  • ? 硬件去抖: 内置数字滤波,消除按键抖动
  • ? 状态机驱动: 清晰的状态转换逻辑,可靠性高
  • ? 多按键支持: 支持无限数量的按键实例
  • ? 回调机制: 灵活的事件回调函数注册
  • ? 内存优化: 紧凑的数据结构,低内存占用
  • ? 配置灵活: 可自定义时间参数和功能选项
  • ? 参数验证: 完善的错误检查和边界条件处理

优化改进

1. 代码结构优化

  • 更清晰的枚举命名 (BTN_PRESS_DOWN vs PRESS_DOWN)
  • 增加状态机状态枚举,提高可读性
  • 统一的函数命名规范
  • 更好的代码注释和文档

2. 功能增强

  • 新增 button_detach() - 动态移除事件回调
  • 新增 button_reset() - 重置按键状态
  • 新增 button_is_pressed() - 查询当前按键状态
  • 新增 button_get_repeat_count() - 获取重复按下次数
  • 改进的 button_get_event() 函数

3. 安全性提升

  • 完善的参数验证
  • 空指针检查
  • 数组越界保护
  • 更好的错误返回值

4. 性能优化

  • 内联函数优化 GPIO 读取
  • 更安全的宏定义
  • 减少不必要的计算
  • 优化的状态机逻辑

5. 可维护性

  • 清晰的状态转换
  • 模块化设计
  • 配置文件分离
  • 详细的使用示例

编译和构建

使用 Makefile (推荐)

# 编译所有内容 (库 + 示例)
make

# 只编译库
make library

# 只编译示例
make examples

# 编译特定示例
make basic_example
make advanced_example
make poll_example

# 运行测试
make test

# 清理构建文件
make clean

# 查看帮助
make help

使用构建脚本

# 使脚本可执行
chmod +x build.sh

# 编译所有内容
./build.sh

# 只编译库
./build.sh library

# 编译特定示例
./build.sh basic_example

# 查看帮助
./build.sh help

构建输出

编译完成后,文件结构如下:

build/
├── lib/
│   └── libmultibutton.a    # 静态库
├── bin/
│   ├── basic_example       # 基础示例
│   ├── advanced_example    # 高级示例
│   └── poll_example        # 轮询示例
└── obj/                    # 目标文件

示例程序

1. 基础示例 (examples/basic_example.c)

演示基本的按键事件处理:

./build/bin/basic_example

功能:

  • 单击、双击、长按检测
  • 重复按下计数
  • 按键状态查询
  • 自动化演示序列

2. 高级示例 (examples/advanced_example.c)

演示高级功能和动态管理:

# 运行完整演示
./build/bin/advanced_example

# 详细输出模式
./build/bin/advanced_example -v

# 安静模式 (手动测试)
./build/bin/advanced_example -q

功能:

  • 多按键管理
  • 动态回调函数添加/移除
  • 配置按键
  • 运行时状态监控

3. 轮询示例 (examples/poll_example.c)

演示轮询模式使用:

./build/bin/poll_example

功能:

  • 无回调函数的轮询模式
  • 事件状态查询
  • 主循环集成示例
  • 预定义按键模式演示

快速开始

1. 包含头文件

#include "multi_button.h"

2. 定义按键实例

static Button btn1;

3. 实现 GPIO 读取函数

uint8_t read_button_gpio(uint8_t button_id)
{
    switch (button_id) {
        case 1:
            return HAL_GPIO_ReadPin(BUTTON1_GPIO_Port, BUTTON1_Pin);
        default:
            return 0;
    }
}

4. 初始化按键

// 初始化按键 (active_level: 0=低电平有效, 1=高电平有效)
button_init(&btn1, read_button_gpio, 0, 1);

5. 注册事件回调

void btn1_single_click_handler(void* btn)
{
    printf("Button 1: Single Click\n");
}

button_attach(&btn1, BTN_SINGLE_CLICK, btn1_single_click_handler);

6. 启动按键处理

button_start(&btn1);

7. 定时调用处理函数

// 在 5ms 定时器中断中调用
void timer_5ms_interrupt_handler(void)
{
    button_ticks();
}

API 参考

按键事件类型

typedef enum {
    BTN_PRESS_DOWN = 0,     // 按键按下
    BTN_PRESS_UP,           // 按键抬起
    BTN_PRESS_REPEAT,       // 重复按下检测
    BTN_SINGLE_CLICK,       // 单击完成
    BTN_DOUBLE_CLICK,       // 双击完成
    BTN_LONG_PRESS_START,   // 长按开始
    BTN_LONG_PRESS_HOLD,    // 长按保持
    BTN_NONE_PRESS          // 无事件
} ButtonEvent;

核心函数

void button_init(Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id)

功能: Initialize button instance
参数:

  • handle: 按键句柄
  • pin_level: GPIO 读取函数指针
  • active_level: 有效电平 (0 或 1)
  • button_id: 按键 ID

void button_attach(Button* handle, ButtonEvent event, BtnCallback cb)

功能: Attach event callback function
参数:

  • handle: 按键句柄
  • event: 事件类型
  • cb: 回调函数

void button_detach(Button* handle, ButtonEvent event)

功能: Detach event callback function
参数:

  • handle: 按键句柄
  • event: 事件类型

int button_start(Button* handle)

功能: Start button processing
返回值: 0=成功, -1=已存在, -2=参数错误

void button_stop(Button* handle)

功能: Stop button processing

void button_ticks(void)

功能: Background processing function (call every 5ms)

工具函数

ButtonEvent button_get_event(Button* handle)

功能: Get current button event

uint8_t button_get_repeat_count(Button* handle)

功能: Get repeat press count

void button_reset(Button* handle)

功能: Reset button state to idle

int button_is_pressed(Button* handle)

功能: Check if button is currently pressed
返回值: 1=按下, 0=未按下, -1=错误

配置选项

multi_button_config.h 中可以自定义以下参数:

#define TICKS_INTERVAL          5       // 定时器中断间隔 (ms)
#define DEBOUNCE_TIME_MS        15      // 去抖时间 (ms)
#define SHORT_PRESS_TIME_MS     300     // 短按时间阈值 (ms)
#define LONG_PRESS_TIME_MS      1000    // 长按时间阈值 (ms)
#define PRESS_REPEAT_MAX_NUM    15      // 最大重复计数

使用注意事项

  1. 定时器设置: 必须配置 5ms 定时器中断,在中断中调用 button_ticks()
  2. GPIO 配置: 按键引脚需配置为输入模式,根据需要启用上拉或下拉电阻
  3. 回调函数: 回调函数应尽量简短,避免长时间阻塞
  4. 内存管理: 按键实例可以是全局变量或动态分配
  5. 多按键: 每个物理按键需要独立的 Button 实例和唯一的 button_id

状态机说明

[IDLE] --按下--> [PRESS] --长按--> [LONG_HOLD]
   ^                |                    |
   |             抬起|                 抬起|
   |                v                    |
   |          [RELEASE] <----------------+
   |          |       ^
   |       超时|       |快速按下
   |          |       |
   +----------+   [REPEAT]

项目结构

MultiButton/
├── multi_button.h          # 主头文件
├── multi_button.c          # 主源文件
├── Makefile               # 构建脚本
├── build.sh               # 备用构建脚本
├── examples/              # 示例目录
│   ├── basic_example.c    # 基础示例
│   ├── advanced_example.c # 高级示例
│   └── poll_example.c     # 轮询示例
├── build/                 # 构建输出目录
│   ├── lib/              # 库文件
│   ├── bin/              # 可执行文件
│   └── obj/              # 目标文件
└── README.md             # 说明文档

兼容性

  • C99 标准
  • 适用于各种微控制器平台 (STM32, Arduino, ESP32, etc.)
  • 支持裸机和 RTOS 环境
  • 内存占用小,适合资源受限的系统

About

Button driver for embedded system

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 15

脸大适合什么发型 右眉上方有痣代表什么 售后服务是做什么的 什么地摇动 新生儿吐奶是什么原因
糖尿病2型是什么意思 沙葱是什么 牙齿什么颜色最健康 两会什么时候开 什么呀
来月经喝啤酒有什么影响 11点多是什么时辰 指甲长出来是白色的什么原因 维生素d和d3有什么区别 八月十号是什么星座
长湿疹是什么原因引起的 胎儿fl是什么意思 编者按是什么意思 细水长流是什么生肖 1970属什么
籍贯指的是什么bfb118.com 儿童手指头脱皮什么原因引起的beikeqingting.com 摩罗丹主要治什么胃病hcv7jop6ns7r.cn 灵芝有什么功效与作用fenrenren.com 胃不舒服恶心想吐吃什么药hcv9jop3ns2r.cn
金钱草长什么样子图片kuyehao.com 部分导联st段改变是什么意思hcv7jop6ns4r.cn dic是什么意思sanhestory.com 贵州有什么特产hcv7jop5ns1r.cn 股票pe是什么意思hcv9jop8ns0r.cn
股票举牌什么意思hcv8jop5ns0r.cn 未曾谋面什么意思hcv9jop6ns0r.cn 五月二十日是什么日子hcv9jop5ns0r.cn 吃什么hcv7jop9ns8r.cn 知乎是干什么的hcv9jop6ns4r.cn
吐白痰是什么原因hcv9jop1ns7r.cn 吃什么可以祛痘排毒hcv8jop9ns3r.cn 糍粑是什么做的hcv8jop1ns7r.cn 肉丝炒什么菜好吃hcv9jop6ns4r.cn 胆碱能性荨麻疹吃什么药hcv7jop6ns7r.cn
百度