FlexibleButton:一个轻巧灵活的按键处理库,让你的按键处理更简单

         在嵌入式系统开发中,按键输入处理是一个常见且重要的环节。然而,许多开发者在处理按键时,往往会遇到按键消抖、组合按键、长按/短按等功能实现的复杂性。如何在保证系统高效运行的同时,简化按键事件的处理呢?

         今天,我们向大家介绍一个小巧而灵活的按键处理库——FlexibleButton。它基于标准 C 语言,简单易用,却具备强大的功能,可以让你轻松实现按键事件的各种处理需求。

一、FlexibleButton的核心特性

  1. 单击、连击、短按、长按、自动消抖:
    FlexibleButton 支持多种常见的按键事件:单击、连击、短按、长按,甚至自动消抖机制。无论你的按键设计复杂还是简单,它都能帮你高效处理。

  2. 灵活的按键组合:
    如果你的系统需要支持多个按键的组合,FlexibleButton 提供了灵活的组合按键设置。用户可以自由配置按键组合并通过回调函数处理事件,非常方便。

  3. 解耦硬件设计:
    FlexibleButton 的设计解耦了具体的按键硬件结构,使得它可以支持各种类型的按键,包括轻触按键和自锁按键。无论你采用什么硬件架构,FlexibleButton 都能轻松适配。

  4. 按键数量的无限扩展:
    FlexibleButton 的架构支持按键数量的扩展,理论上,你可以根据需求无限增加按键数量,而不需要担心性能下降或库的复杂性增加。

  5. 低功耗和中断支持:
    在低功耗和中断场景下,FlexibleButton 也能发挥重要作用。它支持通过中断方式来处理按键事件,保证系统在低功耗状态下也能高效工作。

  6. 简单的按键扫描:
    FlexibleButton 的按键扫描机制非常简洁,仅需三行代码就能完成所有按键状态的读取。无论你使用的是哪种平台,三行按键扫描算法都能让你迅速上手。

二、核心设计:三行按键扫描

FlexibleButton 的高效性源于其简洁的设计:三行按键扫描算法。这一设计使得按键状态的读取和事件处理变得异常简洁和高效。


for (int i = 0; i < BUTTON_COUNT; i++) {button_state[i] = read_button_state(i);  // 读取当前按键状态if (button_state[i] != previous_state[i]) {handle_button_event(i, button_state[i]);  // 处理按键事件}
}

这三行代码简洁明了,充分体现了FlexibleButton的高效性和简易性。通过这种扫描方式,我们可以一次性读取所有按键的状态,并通过回调机制处理每个按键的状态变化。

(1)确定用户按键


typedef enum
{USER_BUTTON_0 = 0, // 对应 IoT Board 开发板的 PIN_KEY0USER_BUTTON_1,     // 对应 IoT Board 开发板的 PIN_KEY1USER_BUTTON_2,     // 对应 IoT Board 开发板的 PIN_KEY2USER_BUTTON_3,     // 对应 IoT Board 开发板的 PIN_WK_UPUSER_BUTTON_MAX
} user_button_t;static flex_button_t user_button[USER_BUTTON_MAX];

上述代码定义了 4 个按键,数据结构存储在 user_button 数组中。

(2)程序入口


int flex_button_main(void)
{rt_thread_t tid = RT_NULL;user_button_init();/* 创建按键扫描线程 flex_btn,线程栈 1024 byte,优先级 10 */tid = rt_thread_create("flex_btn", button_scan, RT_NULL, 1024, 10, 10);if(tid != RT_NULL){rt_thread_startup(tid);}return 0;
}
/* 使用 RT-Thread 的自动初始化 */
INIT_APP_EXPORT(flex_button_main);

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

(3)按键初始化代码

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

