嵌入式按键检测组件

本文最后更新于:17 天前

按键检测模块

模块简介

按键检测模块用于嵌入式系统上实现按键的扫描,实现按键的触发检测,并对短按、长按等状态进行识别检测。

需求分析

按键检测需要可以识别多个按键的多种事件触发,并且需要对事件做出响应处理。

  • 功能性需求
    1. 可以实现多个按键检测
    2. 实现按键扫描事件检测和事件回调触发
  • 非功能性需求
    1. 方便移植
    2. 方便添加按键
    3. 代码实现简洁易读

架构设计

设计目标

  • 可读性
  • 可移植性
  • 可拓展性

设计原理

  • 单个按键对象的方法包含按键的触发识别函数和按键的事件处理函数
  • 单个按键需要状态管理,这些状态的触发条件包含按键触发和时间触发
  • 按键管理组件包含多个按键,这些按键的业务相同,所以需要统一管理
  • 多个按键可以采用链表、数组等方式进行管理
  • 基本状态设计
    按键模块状态切换
    采用两种方案设计
  1. 链表方案
    • 链表的实现参照链表知识
    • 按键类包含的成员如下
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      /**
      * 按键类
      */
      typedef enum
      {
      KEY_IDLE, //空闲
      KEY_PRESS, //按下
      KEY_RELEASE, //释放
      KEY_SHORT_CLICK, //短按
      KEY_LONG_CLICK, //长按
      KEY_DOUBLE_CLICK, //双击
      KEY_LONG_HOLD, //长按保持
      } KEY_STATE;
      #define KEY_LONGPRESS_TICK 200
      /* 按键检测函数指针 */
      typedef uint8_t (*det_func)(void);
      /* 按键状态变化函数指针 */
      typedef void (*handle_func)(uint8_t key_id, uint8_t key_state);
      typedef struct Key_t
      {
      Node node; //节点
      uint8_t key_id; //按键ID
      uint8_t state; //按键状态
      det_func detFunc; //按键检测函数
      handle_func handleFunc; //状态变化回调函数
      uint16_t tick; //按键tick
      } Key;
    • 采用链表在初始化阶段创建链表并将按键节点插入到链表中
    • 采用链表遍历的方式查询按键状态
  2. 数组指针方案设计
    • 包含按键检测类和按键类两个类
    • 实现思路与链表大致相同但是可读性更强一点
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      /* 按键状态 */
      typedef enum
      {
      BUTTON_STATE_IDLE,
      BUTTON_STATE_RELEASE,
      BUTTON_STATE_PRESS,
      BUTTON_STATE_SHORT_CLICK,
      BUTTON_STATE_LONG_CLICK,
      }BUTTON_STATE_TYPE;
      #define BUTTON_LONGCLICK_TIMEOUT 1000
      /**
      * @brief 获取按键状态函数指针
      * @return TRUE 按键被触发 FALSE 按键被释放
      */
      typedef uint8_t (*func_GetButtonState)(void);
      /* 按键类 */
      typedef struct Button_T
      {
      uint8_t ButtonId; //按键的ID信息
      uint8_t state; //按键当前状态
      uint32_t tick; //按键时间参数
      func_GetButtonState func_ButtonState; //获取按键状态的函数成员
      } Button;
      /* 按键模块的事件回调函数指针 */
      typedef void (*func_ButStateChangeHandle)(uint8_t but_id, uint8_t state);
      /* 按键模块类 */
      typedef struct Mod_Button_t
      {
      uint8_t ButtonNum; //按键个数
      Button **ButtonList; //按键列表的地址
      func_ButStateChangeHandle func_EventHandle; //按键模块的事件回调函数
      } Mod_Button;

落地实践

实践仓库-github


嵌入式按键检测组件
https://hudaxia.top/2021/08/17/组件-按键检测实现/
作者
胡大侠
发布于
2021年8月17日
更新于
2023年3月10日
许可协议