灵活的按键处理程序 FlexibleButton,C程序编写,无缝兼容任意的处理器,支持任意 OS 和 non-OS

2023-05-16

灵活的按键处理程序 FlexibleButton

    • 前言
    • 概述
    • 获取
    • 测试
    • DEMO 程序说明
      • 程序入口
      • 用户初始化代码
      • 事件处理代码
    • FlexibleButton 代码说明
      • 按键事件定义
      • 按键注册接口
      • 按键事件读取接口
      • 按键扫描接口
    • 问题和建议

前言

正好工作中用到按键处理,需要处理单击、长按等按键事件,然后就造了这么一个轮子,为了以后更方便地加入其它的项目中使用,遂将其开源到 GitHub 中。

后面发现 RT-Thread 软件包里也有一个开源的按键库 MultiButton,看到这个按键库的时候,心想,完了,又重复造轮子了,好伤心 ?。想想,既然按键处理方式不同,而且时间已经花出去了,那就把轮子圆一圆,放到 GitHub 中,给有缘人用吧,然后就有了这个不太圆的轮子 FlexibleButton。

概述

FlexibleButton 是一个基于 C 语言的小巧灵活的按键处理库。该按键库解耦了具体的按键硬件结构,理论上支持轻触按键与自锁按键,并可以无限扩展按键数量。另外,FlexibleButton 使用扫描的方式一次性读取所有所有的按键状态,然后通过事件回调机制上报按键事件。

该按键库使用 C 语言编写,驱动与应用程序解耦,便于灵活应用,比如用户可以方便地在应用层增加按键中断、处理按键功耗、定义按键事件处理方式,而无需修改 FlexibleButton 库中的代码。

另外,使用 C 语言标准库 API 编写,也使得该按键库可以无缝兼容任意的处理器平台,并且支持任意 OS 和 non-OS(裸机程序)。

另外,该按键库核心的按键扫描代码仅有三行,没错,就是经典的三行按键扫描算法,出自哪位大神之手就无从得知了,也欢迎知道此高人的读者文后留言哈。算法介绍可以去搜索引擎里查找,这里就不作介绍了。

获取

git clone https://github.com/murphyzhao/FlexibleButton.git

测试

FlexibleButton 库中提供了一个 DEMO flexible_button_demo.c,这里基于 RT-Thread OS 进行测试,当然你可以选择使用其他的 OS,或者使用裸机测试,只需要移除 OS 相关的特性即可。

将 FlexibleButton 库放到 RT-Thread BSP 下即可使用 scons 进行编译构建。

DEMO 程序说明

程序入口

int flex_button_main(void)
{
    rt_thread_t tid = RT_NULL;
    user_button_init();
    /* Create background ticks thread */
    tid = rt_thread_create("flex_btn", button_scan, RT_NULL, 1024, 10, 10);
    if(tid != RT_NULL)
    {
        rt_thread_startup(tid);
    }
    return 0;
}
INIT_APP_EXPORT(flex_button_main);

如上所示,首先使用 user_button_init(); 初始化用户按键硬件,并挂载到 FlexibleButton库。然后,使用了 RT-Thread 的 INIT_APP_EXPORT 接口导出为上电自动初始化,创建了一个 “flex_btn” 名字的按键扫描线程,线程里扫描检查按键事件。

用户初始化代码

user_button_init(); 初始化代码如下所示:

