You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
3 years ago | |
|---|---|---|
| examples | 3 years ago | |
| LICENSE | 8 years ago | |
| README.md | 3 years ago | |
| multi_button.c | 3 years ago | |
| multi_button.h | 3 years ago | |
README.md
MultiButton
简介
MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰。
使用方法
1.先申请一个按键结构
struct Button button1;
2.初始化按键对象,绑定按键的GPIO电平读取接口read_button_pin() ,后一个参数设置有效触发电平
button_init(&button1, read_button_pin, 0);
3.注册按键事件
button_attach(&button1, SINGLE_CLICK, BTN_EVENT_Handler);
button_attach(&button1, DOUBLE_CLICK, BTN_EVENT_Handler);
...
4.启动按键
button_start(&button1);
5.设置一个5ms间隔的定时器循环调用后台处理函数
while(1) {
...
if(timer_ticks == 5) {
timer_ticks = 0;
button_ticks();
}
}
特性
MultiButton 使用C语言实现,基于面向对象方式设计思路,每个按键对象单独用一份数据结构管理:
struct Button {
uint16_t ticks;
uint8_t repeat: 4;
uint8_t event : 4;
uint8_t state : 3;
uint8_t debounce_cnt : 3;
uint8_t active_level : 1;
uint8_t button_level : 1;
uint8_t (*hal_button_Level)(void);
BtnCallback cb[number_of_event];
struct Button* next;
};
这样每个按键使用单向链表相连,依次进入 button_handler(struct Button* handle) 状态机处理,所以每个按键的状态彼此独立。
按键事件
| 事件 | 说明 |
|---|---|
| PRESS_DOWN | 按键按下,每次按下都触发 |
| PRESS_UP | 按键弹起,每次松开都触发 |
| PRESS_REPEAT | 重复按下触发,变量repeat计数连击次数 |
| SINGLE_CLICK | 单击按键事件 |
| DOUBLE_CLICK | 双击按键事件 |
| LONG_PRESS_START | 达到长按时间阈值时触发一次 |
| LONG_PRESS_HOLD | 长按期间一直触发 |
Examples
#include "multi_button.h"
typedef enum {
BUTTON_ID_0,
BUTTON_ID_2,
BUTTON_ID_MAX
} BUTTON_ID_INDEX;
struct Button btnGroup[BUTTON_ID_MAX];
uint8_t btnActiveLevel[BUTTON_ID_MAX] = {0, 0};
uint8_t read_button_level()
{
uint8_t code = 0x01;
for (size_t i = 0; i < BUTTON_ID_MAX; i++)
{
if (get_button_current() == &btnGroup[i])
{
switch (i)
{
case BUTTON_ID_0:
code = HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin);
break;
case BUTTON_ID_2:
code = HAL_GPIO_ReadPin(B2_GPIO_Port, B2_Pin);
break;
default:
break;
}
}
}
return code;
}
void BTN_EVENT_Handler(void *btn)
{
for (size_t i = 0; i < BUTTON_ID_MAX; i++)
{
if (((Button *)btn) == &btnGroup[i])
{
switch (((Button *)btn)->event)
{
case PRESS_DOWN:
switch (i)
{
case BUTTON_ID_0:
// do something
break;
case BUTTON_ID_2:
// do something
break;
default:
break;
}
break;
case PRESS_UP:
switch (i)
{
case BUTTON_ID_0:
// do something
break;
case BUTTON_ID_2:
// do something
break;
default:
break;
}
break;
case PRESS_REPEAT:
switch (i)
{
case BUTTON_ID_0:
// do something
break;
case BUTTON_ID_2:
// do something
break;
default:
break;
}
break;
case SINGLE_CLICK:
switch (i)
{
case BUTTON_ID_0:
// do something
break;
case BUTTON_ID_2:
// do something
break;
default:
break;
}
break;
case DOUBLE_CLICK:
switch (i)
{
case BUTTON_ID_0:
// do something
break;
case BUTTON_ID_2:
// do something
break;
default:
break;
}
break;
case LONG_PRESS_START:
switch (i)
{
case BUTTON_ID_0:
// do something
break;
case BUTTON_ID_2:
// do something
break;
default:
break;
}
break;
case LONG_PRESS_HOLD:
switch (i)
{
case BUTTON_ID_0:
// do something
break;
case BUTTON_ID_2:
// do something
break;
default:
break;
}
break;
default:
break;
}
}
}
}
int main()
{
for (size_t i = 0; i < BUTTON_ID_MAX; i++)
{
button_init(&btnGroup[i], read_button_level, btnActiveLevel[i]);
button_attach(&btnGroup[i], PRESS_DOWN, BTN_EVENT_Handler);
button_attach(&btnGroup[i], PRESS_UP, BTN_EVENT_Handler);
button_attach(&btnGroup[i], PRESS_REPEAT, BTN_EVENT_Handler);
button_attach(&btnGroup[i], SINGLE_CLICK, BTN_EVENT_Handler);
button_attach(&btnGroup[i], DOUBLE_CLICK, BTN_EVENT_Handler);
button_attach(&btnGroup[i], LONG_PRESS_START, BTN_EVENT_Handler);
button_attach(&btnGroup[i], LONG_PRESS_HOLD, BTN_EVENT_Handler);
button_start(&btnGroup[i]);
}
// make the timer invoking the button_ticks() interval 5ms.
// This function is implemented by yourself.
__timer_start(button_ticks, 0, 5);
while (1)
{
}
}