千家信息网

纯C语言实现的按键驱动Button_drive的实例用法

发表于:2025-01-23 作者:千家信息网编辑
千家信息网最后更新 2025年01月23日,这篇文章主要讲解了"纯C语言实现的按键驱动Button_drive的实例用法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"纯C语言实现的按键驱动But
千家信息网最后更新 2025年01月23日纯C语言实现的按键驱动Button_drive的实例用法

这篇文章主要讲解了"纯C语言实现的按键驱动Button_drive的实例用法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"纯C语言实现的按键驱动Button_drive的实例用法"吧!

Button_drive简介

Button_drive是一个小巧的按键驱动,支持单击、双击、长按、连续触发等(后续可以在按键控制块中添加触发事件),理论上可无限量扩展Button,Button_drive采用按键触发事件回调方式处理业务逻辑,支持在RTOS中使用,我目前仅在RT-Thread上测试过。 写按键驱动的目的是想要将用户按键逻辑与按键处理事件分离,用户无需处理复杂麻烦的逻辑事件。

Button_drive使用效果

  1. 单击与长按

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2nhPnwqF-1571148176402)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/1.png?raw=true)]

  1. 双击

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wtGvjTjq-1571148176403)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/2.png?raw=true)]

  1. 连按

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QUypOh3s-1571148176403)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/3.png?raw=true)]

  1. 连按释放

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LfsbuM1W-1571148176404)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/4.png?raw=true)]

使用方法

  1. 创建按键句柄

