Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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

AltStyle によって変換されたページ (->オリジナル) /