查看原文
其他

完全由C编写,高度可移植,超级牛逼的按键驱动机制!

晓宇 芯片之家 2021-01-31

作为一个搞电子嵌入式的你来说,按键驱动相信绝对不陌生,比如让你实现一些按键按下,按键松开,单击、双击、长按等不同的机制,你是否有一个很好的程序框架?前几天芯片之家1群里有个朋友(备注名:北京-单片机-顺顺)在群里分享了GitHub上一个很不错的按键驱动机制(作者:liu2guang),看了确实不错,移植很方便,并且附带RT-Thread的例子,这里分享给大家!公众号后台回复:  按键驱动   下载源代码。


MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰。


使用方法

1.先申请一个按键结构

struct Button button1;

2.初始化按键对象,绑定按键的GPIO电平读取接口read_button_pin() ,后一个参数设置有效触发电平

button_init(&button1, read_button_pin, 0);

3.注册按键事件

button_attach(&button1, SINGLE_CLICK, Callback_SINGLE_CLICK_Handler);
button_attach(&button1, DOUBLE_CLICK, Callback_DOUBLE_Click_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_RRESS_START

达到长按时间阈值时触发一次    

LONG_PRESS_HOLD

长按期间一直触发

Examples

#include "button.h"

struct Button btn1;

int read_button1_GPIO()
{
 return HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin);
}

int main()
{
 button_init(&btn1, read_button1_GPIO, 0);
 button_attach(&btn1, PRESS_DOWN,       BTN1_PRESS_DOWN_Handler);
 button_attach(&btn1, PRESS_UP,         BTN1_PRESS_UP_Handler);
 button_attach(&btn1, PRESS_REPEAT,     BTN1_PRESS_REPEAT_Handler);
 button_attach(&btn1, SINGLE_CLICK,     BTN1_SINGLE_Click_Handler);
 button_attach(&btn1, DOUBLE_CLICK,     BTN1_DOUBLE_Click_Handler);
 button_attach(&btn1, LONG_RRESS_START, BTN1_LONG_RRESS_START_Handler);
 button_attach(&btn2, LONG_PRESS_HOLD,  BTN1_LONG_PRESS_HOLD_Handler);
 button_start(&btn1);
 
 //make the timer invoking the button_ticks() interval 5ms.
 //This function is implemented by yourself.
 __timer_start(button_ticks, 0, 5);
 
 while(1)
 {}
}

void BTN1_PRESS_DOWN_Handler(void* btn)
{
 //do something...
}

void BTN1_PRESS_UP_Handler(void* btn)
{
 //do something...
}

...
往期好文

完全由C编写,高度可移植,超级牛逼的软件定时器!


超级炫酷的LED数字变换算法,你能写的出吗?


【拆解】小米AI音箱,看看小爱同学内部究竟有什么


【拆解】斐讯AI智能音箱R1,内部究竟采用了什么?


【视频】老外教你学电子系列第13期-第15期,我就不信还有不懂的!


【最强干货】618个3D封装免费分享


阿里巴巴人工智能实验室2018春季发布会完整版视频


MPS软件帮您搞定DC-DC电源设计!


天呐!身为电子工程师的你,竟然还在用百度找资料?

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存