Button_t Button1;Button_t Button2;
  1. 创建按键,初始化按键信息,包括按键名字、按键电平检测函数接口、按键触发电平。

  Button_Create("Button1",                            //按键名字                &Button1,                              //按键句柄                Read_Button1_Level,        //按键电平检测函数接口                BTN_TRIGGER);                    //触发电平                                ......
  1. 按键触发事件与事件回调函数链接映射,当按键事件被触发的时候,自动跳转回调函数中处理业务逻辑。

  Button_Attach(&Button1,BUTTON_DOWM,Btn2_Dowm_CallBack);           //按键单击  Button_Attach(&Button1,BUTTON_DOUBLE,Btn2_Double_CallBack);     //双击  Button_Attach(&Button1,BUTTON_LONG,Btn2_Long_CallBack);         //长按                                                                .......
  1. 周期调用回调按键处理函数即可,建议调用周期20-50ms。

Button_Process();     //需要周期调用按键处理函数

需要用户实现的 2 个函数:

  • 按键电平检测接口:

uint8_t Read_Button1_Level(void){  return GPIO_ReadInputDataBit(BTN1_GPIO_PORT,BTN1_GPIO_PIN);}uint8_t Read_Button2_Level(void){  return GPIO_ReadInputDataBit(BTN2_GPIO_PORT,BTN2_GPIO_PIN);}// 这是我在stm32上简单测试的伪代码,以实际源码为准
  • 按键逻辑处理

void Btn1_Dowm_CallBack(void *btn){  PRINT_INFO("Button1 单击!");}void Btn1_Double_CallBack(void *btn){  PRINT_INFO("Button1 双击!");}void Btn1_Long_CallBack(void *btn){  PRINT_INFO("Button1 长按!");    Button_Delete(&Button2);  PRINT_INFO("删除Button1");  Search_Button();}

特点

Button_drive开放源码,按键控制块采用数据结构方式,按键事件采用枚举类型,确保不会重复,也便于添加用户需要逻辑,采用宏定义方式定义消抖时间、连按触发时间、双击时间间隔、长按时间等,便于修改。 同时所有被创建的按键采用单链表方式连击,用户只管创建,无需理会按键处理,只需调用Button_Process()即可,在函数中会自动遍历所有被创建的按键。 支持按键删除操作,用户无需在代码中删除对应的按键创建于映射链接代码,也无需删除关于按键的任何回调事件处理函数,只需调用Button_Delete()函数即可,这样子,就不会处理关于被删除按键的任何状态。当然目前按键内存不会释放,如果使用os的话,建议释放按键内存。

按键控制块
/*        每个按键对应1个全局的结构体变量。        其成员变量是实现消抖和多种按键状态所必须的*/typedef struct button{        /* 下面是一个函数指针,指向判断按键手否按下的函数 */        uint8_t (*Read_Button_Level)(void); /* 读取按键电平函数,需要用户实现 */    char Name[BTN_NAME_MAX];        uint8_t Button_State              :   4;    /* 按键当前状态(按下还是弹起) */  uint8_t Button_Last_State         :   4;     /* 上一次的按键状态,用于判断双击 */  uint8_t Button_Trigger_Level      :   2;    /* 按键触发电平 */  uint8_t Button_Last_Level         :   2;    /* 按键当前电平 */    uint8_t Button_Trigger_Event;     /* 按键触发事件,单击,双击,长按等 */    Button_CallBack CallBack_Function[number_of_event];  uint8_t Button_Cycle;             /* 连续按键周期 */    uint8_t Timer_Count;                   /* 计时 */  uint8_t Debounce_Time;         /* 消抖时间 */    uint8_t Long_Time;               /* 按键按下持续时间 */    struct button *Next;  }Button_t;
触发事件
typedef enum {  BUTTON_DOWM = 0,  BUTTON_UP,  BUTTON_DOUBLE,  BUTTON_LONG,  BUTTON_CONTINUOS,  BUTTON_CONTINUOS_FREE,  BUTTON_ALL_RIGGER,  number_of_event, /* 触发回调的事件 */  NONE_TRIGGER}Button_Event;
宏定义选择
#define BTN_NAME_MAX  32     //名字最大为32字节/* 按键消抖时间40ms, 建议调用周期为20ms 只有连续检测到40ms状态不变才认为有效,包括弹起和按下两种事件*/#define CONTINUOS_TRIGGER             0  //是否支持连续触发,连发的话就不要检测单双击与长按了    /* 是否支持单击&双击同时存在触发,如果选择开启宏定义的话,单双击都回调,只不过单击会延迟响应,   因为必须判断单击之后是否触发了双击否则,延迟时间是双击间隔时间 BUTTON_DOUBLE_TIME。   而如果不开启这个宏定义,建议工程中只存在单击/双击中的一个,否则,在双击响应的时候会触发一次单击,   因为双击必须是有一次按下并且释放之后才产生的 */#define SINGLE_AND_DOUBLE_TRIGGER     1 /* 是否支持长按释放才触发,如果打开这个宏定义,那么长按释放之后才触发单次长按,   否则在长按指定时间就一直触发长按,触发周期由 BUTTON_LONG_CYCLE 决定 */#define LONG_FREE_TRIGGER             0 #define BUTTON_DEBOUNCE_TIME    2   //消抖时间      (n-1)*调用周期#define BUTTON_CONTINUOS_CYCLE  1          //连按触发周期时间  (n-1)*调用周期  #define BUTTON_LONG_CYCLE       1         //长按触发周期时间  (n-1)*调用周期 #define BUTTON_DOUBLE_TIME      15      //双击间隔时间  (n-1)*调用周期  建议在200-600ms#define BUTTON_LONG_TIME            50          /* 持续n秒((n-1)*调用周期 ms),认为长按事件 */#define TRIGGER_CB(event)   \        if(btn->CallBack_Function[event]) \          btn->CallBack_Function[event]((Button_t*)btn)
例子
  Button_Create("Button1",              &Button1,               Read_KEY1_Level,               KEY_ON);  Button_Attach(&Button1,BUTTON_DOWM,Btn1_Dowm_CallBack);                       //单击  Button_Attach(&Button1,BUTTON_DOUBLE,Btn1_Double_CallBack);                   //双击  Button_Attach(&Button1,BUTTON_CONTINUOS,Btn1_Continuos_CallBack);             //连按    Button_Attach(&Button1,BUTTON_CONTINUOS_FREE,Btn1_ContinuosFree_CallBack);    //连按释放    Button_Attach(&Button1,BUTTON_LONG,Btn1_Long_CallBack);                       //长按  Button_Create("Button2",              &Button2,               Read_KEY2_Level,               KEY_ON);  Button_Attach(&Button2,BUTTON_DOWM,Btn2_Dowm_CallBack);                     //单击  Button_Attach(&Button2,BUTTON_DOUBLE,Btn2_Double_CallBack);                 //双击  Button_Attach(&Button2,BUTTON_CONTINUOS,Btn2_Continuos_CallBack);           //连按  Button_Attach(&Button2,BUTTON_CONTINUOS_FREE,Btn2_ContinuosFree_CallBack);  //连按释放  Button_Attach(&Button2,BUTTON_LONG,Btn2_Long_CallBack);                     //长按  Get_Button_Event(&Button1);  Get_Button_Event(&Button2);

后续

流光大佬的要求,让我玩一玩RTT的rtkpgs,打算用Button_drive练一练手吧。

ButtonDrive在env使用

目前我已将按键驱动做成软件包(packages),如果使用RT-Thread操作系统的话,可以在env中直接配置使用!

步骤如下:

  1. 选择在线软件包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gG59d3Yn-1571148176404)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/5.png?raw=true)]

  1. 选择软件包属性为外设相关

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-amGYFH8P-1571148176404)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/6.png?raw=true)]

  1. 选择button_drive

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O0a0wqdi-1571148176404)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/7.png?raw=true)]

  1. 进入驱动的选项配置(自带默认属性)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O5sGP0CE-1571148176405)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/8.png?raw=true)]

  1. 如果不懂按键的配置是什么意思,按下"shift+?",即可有解释

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EYxByBVm-1571148176407)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/9.png?raw=true)]

  1. 编译生成mdk/iar工程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e0pdTFhz-1571148176407)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/10.png?raw=true)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lXNX8VeJ-1571148176407)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/11.png?raw=true)]