static void user_button_init(void)
{int i;/* 初始化按键数据结构 */rt_memset(&user_button[0], 0x0, sizeof(user_button));/* 初始化 IoT Board 按键引脚,使用 rt-thread PIN 设备框架 */rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP);    /* 设置 GPIO 为上拉输入模式 */rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP);    /* 设置 GPIO 为上拉输入模式 */rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP);    /* 设置 GPIO 为上拉输入模式 */rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT_PULLDOWN); /* 设置 GPIO 为下拉输入模式 */for (i = 0; i < USER_BUTTON_MAX; i ++){user_button[i].id = i;user_button[i].usr_button_read = common_btn_read;user_button[i].cb = common_btn_evt_cb;user_button[i].pressed_logic_level = 0;user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500);user_button[i].long_press_start_tick = FLEX_MS_TO_SCAN_CNT(3000);user_button[i].long_hold_start_tick = FLEX_MS_TO_SCAN_CNT(4500);if (i == USER_BUTTON_3){user_button[USER_BUTTON_3].pressed_logic_level = 1;}flex_button_register(&user_button[i]);}
}

核心的配置如下:

配置项

说明

id

按键编号

usr_button_read

设置按键读值回调函数

cb

设置按键事件回调函数

pressed_logic_level

设置按键按下时的逻辑电平

short_press_start_tick

短按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏转化为扫描次数

long_press_start_tick

长按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏转化为扫描次数

long_hold_start_tick

超长按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏转化为扫描次数

注意,short_press_start_tick、long_press_start_tick 和 long_hold_start_tick 必须使用 FLEX_MS_TO_SCAN_CNT 将毫秒时间转化为扫描次数。

user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500); 表示按键按下开始计时,1500 ms 后按键依旧是按下状态的话,就断定为短按开始。

(4)事件处理代码


static void common_btn_evt_cb(void *arg)
{flex_button_t *btn = (flex_button_t *)arg;rt_kprintf("id: [%d - %s]  event: [%d - %30s]  repeat: %d\n", btn->id, enum_btn_id_string[btn->id],btn->event, enum_event_string[btn->event],btn->click_cnt);if (flex_button_event_read(&user_button[USER_BUTTON_0]) == flex_button_event_read(&user_button[USER_BUTTON_1]) == FLEX_BTN_PRESS_CLICK){rt_kprintf("[combination]: button 0 and button 1\n");}
}

示例代码中,将所有的按键事件回调均绑定到 common_btn_evt_cb 函数,在该函数中打印了按键 ID 和按键事件,以及按键连击次数,并演示了如何使用组合按键。

三、适用场景

FlexibleButton 的适用场景非常广泛,特别适合以下几类项目:

  • 低功耗嵌入式系统:

     通过中断和按键消抖机制,能够在低功耗模式下高效工作。

  • 复杂按键输入场景:

     支持组合按键、长按/短按等多种按键事件。

  • 跨平台开发:

     基于标准 C 语言,支持各种硬件平台和操作系统,甚至是裸机系统。

  • 实时按键响应需求:

     通过事件回调机制,保证按键事件能够快速响应并处理。

四、为何选择FlexibleButton?

  • 小巧而高效:

     相较于其他按键处理库,FlexibleButton 不仅小巧,还具有极高的处理效率,非常适合嵌入式系统中的资源受限场景。

  • 易于集成:

     由于使用了标准 C 语言 API,FlexibleButton 可以无缝集成到各种处理器平台和操作系统中,不需要额外的依赖。

  • 可扩展性强:

     它的架构设计让你可以根据需求自由添加更多按键,且不会增加过多的复杂度。

  • 支持事件回调:

     灵活的事件回调机制可以让你更直观地处理各种按键事件,增强系统的响应速度和可维护性。

    无论是简单的按键控制,还是复杂的多按键组合,FlexibleButton 都能帮助你轻松应对。它的高效性、灵活性和易用性使得它在嵌入式开发中成为理想的按键处理方案。通过FlexibleButton,你可以专注于业务逻辑的实现,而不必为按键处理的复杂性烦恼。

立即尝试 FlexibleButton,让你的按键输入处理更简单、更高效!https://github.com/murphyzhao/FlexibleButton

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/904340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索程序员薪资背后的秘密与未来:智能化工具如何助力职场发展