static void user_button_init(void)
{
    int i;
    rt_memset(&user_button[0], 0x0, sizeof(user_button));
    user_button[USER_BUTTON_0].usr_button_read = button_key0_read;
    user_button[USER_BUTTON_0].cb = (flex_button_response_callback)btn_0_cb;
    user_button[USER_BUTTON_1].usr_button_read = button_key1_read;
    user_button[USER_BUTTON_1].cb = (flex_button_response_callback)btn_1_cb;
    user_button[USER_BUTTON_2].usr_button_read = button_key2_read;
    user_button[USER_BUTTON_3].usr_button_read = button_keywkup_read;
    rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT); /* set KEY pin mode to input */
    rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT); /* set KEY pin mode to input */
    rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT); /* set KEY pin mode to input */
    rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT); /* set KEY pin mode to input */
    for (i = 0; i < USER_BUTTON_MAX; i ++)
    {
        user_button[i].status = 0;
        user_button[i].pressed_logic_level = 0;
        user_button[i].click_start_tick = 20;
        user_button[i].short_press_start_tick = 100;
        user_button[i].long_press_start_tick = 200;
        user_button[i].long_hold_start_tick = 300;
        if (i == USER_BUTTON_3)
        {
            user_button[USER_BUTTON_3].pressed_logic_level = 1;
        }
        flex_button_register(&user_button[i]);
    }
}

user_button_init(); 主要用于初始化按键硬件,设置按键长按和短按的 tick 数(RT-Thread上面默认一个 tick 为 1ms),然后注册按键到 FlexibleButton 库。

事件处理代码

static void btn_0_cb(flex_button_t *btn)
{
    rt_kprintf("btn_0_cb\n");
    switch (btn->event)
    {
        case FLEX_BTN_PRESS_DOWN:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_DOWN]\n");
            break;
        case FLEX_BTN_PRESS_CLICK:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_CLICK]\n");
            break;
        case FLEX_BTN_PRESS_DOUBLE_CLICK:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_DOUBLE_CLICK]\n");
            break;
        case FLEX_BTN_PRESS_SHORT_START:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_SHORT_START]\n");
            break;
        case FLEX_BTN_PRESS_SHORT_UP:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_SHORT_UP]\n");
            break;
        case FLEX_BTN_PRESS_LONG_START:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_LONG_START]\n");
            break;
        case FLEX_BTN_PRESS_LONG_UP:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_LONG_UP]\n");
            break;
        case FLEX_BTN_PRESS_LONG_HOLD:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_LONG_HOLD]\n");
            break;
        case FLEX_BTN_PRESS_LONG_HOLD_UP:
            rt_kprintf("btn_0_cb [FLEX_BTN_PRESS_LONG_HOLD_UP]\n");
            break;
    }
}

FlexibleButton 代码说明

按键事件定义

按键事件的定义并没有使用 Windows 驱动上的定义,主要是方便嵌入式设备中的应用场景(也可能是我理解的偏差),按键事件定义如下:

typedef enum
{
    FLEX_BTN_PRESS_DOWN = 0,        // 按下事件
    FLEX_BTN_PRESS_CLICK,           // 单击事件
    FLEX_BTN_PRESS_DOUBLE_CLICK,    // 双击事件
    FLEX_BTN_PRESS_SHORT_START,     // 短按开始事件
    FLEX_BTN_PRESS_SHORT_UP,        // 短按抬起事件
    FLEX_BTN_PRESS_LONG_START,      // 长按开始事件
    FLEX_BTN_PRESS_LONG_UP,         // 长按抬起事件
    FLEX_BTN_PRESS_LONG_HOLD,       // 长按保持事件
    FLEX_BTN_PRESS_LONG_HOLD_UP,    // 长按保持的抬起事件
    FLEX_BTN_PRESS_MAX,
    FLEX_BTN_PRESS_NONE,
} flex_button_event_t;

按键注册接口

使用该接口注册一个用户按键,入参为一个 flex_button_t 结构体实例的地址。

int8_t flex_button_register(flex_button_t *button);

按键事件读取接口

使用该接口获取指定按键的事件。

flex_button_event_t flex_button_event_read(flex_button_t* button);

按键扫描接口

按键扫描的核心函数,需要放到应用程序中定时扫描间隔 5-20ms 即可。

void flex_button_scan(void);

问题和建议

如果您在应用的时候遇到了问题,或者有好的想法和建议,欢迎到这个 issue 上讨论,谢谢。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