关于rtkpgs

简介 (English)

buildpkg 是用于生成 RT-Thread package 的快速构建工具。

一个优秀的 package 应该是这样的:

  1. 代码优雅, 规范化。

  2. examples 例程,提供通俗易懂的使用例程。

  3. SConscript 文件,用于和 RT-Thread 环境一起进行编译。

  4. README.md 文档,向用户提供必要的功能说明。

  5. docs 文件夹, 放置除了 README 之外的其他细节文档。

  6. license 许可文件,版权说明。

为了方便快速的生成 RT-Thread package 规范化模板 以及 减轻开源仓库迁移 RT-Thread 的前期准备工作的负担,基于此目的的 buildpkg 应运而生,为开发 Rt-Thread 的 package 的开发者提供辅助开发工具。

序号支持功能描述
1构建 package 模板创建指定名称 package , 自动添加 readme /版本号/ github ci脚本/demo/开源协议文件
2迁移开源仓库从指定 git 仓库构建 package , 自动添加readme/版本号/ github ci脚本/demo/开源协议文件, 但是迁移的仓库需要用户自己按照实际情况修改
3更新 package生成package后可以再次更新之前设定的版本号,开源协议或者scons脚本等

使用说明

1. 构建package

buildpkg.exe make pkgdemo

2. 迁移开源仓库

buildpkg.exe make cstring https://github.com/liu2guang/cstring.git

3. 更新package

buildpkg.exe update pkgname

4. 可选配置

长参数短参数描述
--version=v1.0.0-v v1.0.0设置 package 的版本
--license=MIT-l MIT设置 package 所遵循的版权协议
--submodule-s删除 git 子模块

Windows10 及 Linux 平台的演示动图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CT6Hxh38-1571148176408)(/figures/buildpkg.gif)]

测试平台

序号测试平台测试结果
1win10exe测试通过, py测试通过
2win7exe待测试, py待测试
3macpy脚本不知道是否兼容, 没有测试条件, 后面维护下
4linuxpy脚本不知道是否兼容, 没有测试条件, 后面维护下

感谢各位的阅读,以上就是"纯C语言实现的按键驱动Button_drive的实例用法"的内容了,经过本文的学习后,相信大家对纯C语言实现的按键驱动Button_drive的实例用法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0