最新接入DeepSeek-V3模型&#xff0c;点击下载最新版本InsCode AI IDE 探索程序员薪资背后的秘密与未来&#xff1a;智能化工具如何助力职场发展 引言 在当今数字化时代&#xff0c;程序员作为科技发展的核心力量&#xff0c;其职业前景和薪资水平备受关注。随着人工智能和自…

【STM32单片机】#14 PWR电源控制

主要参考学习资料&#xff1a; B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装&#xff1a;STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 目录 PWR…

第十五届蓝桥杯单片机国赛-串口解析

串口通信像是蓝桥杯单片机组国赛中一个若隐若现的秘境&#xff0c;总在不经意间为勇者们敞开大门。然而&#xff0c;初次探索这片领域的冒险者&#xff0c;常常会被其神秘莫测的特性所震慑&#xff0c;黯然退场&#xff08;编不下去了&#xff0c;直接进入正题&#xff09;。 附…

深入探索 51 单片机:从入门到实践的全面指南

深入探索 51 单片机&#xff1a;从入门到实践的全面指南 一、引言 在嵌入式系统发展的漫长历程中&#xff0c;51 单片机犹如一颗璀璨的明星&#xff0c;虽然诞生已有数十年&#xff0c;但至今仍在众多领域发挥着重要作用。它以结构简单、易于学习、成本低廉等优势&#xff0c…

GD32F470+CH395Q

第一步&#xff1a;资料下载 以太网协议栈芯片 CH395 - 南京沁恒微电子股份有限公司 第二步&#xff1a;准备工程 &#xff08;1&#xff09; 首先准备一个编译无报错、可以正常打印和延时的工程文件&#xff0c;官方例程采用STM32F1芯片&#xff0c;但本文采用GD32F470芯片 …

Linux 怎么使用局域网内电脑的网络访问外部

一次性 export http_proxy"http://192.168.0.188:7890" export https_proxy"http://192.168.0.188:7890"一直生效 写入 ~/.bashrc&#xff08;或 ~/.bash_profile&#xff09; nano ~/.bashrc加入这一行&#xff1a; export http_proxy"http://19…

Mysql进阶篇1_存储引擎、索引、SQL性能分析指令

文章目录 1.存储引擎InnoDBMyISAMMemory存储引擎选择和对比 2.索引索引结构索引分类索引语法索引使用&#xff08;建议看完第3节后观看&#xff09;&#xff01;&#xff01;&#xff01;mysql如何使用索引查询数据&#xff08;个人理解&#xff09; 3.SQL性能分析SQL执行频率慢…

LeetCode 热题 100 118. 杨辉三角

LeetCode 热题 100 | 118. 杨辉三角 大家好&#xff0c;今天我们来解决一道经典的算法题——杨辉三角。这道题在 LeetCode 上被标记为简单难度&#xff0c;要求生成杨辉三角的前 numRows 行。杨辉三角是一个经典的组合数学问题&#xff0c;每一行的数字都是其正上方和正左上方…

修改或禁用Cursor的全局搜索默认快捷键

在 Cursor 中&#xff0c;默认情况下 双击 Shift 会打开 全局搜索&#xff08;Quick Open&#xff09;&#xff0c;类似于 VS Code 的 CtrlP 功能。如果你想修改或禁用这个快捷键&#xff0c;可以按照以下步骤操作&#xff1a; 1. 打开快捷键设置 方法 1&#xff1a;按下 Ctrl…

HarmonyOS Device Connector(hdc)

它是为开发人员提供的用于调试的命令行工具&#xff0c;通过该工具可以在windows/linux/mac系统上与设备进行交互。 hdc分为三部分&#xff1a; client&#xff1a;运行在电脑端的进程&#xff0c;开发者在执行hdc命令时启动该进程&#xff0c;命令结束后进程退出。 server&…

开源PDF解析工具Marker深度解析