灵活的按键处理程序 FlexibleButton,C程序编写,无缝兼容任意的处理器,支持任意 OS 和 non-OS 的相关文章

  • 802.11标准deauth报文的reason code中文版

    代码 原因 0 保留 1非特定原因 2以前的身份验证不再有效 3由于发送STA离开 xff08 或已经离开 xff09 ibs或ESS而被取消身份验证 4由于不活动而解除关联 5已解除关联 xff0c 因为AP无法处理所有当前关联的STA
  • 虚拟机ubuntu单向ping通

    可以单向ping通 xff0c 到win端查看VMnet8 xff0c 发现VMnet8不见了 找回方法 xff1a 在VMware中对NAT模式进行 还原默认设置 操作或者配置好后点击确定 xff08 注意 xff1a 虚拟机开机后无法还
  • Beyond compare文件夹内容自动比较

    前言 xff1a 在一开始比较文件都是手动一个个去点击文件 xff0c 如果是几万个代码文件这将是巨大的工程 xff0c 带着偷懒的想法跑去找方法真找到了 默认会全部的文件标红 xff0c 这就很难受了 解决方案 xff1a 顶部的菜单 会
  • 从MIT协议谈契约精神

    以前看到过李笑来讲的发生在他身上的故事 xff0c 说他当年 2001年 住在双榆树 xff0c 经常去双安商场的地下超市买东西 xff0c 有一次买了个什么东西觉得不好 xff0c 要退 xff0c 超市服务员说按规定 xff0c 该类商
  • VLC命令行使用帮助

    Usage vlc options stream You can specify multiple streams on the commandline They will be enqueued in the playlist The f
  • 将Conda Prompt Here添加到右键菜单

    如何将Conda Prompt Here添加到右键菜单 Conda是一个非常流行的Python的环境管理工具 xff0c 在做项目的时候把它跟IDE整合在一起用来管理不同项目的环境会很方便 xff0c 但是在日常使用Windows的过程中如
  • AMS-1117

    电路图 说明 10uF 61 10622uF 61 226100nF 61 104106 61 10乘以10的6次方pF xff1b 简单点的说就是106表示容量 10后面加六个零 单位pF 转换成uF就是10uF 电容之间的换算公式 xf
  • ROS---用catkin创建ROS包、编译

    安装好ROS后 xff0c 默认已经安装了catkin xff0c 接着执行以下步骤 用catkin创建ROS包 span class hljs comment 每次都要进入这个目录 xff0c 也就是所有的包都要放在这个目录下 span
  • libQtGui.so: undefined reference to `png

    使用Qt4 包在Centos上编译时 xff0c 出现libQtGui so 找到未定义的png等 首先进行网上搜索 xff0c 没有发现任何思路 执行ldd时 xff0c 发现少了很多依赖库 xff0c 如下 xff1a ldd libQ
  • C/C++中在头文件中定义函数或变量会出现的问题

    在 C C 43 43 中 xff0c 我们一般是把代码分为头文件 xff08 h xff09 和源文件 xff08 c cpp xff09 分开保存 xff0c 这样可以方便代码管理和阅读 但是如果把函数或变量的定义也放在头文件中会出现什
  • C++ 求100的阶乘

    include lt iostream gt using namespace std int main int n int k 61 1 k为当前的位数 int fact 10000 61 1 0 cout lt lt 34 输入阶乘n 3
  • C++ 读入一个整数,将各个数位上的数拆分下来并输出(从高位到低位)。

    include lt iostream gt include lt cmath gt using namespace std void split int num int n 61 num int count 61 0 位数 int tem
  • C++建立一个关于平面点坐标的类

    建立一个关于平面点坐标的类 include lt iostream gt include lt cmath gt using namespace std class Cpoint private int flag flag 61 1时 xf
  • 图---生成树与最小生成树

    今天在做题的时候遇到一个问题 xff0c 如何根据图的邻接表来画出 DFS 生成树和 BFS 生成树 xff0c 有两年的真题中涉及到这个问题 xff0c 在以前的学习中没注意过此问题 xff0c 由于严奶奶的书上也只是一带而过 xff0c
  • 编写一个递归算法,实现将一棵二叉树的左右孩子互换。

    include 34 iostream 34 using namespace std define max 20 定义树的结点数 typedef struct BTNode 定义二叉树结点类型 char data 结点数据类型 struct
  • IIC协议解释

    xff08 1 xff09 概述 I2C Inter Integrated Circuit BUS 集成电路总线 xff0c 该总线由NXP xff08 原PHILIPS xff09 公司设计 xff0c 多用于主控制器和从器件间的主从通信
  • 使用栈非递归实现复制二叉树

    include 34 iostream 34 using namespace std define max 20 the number of node typedef struct BTNode char data struct BTNod
  • stanford-segmenter一个简单例子

    1 简介 stanford分词目前支持 Arabic 和 Chinese 它的原理是基于CRFs CRFs分词的原理不难懂 xff0c 就是把分词当作另一种形式的命名实体识别 xff0c 利用特征建立概率图模型后 xff0c 用Veterb
  • 集中式vs分布式

    Linus一直痛恨的CVS及SVN都是集中式的版本控制系统 xff0c 而Git是分布式版本控制系统 xff0c 集中式和分布式版本控制系统有什么区别呢 xff1f 先说集中式版本控制系统 xff0c 版本库是集中存放在中央服务器的 xff
  • 一个完整的schema验证xml的例子

    xml文件 xff1a lt reference xmlns 61 34 http www w3school com cn 34 xmlns xsi 61 34 http www w3 org 2001 XMLSchema instance

随机推荐

  • 三维视觉论文阅读:DeepPruner2019双目立体匹配

    论文 DeepPruner Learning Efficient Stereo Matching via Differentiable PatchMatch 摘要 DeepPruner这篇文章 xff0c 本人在2019年上半旬就大致读过一
  • 三维视觉论文阅读:RAFT2020双目光流

    论文 RAFT Recurrent All Pairs Field Transforms for Optical Flow 摘要 2020年下半年以来 xff0c 深度学习都逐渐走向了迭代优化 xff08 例如NeRf xff09 xff0
  • 三维视觉论文阅读:high-res-stereo2019双目立体视觉

    论文 Hierarchical Deep Stereo Matching on High resolution Images 摘要 本篇文章本人在看的时候 xff0c 感觉特别像StereoNet和StereoDRNet high res
  • 三维视觉论文阅读:MVSNet2018多视立体匹配

    论文 MVSNet Depth Inference for Unstructured Multi view Stereo 摘要 MVSNet是深度学习多视立体匹配的开山之作 xff08 我个人认为 xff09 xff0c 虽然其在网络结构上
  • 三维视觉论文阅读:RMVSNet2019多视立体匹配

    论文 Recurrent MVSNet for High resolution Multi view Stereo Depth Inference 摘要 MVSNet最大的问题是3D UNet xff0c 太耗费内存了 RMVSNet另辟蹊
  • 三维视觉论文实战:DenseDepth2019--网络结构及demo

    目的 本篇博客的主要目的是记录测试DenseDepth的demo的过程 xff0c 包括 pytorch模型构建 和 keras模型参数转pytorch 两大部分 xff0c 当然最后还有一个实验模块 注明以下 xff0c 本篇博客为啥要构
  • GTAV:原始影像和深度图获取

    背景 GTAV是一个非常好的游戏 xff0c 目前也已经被广泛应用到深度学习之中了 本篇博客简单介绍一下如何采集数据 1 数据采集 1 代码修改 本篇博客的代码来源于GTAVisionExport 但是上述代码中 xff0c 存在些许问题
  • Blender2.8:Blender Python渲染降噪节点(Cycles)

    参考 https www bilibili com read cv9221189 背景 Blender的Cycles渲染引擎存在非常多的噪声 方法 一个比较好的思路是利用 Denoising Data 和降噪节点 参考文档里的是手动设置 x
  • Ubuntu:显存占用及处理

    问题 在进行深度学习时 xff0c 显存是一种非常宝贵的资源 但是即便在Ubuntu下 xff0c 各种各样的系统配置都会不自觉的占用一些显存 xff0c 导致深度学习难以为继 在本博客中 xff0c 主要搬运一些查询显存占用原因及处理方法
  • Jittor:Jittor三千问

    Jittor三千问 记录一下在使用Jittor时遇到的问题和对应的解决方案 xff0c 持续更新 非常感谢梁盾博士的回复 1 Jittor如何指定显卡 xff1f 在运行脚本时 xff0c 使用 CUDA VISIBLE DEVICES 6
  • 机器学习:补课目录

    补课目录 xff1a xff08 已经完成 xff09 吴恩达DeepLearning ai xff1a Deep Learning Specialization xff08 正在进行 xff09 林轩田 机器学习基石 xff08 正在进行
  • conda:离线环境安装

    Aanconda的离线环境安装的必要条件是有一台可以联网的电脑 在后文中 xff0c 分别称可以联网的电脑为On line xff0c 不可以联网的电脑为Off line 以下即为对应的操作步骤 1 On line 下载annconda安装
  • Ubuntu:pip install gdal

    方法 sudo apt get update 必须首先安装gdal的lib xff0c python只是针对该lib的调用 sudo apt install gdal bin libgdal dev pip安装的版本必须和gdal一致 pi
  • Git:使用笔记

    git局部配置 git config user name 34 username 34 git config user email 34 email 34 git带用户密码clone git clone https username pas
  • Pytorch:conda安装不同版本的cuda

    我不会是最后一个知道可以用conda安装不同版本的cuda的人吧 通常的pytorch安装流程是 xff1a 首先安装NVIDIA驱动 xff0c 然后安装对应版本的cuda和cudnn最后再安装cuda支持的pytorch版本 然而实际上
  • obsidian使用技巧

    背景 obsidian是一个非常牛逼的本地笔记工具 xff0c 极大的提高了本人的学习能力 xff0c 卷的更加厉害了 此处简要记录一下在使用过程中遇到问题和对应的解决方案 xff0c 至于具体的使用方法网上多的是就不介绍了 三方插件推荐
  • ubuntu:命令行查询文件(夹)大小

    背景 使用命令行查询文件文件 夹 大小 参考 https www cnblogs com zhengyiqun1992 p 11183819 html 使用方法 查看当前文件夹下文件大小 ll h 输出如下 xff0c 其中文件夹大小是错误
  • VSCode:remote-ssh多级跳转

    背景 vscode目前是非常流行的编程工具 xff0c 提供了大量的插件 xff0c 尤其是其中的remote ssh xff0c 能够提供远程ssh连接服务器 xff0c 居家办公两不误 然而比较麻烦的事情是 xff0c 通常服务器为了保
  • Jittor:Jittor1.3.1之离线安装

    背景 Jittor是一个非常牛逼的框架 xff0c 维护了大量的官方demo xff0c 非常容易上手 与其他方法相比 xff0c 采用了即时编译的流程 xff0c 因此在效率上往往更高 但是在使用Jittor的过程中 xff0c 也遇到了
  • 灵活的按键处理程序 FlexibleButton,C程序编写,无缝兼容任意的处理器,支持任意 OS 和 non-OS

    灵活的按键处理程序 FlexibleButton 前言概述获取测试DEMO 程序说明程序入口用户初始化代码事件处理代码 FlexibleButton 代码说明按键事件定义按键注册接口按键事件读取接口按键扫描接口 问题和建议 前言 正好工作中