照着别人网站做,可以制作视频的软件,青浦建设机械网站,厦门城乡建设厅网站MultiButton MultiButton简介使用方法特性按键事件Examples 具体实现代码multi_button.cmulti_button.h MultiButton
简介
MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块#xff0c;可无限量扩展按键#xff0c;按键事件的回调异步处理方式可以简化你的程序结构… MultiButton MultiButton简介使用方法特性按键事件Examples 具体实现代码multi_button.cmulti_button.h MultiButton
简介
MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块可无限量扩展按键按键事件的回调异步处理方式可以简化你的程序结构去除冗余的按键处理硬编码让你的按键业务逻辑更清晰。
使用方法
1.先申请一个按键结构
struct Button button1;2.初始化按键对象绑定按键的GPIO电平读取接口read_button_pin() 后一个参数设置有效触发电平
button_init(button1, read_button_pin, 0, 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 button_id;uint8_t (*hal_button_Level)(uint8_t button_id_);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 button.hunit8_t btn1_id 0;struct Button btn1;uint8_t read_button_GPIO(uint8_t button_id)
{// you can share the GPIO read function with multiple Buttonsswitch(button_id){case btn1_id:return HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin);break;default:return 0;break;}
}
void BTN1_PRESS_DOWN_Handler(void* btn)
{//do something...
}void BTN1_PRESS_UP_Handler(void* btn)
{//do something...
}...int main()
{button_init(btn1, read_button_GPIO, 0, btn1_id);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_PRESS_START, BTN1_LONG_PRESS_START_Handler);button_attach(btn1, 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){}
}具体实现代码
multi_button.c
/** Copyright (c) 2016 Zibin Zheng znbinqq.com* All rights reserved*/#include multi_button.h#define EVENT_CB(ev) if(handle-cb[ev])handle-cb[ev]((void*)handle)
#define PRESS_REPEAT_MAX_NUM 15 /*! The maximum value of the repeat counter *///button handle list head.
static struct Button* head_handle NULL;static void button_handler(struct Button* handle);/*** brief Initializes the button struct handle.* param handle: the button handle struct.* param pin_level: read the HAL GPIO of the connected button level.* param active_level: pressed GPIO level.* param button_id: the button id.* retval None*/
void button_init(struct Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id)
{memset(handle, 0, sizeof(struct Button));handle-event (uint8_t)NONE_PRESS;handle-hal_button_Level pin_level;handle-button_level handle-hal_button_Level(button_id);handle-active_level active_level;handle-button_id button_id;
}/*** brief Attach the button event callback function.* param handle: the button handle struct.* param event: trigger event type.* param cb: callback function.* retval None*/
void button_attach(struct Button* handle, PressEvent event, BtnCallback cb)
{handle-cb[event] cb;
}/*** brief Inquire the button event happen.* param handle: the button handle struct.* retval button event.*/
PressEvent get_button_event(struct Button* handle)
{return (PressEvent)(handle-event);
}/*** brief Button driver core function, driver state machine.* param handle: the button handle struct.* retval None*/
static void button_handler(struct Button* handle)
{uint8_t read_gpio_level handle-hal_button_Level(handle-button_id);//ticks counter working..if((handle-state) 0) handle-ticks;/*------------button debounce handle---------------*/if(read_gpio_level ! handle-button_level) { //not equal to prev one//continue read 3 times same new level changeif((handle-debounce_cnt) DEBOUNCE_TICKS) {handle-button_level read_gpio_level;handle-debounce_cnt 0;}} else { //level not change ,counter reset.handle-debounce_cnt 0;}/*-----------------State machine-------------------*/switch (handle-state) {case 0:if(handle-button_level handle-active_level) { //start press downhandle-event (uint8_t)PRESS_DOWN;EVENT_CB(PRESS_DOWN);handle-ticks 0;handle-repeat 1;handle-state 1;} else {handle-event (uint8_t)NONE_PRESS;}break;case 1:if(handle-button_level ! handle-active_level) { //released press uphandle-event (uint8_t)PRESS_UP;EVENT_CB(PRESS_UP);handle-ticks 0;handle-state 2;} else if(handle-ticks LONG_TICKS) {handle-event (uint8_t)LONG_PRESS_START;EVENT_CB(LONG_PRESS_START);handle-state 5;}break;case 2:if(handle-button_level handle-active_level) { //press down againhandle-event (uint8_t)PRESS_DOWN;EVENT_CB(PRESS_DOWN);if(handle-repeat ! PRESS_REPEAT_MAX_NUM) {handle-repeat;}EVENT_CB(PRESS_REPEAT); // repeat hithandle-ticks 0;handle-state 3;} else if(handle-ticks SHORT_TICKS) { //released timeoutif(handle-repeat 1) {handle-event (uint8_t)SINGLE_CLICK;EVENT_CB(SINGLE_CLICK);} else if(handle-repeat 2) {handle-event (uint8_t)DOUBLE_CLICK;EVENT_CB(DOUBLE_CLICK); // repeat hit}handle-state 0;}break;case 3:if(handle-button_level ! handle-active_level) { //released press uphandle-event (uint8_t)PRESS_UP;EVENT_CB(PRESS_UP);if(handle-ticks SHORT_TICKS) {handle-ticks 0;handle-state 2; //repeat press} else {handle-state 0;}} else if(handle-ticks SHORT_TICKS) { // SHORT_TICKS press down hold time LONG_TICKShandle-state 1;}break;case 5:if(handle-button_level handle-active_level) {//continue hold triggerhandle-event (uint8_t)LONG_PRESS_HOLD;EVENT_CB(LONG_PRESS_HOLD);} else { //releasedhandle-event (uint8_t)PRESS_UP;EVENT_CB(PRESS_UP);handle-state 0; //reset}break;default:handle-state 0; //resetbreak;}
}/*** brief Start the button work, add the handle into work list.* param handle: target handle struct.* retval 0: succeed. -1: already exist.*/
int button_start(struct Button* handle)
{struct Button* target head_handle;while(target) {if(target handle) return -1; //already exist.target target-next;}handle-next head_handle;head_handle handle;return 0;
}/*** brief Stop the button work, remove the handle off work list.* param handle: target handle struct.* retval None*/
void button_stop(struct Button* handle)
{struct Button** curr;for(curr head_handle; *curr; ) {struct Button* entry *curr;if(entry handle) {*curr entry-next;
// free(entry);return;//glacier add 2021-8-18} else {curr entry-next;}}
}/*** brief background ticks, timer repeat invoking interval 5ms.* param None.* retval None*/
void button_ticks(void)
{struct Button* target;for(targethead_handle; target; targettarget-next) {button_handler(target);}
}
multi_button.h
/** Copyright (c) 2016 Zibin Zheng znbinqq.com* All rights reserved*/#ifndef _MULTI_BUTTON_H_
#define _MULTI_BUTTON_H_#include stdint.h
#include string.h//According to your need to modify the constants.
#define TICKS_INTERVAL 5 //ms
#define DEBOUNCE_TICKS 3 //MAX 7 (0 ~ 7)
#define SHORT_TICKS (300 /TICKS_INTERVAL)
#define LONG_TICKS (1000 /TICKS_INTERVAL)typedef void (*BtnCallback)(void*);typedef enum {PRESS_DOWN 0,PRESS_UP,PRESS_REPEAT,SINGLE_CLICK,DOUBLE_CLICK,LONG_PRESS_START,LONG_PRESS_HOLD,number_of_event,NONE_PRESS
}PressEvent;typedef 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 button_id;uint8_t (*hal_button_Level)(uint8_t button_id_);BtnCallback cb[number_of_event];struct Button* next;
}Button;#ifdef __cplusplus
extern C {
#endifvoid button_init(struct Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id);
void button_attach(struct Button* handle, PressEvent event, BtnCallback cb);
PressEvent get_button_event(struct Button* handle);
int button_start(struct Button* handle);
void button_stop(struct Button* handle);
void button_ticks(void);#ifdef __cplusplus
}
#endif#endif
这段代码实现了一个多按钮驱动库用于处理单片机中多个按钮的按键事件。下面是对代码的详细解释 数据结构定义 Button 结构体定义了一个按钮的属性包括按下时间、重复次数、当前事件、当前状态等信息。PressEvent 枚举定义了按钮可能触发的事件类型包括按下、释放、重复按下、单击、双击、长按开始和长按持续等事件。 函数说明 button_init初始化按钮结构体设置按钮的GPIO读取函数、活动电平、按钮ID等参数。button_attach绑定按钮的事件回调函数用于处理不同事件时的操作。get_button_event获取按钮当前的事件类型。button_start开始监听按钮事件将按钮添加到事件处理列表中。button_stop停止监听按钮事件将按钮从事件处理列表中移除。button_ticks定时器中断处理函数用于处理按钮的状态机逻辑。 按钮状态机 按钮状态机包括了按下、释放、重复按下、单击、双击和长按等状态。每次定时器中断会调用 button_handler 函数处理按钮的状态转换和事件触发。 事件处理 当按钮按下时触发 PRESS_DOWN 事件当按钮释放时触发 PRESS_UP 事件。当按钮按下时间超过一定时间时触发 LONG_PRESS_START 事件持续按下时触发 LONG_PRESS_HOLD 事件。当按钮连续按下时触发 SINGLE_CLICK 或 DOUBLE_CLICK 事件。 其他说明 定义了一些常量用于设置按钮的时间阈值和抖动时间。使用了链表结构管理多个按钮可以方便地添加、删除和遍历按钮列表。
这段代码实现了一个简单但功能强大的多按钮驱动库可以方便地集成到单片机的项目中实现按钮事件的处理和响应。