开源PDF解析工具Marker深度解析 检索增强生成&#xff08;RAG&#xff09;系统的第一步就是做 pdf 解析&#xff0c;从复杂多样的 pdf 中提取出干净准确的文本内容。现有的最优秀的开源工具有两个&#xff1a;Marker 和 MinerU。因为 Marker 是个人开发者做的&#xff0c;文档…

ARM子程序调用与返回

子程序&#xff08;也叫过程、函数、方法&#xff09;是一个能被调用和执行并返回到调用点那条指令的代码 段。 两个问题&#xff1a;如何将参数传递给子程序或从子程序中传递出来&#xff1f;怎么从子程序返回到调用点&#xff1f; 指令BSR Proc_A调用子程序Proc_A。 处理器将…

算力经济模型推演:从中心化到去中心化算力市场的转变(区块链+智能合约的算力交易原型设计)

一、算力经济的历史脉络与范式转移 1.1 中心化算力市场的演进困境 传统算力市场以超算中心、云计算平台为核心载体&#xff0c;其运营模式呈现强中心化特征。中国移动构建的"四算融合"网络虽实现百万级服务器的智能调度&#xff0c;但动态资源分配仍受制于集中式控…

小结: 接口类型和路由优先级

网络接口类型 1. Bridge-if&#xff08;桥接接口&#xff09; 作用&#xff1a;用于桥接网络&#xff0c;将多个接口或VLAN连接为一个广播域&#xff0c;实现二层数据转发。 常用指令&#xff1a; interface bridge-if <number> bridge <bridge-id> # 将接口加入…

mysql一些事

一.联合查询/多表查询 联合查询关键在于笛卡尔积的过程 笛卡尔坐标积的排列组合 首先它会将两个表用排列组合的方式进行排列组合。 表一 表二 进行排列组合 我们发现它的行是 两个表的行相乘&#xff0c;列是两表的列相加。 我们所看到的数据有合理的也有不合理的我们接下…

【工具】Open WebUI:本地化部署的AI交互平台

文章目录 一、Open WebUI 简介二、核心功能详解1. 多模型与多模态支持2. 本地RAG与文档集成3. 开发与定制化能力4. 安全与权限管理5. 用户体验优化 三、安装与部署指南1. 快速安装方式2. 高级配置3. 常见问题 四、实际应用场景1. 个人隐私助手2. 企业知识库3. 学术研究4. 创意工…

AutoGPT

一、简介 是一个基于openAI研发的GPT4模型的一个开源应用程序&#xff0c;根据用户指定的目标&#xff0c;自动生成所需的提示&#xff0c;并且执行需要多个步骤才能完成的项目&#xff0c;整个过程不需要人类干预和指导&#xff08;无监督学习&#xff09;&#xff0c;生成式…

[C++] 小游戏 决战苍穹

大家好&#xff0c;各位看到这个标题&#xff0c;斗破苍穹什么时候改叫决战苍穹了&#xff1f;其实&#xff0c;因为版权等一系列问题&#xff0c;斗破苍穹正式改名为决战苍穹&#xff0c;这个版本主要更新内容为解决了皇冠竞技场太过影响游戏平衡&#xff0c;并且提高了一些装…

Spring的数据库编程

本内容采用最新SpringBoot3框架版本,视频观看地址:B站视频播放 1. JdbcTemplate概述 针对数据库操作,Spring框架提供了JdbcTemplate类,JdbcTemplate是一个模板类,Spring JDBC中的更高层次的抽象类均在JdbcTemplate模板类的基础上创建。 JdbcTemplate类提供了操作数据库…

Debezium MySqlValueConverters详解

Debezium MySqlValueConverters详解 1. 类的作用与功能 1.1 核心作用 MySqlValueConverters是Debezium中负责MySQL数据类型转换的核心类,主要功能包括: 数据类型映射:将MySQL的数据类型映射到Kafka Connect的Schema类型值转换:将MySQL的原始值转换为Kafka Connect可用的…