乳房结节是什么原因引起的| 4月19是什么星座| 投资公司是做什么的| 邪祟是什么意思| 男人第一次什么 感觉| 阳历7月15日是什么星座| 鼻屎多是什么原因| 对立面是什么意思| 静息是什么意思| 8月20号什么星座| 身上起红点是什么原因| 5.7是什么星座| 梦见买帽子是什么意思| 腺病毒是什么病毒| 乙肝抗体是什么意思| 胃食管反流挂什么科| 芒果是什么意思| 什么时候洗头是最佳时间| 微光是什么意思| 贫血是什么引起的| 桃子不能和什么一起吃| 办理慢性病需要什么手续| 277是什么意思| 乌黑对什么| 淋巴结转移是什么意思| 可颂是什么意思| 小沈阳属什么生肖| 褒义是什么意思| glu是什么氨基酸| 为什么会突然头晕| 孕酮低有什么影响| 什么的礼物| 航母舰长是什么级别| 左肺结节是什么意思| 榧读什么| 6月13号是什么星座| 瘢痕子宫是什么意思| 12颗珠子的手串什么意思| 1965年什么时候退休| 下午一点是什么时辰| 肌酸激酶高吃什么药| 气血亏虚吃什么中成药| 出汗吃什么药| 犬和狗有什么区别| 吃花生有什么好处| 什么是六合| 1987年属什么| 吃南瓜子有什么好处| 浪琴表属于什么档次| 什么是职业暴露| 是什么意思啊| 影射是什么意思| 辣皮子是什么| 菜板买什么材质的好| 脑供血不足是什么原因引起的| 目前是什么意思| 法国铁塔叫什么名字| 辰寅卯是什么生肖| 蚂蝗吃什么| 孕妇吃海参对胎儿有什么好处| 扭曲是什么意思| 双侧筛窦粘膜增厚是什么意思| 什么鬼什么神| 霉菌感染什么症状| 胆结石吃什么比较好| 呼吸机vt代表什么| 6月8日什么星座| 夏至是什么| 肝右叶占位是什么意思| 庙是什么意思| 眉毛浓的男人代表什么| 东营有什么大学| 北京中秋节有什么活动| 加是什么生肖| 五爷是什么菩萨| sdnn是什么意思| 胸膈痞闷是什么症状| 黑豆有什么作用| 往事不堪回首是什么意思| 雨中即景什么意思| 用什么药可以缩阴紧致| 利尿剂是什么| 尿蛋白尿潜血同时出现说明什么| 腋下淋巴结肿大挂什么科| 血脂高可以吃什么水果| 吃鹅蛋有什么好处| 全身痒是什么病的前兆| pac是什么| 干咳吃什么药最有效| 胃酸多吃什么药| khaki是什么颜色| 什么的高山填空| 空调开什么模式最凉快| 隔离是什么意思| 一醉方休什么意思| 酱牛肉放什么调料| 豆芽不能和什么一起吃| 呼吸内镜检查什么| 比翼双飞是什么意思| 益生菌是什么| 嫁衣是什么意思| 打日本电话前面加什么| 欧根纱是什么面料| p是什么意思医学| 心脏搭桥和支架有什么区别| 变色龙形容什么样的人| 不时之需是什么意思| 生物制剂是什么药| 夕阳无限好只是近黄昏是什么意思| 鼻血流不停是什么原因| 梦见放鞭炮是什么意思| 热休克蛋白90a检查高是什么原因| 治疗阳痿早泄什么药最好| 杨八妹属什么生肖| 小寒节气的含义是什么| 软组织挫伤是什么意思| 义乌有什么大学| 做无创需要注意什么| 慢性咽炎吃什么药效果最好| 睡觉总是流口水是什么原因| 黑脸是什么意思| 做什么动作可以长高| a股是什么| 什么奶粉对肠胃吸收好| 水银是什么| 学生早餐吃什么方便又营养| 女主是什么意思| 吃完榴莲不能吃什么| 夜盲吃什么维生素| 什么叫同房| 植物神经紊乱用什么药| 尿隐血阳性什么意思| 梦到门牙掉了是什么意思| 什么的金边| 中药液是什么药| 一龙一什么| 毛周角化症用什么药膏| 窦骁的父母是干什么的| 男士私处用什么清洗| 被动什么意思| 知柏地黄丸治什么病| 出家人不打诳语是什么意思| 爱的意义是什么| 丘疹性荨麻疹吃什么药| kappa是什么牌子| 史莱姆是什么意思| 什么奶茶好喝| la是什么品牌| im是什么意思| 孕妇喝什么汤最好最有营养| 临界值是什么意思| 膀胱破裂什么症状| 下午3点到4点是什么时辰| 什么床垫好| 睡觉咳嗽是什么原因| 松针泡水喝有什么功效| 格桑花什么时候开花| 化缘是什么意思| 年终奖是什么意思| bobby什么意思| 女人下身干燥无水是什么原因| 爆单什么意思| 除牛反绒是什么意思| 红牛加什么提高性功能| 掏耳朵咳嗽是什么原因| 晚上喝牛奶有什么好处| 暗渡陈仓什么意思| 牛油果和什么榨汁好喝| 吃什么可以提高代谢| 炸薯条用什么油| 甲状腺挂什么科| DDP是什么| hpv是指什么| 痛经吃什么止疼药| 春秋鼎盛是什么意思| 毒龙钻什么意思| 晒伤用什么药| 马到成功是什么生肖| 明天是什么| 玩家是什么意思| 1985年属牛的是什么命| 腹泻拉水是什么原因| 追求完美的人什么性格| 申请低保需要什么条件| 海藻糖是什么糖| 仔仔是什么意思| 口子念什么| 美宝莲属于什么档次| 吃什么减脂肪最快最有效的方法| 女人内火旺喝什么降火| 激光脱毛挂什么科| 仁爱是什么意思| 号召是什么意思| 哮喘不能吃什么| 彼此彼此什么意思| 宝宝经常发烧是什么原因引起的| 梦见朋友离婚了是什么意思| 婴儿增强免疫力吃什么| 什么叫二婚线| 除日是什么意思| 印度是什么制度的国家| 痦子和痣有什么区别| 月经期间喝什么好排毒排污血| 摩羯座男生喜欢什么样的女生| 动脉圆锥是什么意思| 高危妊娠监督什么意思| 尖锐是什么意思| 嗓子疼发烧吃什么药| 细胞是什么| npn是什么意思| 早上尿黄是什么原因| 什么农药最毒| 大摇大摆是什么生肖| 灬是什么意思| 请多指教是什么意思| 指纹不清晰是什么原因| 预防水痘吃什么药| 血脂高有什么症状| 什么是邮箱地址应该怎么填写| 里正是什么官| 药剂科是干什么的| 男人吃西红柿有什么好处| 大熊猫生活在什么地方| 山竹是什么味道| 扁桃体溃疡吃什么药| 生姜黄叶病用什么药| 小腹疼痛挂什么科| 梦见车丢了是什么意思| 吃什么容易怀女儿| 话少一般都是什么人| 龙猫吃什么| 狗肉和什么一起炖最佳| 夏天吃什么菜| 皮肤干燥缺什么维生素| 嘴角周围长痘痘是什么原因| 骰子是什么意思| 金牛座女和什么座最配对| 胸腺肿瘤是什么病| 太阳黑子是什么东西| 吃什么受孕率又快又高| 什么的东西| 解脲脲原体阳性是什么| 慢性结肠炎是什么症状| 舅舅的老婆叫什么| 远香近臭什么意思| 日晡潮热是什么意思| 孩子专注力差去什么医院检查| 什么是白平衡| 蒸馏酒是什么酒| 皮肤溃烂是什么病| 2024年是属什么生肖| 乌鸦飞进家里什么征兆| 中华田园犬为什么禁养| 11号来月经什么时候是排卵期| ipa啤酒什么意思| 犟驴是什么意思| 结婚36年是什么婚| 早餐吃什么最好| 口苦吃什么好得快| 居住证签注是什么意思| 肺上有结节是什么病| 屁特别臭是什么原因| 一厢情愿是什么意思| 什么是根管治疗| 百度
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
物欲横流是什么意思 以纯属于什么档次 类风湿是什么病 意思是什么意思 测心率手表什么牌子好
吝啬鬼是什么生肖 吃鹅蛋对孕妇有什么好处 眉毛脱落是什么原因造成的 6月12日是什么星座 宛如是什么意思
投影是什么意思 副司长是什么级别 韩束适合什么年龄段的人用 鹿吃什么 磨牙是什么原因引起的
5.16号是什么星座 宫外孕出血是什么颜色 小混混是什么意思 吴刚和嫦娥什么关系 阶段性是什么意思
男人吃六味地黄丸有什么好处hcv8jop0ns3r.cn 孕妇缺碘对胎儿有什么影响hcv9jop3ns3r.cn 罪恶感什么意思hcv9jop6ns1r.cn 巴甫洛夫的狗比喻什么baiqunet.com 甲状腺挂什么科室hcv8jop9ns1r.cn
无私是什么意思hcv9jop5ns7r.cn 拉肚子吃什么药最有效hcv8jop0ns8r.cn 偷梁换柱是什么意思bjhyzcsm.com 营养神经吃什么药效果好hcv9jop6ns2r.cn 谷草转氨酶高吃什么药hcv8jop4ns5r.cn
两眼中间的位置叫什么hcv8jop1ns6r.cn 帕金森病是什么原因引起的hcv7jop6ns2r.cn 补锌吃什么hcv9jop4ns9r.cn 清什么什么月520myf.com 做凉粉用什么淀粉最好hcv8jop1ns8r.cn
名什么什么实hcv9jop1ns6r.cn 腿浮肿是什么原因hcv7jop9ns2r.cn 广东省省长是什么级别hcv8jop4ns3r.cn 小孩脸上有白斑是什么原因hcv8jop3ns2r.cn 眼珠发黄是什么原因hcv9jop4ns5r.cn
百度