首页 > 其他分享 >记录一个按键处理模块

记录一个按键处理模块

时间:2023-11-17 17:02:17浏览次数:27  
标签:Ticks 模块 KeyEvent 记录 pHandle Key 按键 Level Def

本模块模仿MultiButton实现的。GitHubhttps://github.com/0x1abin/MultiButton

按键状态参考DALI协议301部分按键状态。

分享测试文件:

链接:https://pan.baidu.com/s/1dqXc-_ycR-Tl-KQtsxJs4A
提取码:1234

 

按键状态分为以下状态:

typedef enum {     KeyEvent_Idle = 0,     KeyEvent_PutDown,     KeyEvent_RealeaseUp,     KeyEvent_Click,     KeyEvent_DoubleClick,     KeyEvent_LongPressStart,     KeyEvent_LongPressRepeat,     KeyEvent_LongPressEnd,     KeyEvent_Stuck,     KeyEvent_Free } KeyEvent_Def; 有按下,弹起,单击,双击,长按,卡死等。 大致逻辑就是滤波+状态机+链表管理;     按下时间小于ShortPress_Ticks 就是短按,大于这个时间进入长按; 第一次按下之后的空闲时间 < DoubleClickIdle_Ticks 就是一个双击有效的区域,超过这个时间就默认是一个短按 Stuck_Ticks 是指按键卡死所需的时间,如果按键按键20s以上,就认为是一个卡死事件 LongPressRepeat_Ticks 指长按下时的重发时间,一直长按会一直发。             以下为按键部分代码内容: #include "bsp_includes.h" #include <string.h>
static KeyInfo_Def *pHead_Node = NULL; /**************************************************************************  * @brief 初始化链表头结点  **************************************************************************/ void List_Init(void) {     pHead_Node = NULL; } /**************************************************************************  * @brief 获取按键当前触发的事件  **************************************************************************/ u8 Get_KeyCurEvent(KeyInfo_Def *pHandle) {     return (u8)(pHandle->byEvent); } /**************************************************************************  * @brief 把新增的按键加入链表  **************************************************************************/ int Add_KeyToList(KeyInfo_Def *pCurNode) {     KeyInfo_Def *pTargetNode = pHead_Node;     while (pTargetNode)     {         if (pTargetNode == pCurNode)         {             return -1; // already exist.         }         pTargetNode = pTargetNode->pNext; // find Null node     }
    pCurNode->pNext = pHead_Node;     pHead_Node = pCurNode;     return 0; // add success }
/**************************************************************************  * @brief 注册按键信息  **************************************************************************/ void Key_Attach(KeyInfo_Def *pHandle, GetIOStatus pFunc1, KeyEventProcess pFunc2, uint8_t byState) {     memset(pHandle, 0, sizeof(KeyInfo_Def));     pHandle->dwPressedTicks = 0;     pHandle->dwReleasedTicks = 0;     pHandle->dwLongPressRepeat_Ticks = 0;     pHandle->byEvent = KeyEvent_Idle;     pHandle->byKeyStatus = Key_IDLE;     pHandle->byDebounce_Count = 0;     pHandle->byMultiplePressEnable = byState;     pHandle->pGetIOLevel_Func = pFunc1;     pHandle->pProcess_Func = pFunc2;     pHandle->byKey_Level = pHandle->pGetIOLevel_Func();
    Add_KeyToList(pHandle); }
void KeyEvent_Process(KeyInfo_Def *handle, KeyEvent_Def keyEvent) {     handle->byEvent = keyEvent;     handle->pProcess_Func(handle, handle->byEvent); } /**************************************************************************  * @brief 按键状态机  **************************************************************************/ void Key_handler(KeyInfo_Def *pHandle) {     uint8_t byRead_IO_Level = pHandle->pGetIOLevel_Func();
    /*------------button debounce handle---------------*/     if (byRead_IO_Level != pHandle->byKey_Level) // not equal to prev one     {         // continue read 3 times same new level change         if (++(pHandle->byDebounce_Count) >= DEBOUNCE_TICKS)         {             pHandle->byKey_Level = byRead_IO_Level;             pHandle->byDebounce_Count = 0;             if (pHandle->byKey_Level == Pressed)             {                 KeyEvent_Process(pHandle, KeyEvent_PutDown);             }             else             {                 KeyEvent_Process(pHandle, KeyEvent_RealeaseUp);             }         }     }     else     { // leved not change ,counter reset.         pHandle->byDebounce_Count = 0;     }
    if (pHandle->dwReleasedTicks < 300000) // 300s         pHandle->dwReleasedTicks++;     if (pHandle->dwPressedTicks < 300000)         pHandle->dwPressedTicks++;
    if (byRead_IO_Level != pHandle->byKey_Level)     {         if (byRead_IO_Level == Pressed)             pHandle->dwPressedTicks = 0;         else             pHandle->dwReleasedTicks = 0;     }
    switch (pHandle->byKeyStatus)     {     case Key_IDLE:         if (pHandle->byKey_Level == Pressed)         {             if (pHandle->dwPressedTicks >= ShortPress_Ticks)             {                 KeyEvent_Process(pHandle, KeyEvent_LongPressStart);                 pHandle->dwLongPressRepeat_Ticks = 0;                 pHandle->byKeyStatus = Key_LongPress;             }             else             {                 pHandle->byKeyStatus = Key_ACK;             }         }         else         {             pHandle->byKeyStatus = Key_IDLE;         }         break;     case Key_ACK:         if (pHandle->byKey_Level == Pressed)         {             if (pHandle->dwPressedTicks >= ShortPress_Ticks)             {                 KeyEvent_Process(pHandle, KeyEvent_LongPressStart);                 pHandle->dwLongPressRepeat_Ticks = 0;                 pHandle->byKeyStatus = Key_LongPress;             }         }         else         {             if (pHandle->byMultiplePressEnable == DPress_Disable)             {                 KeyEvent_Process(pHandle, KeyEvent_Click);                 pHandle->byKeyStatus = Key_IDLE;             }             else             {                 pHandle->byKeyStatus = Key_WaitDoublePress;             }         }         break;     case Key_WaitDoublePress:         if (pHandle->byKey_Level == Pressed)         {             if (pHandle->dwReleasedTicks <= DoubleClickIdle_Ticks)             {                 if (pHandle->byMultiplePressEnable == DPress_Enable)                     KeyEvent_Process(pHandle, KeyEvent_DoubleClick);                 else                     KeyEvent_Process(pHandle, KeyEvent_PutDown);                 pHandle->byKeyStatus = Key_WaitDoublePressIdle;             }         }         else         {             if (pHandle->dwReleasedTicks > DoubleClickIdle_Ticks)             {                 KeyEvent_Process(pHandle, KeyEvent_Click);                 pHandle->byKeyStatus = Key_IDLE;             }         }         break;     case Key_WaitDoublePressIdle:         if (pHandle->byKey_Level == Released)         {             pHandle->byKeyStatus = Key_IDLE;         }         break;     case Key_LongPress:         if (pHandle->byKey_Level == Pressed)         {             if (pHandle->dwPressedTicks > Stuck_Ticks)             {                 KeyEvent_Process(pHandle, KeyEvent_Stuck);                 pHandle->byKeyStatus = Key_STUCK;             }             else if (pHandle->dwLongPressRepeat_Ticks > LongPressRepeat_Ticks)             {                 KeyEvent_Process(pHandle, KeyEvent_LongPressRepeat);                 pHandle->dwLongPressRepeat_Ticks = 0;             }             else             {                 pHandle->dwLongPressRepeat_Ticks++;             }         }         else         {             KeyEvent_Process(pHandle, KeyEvent_LongPressEnd);             pHandle->byKeyStatus = Key_IDLE;         }         break;
    case Key_STUCK:         if (pHandle->byKey_Level == Released)         {             KeyEvent_Process(pHandle, KeyEvent_Free);             pHandle->byKeyStatus = Key_IDLE;         }     default:         break;     } } /**************************************************************************  * @brief 移除按键节点  **************************************************************************/ void Remove_Key(KeyInfo_Def *pTarget) {     KeyInfo_Def **ppCur;     KeyInfo_Def *entry = *ppCur;     for (ppCur = &pHead_Node; (*ppCur) != NULL;)     {         if (entry == pTarget)         {             *ppCur = entry->pNext;             // free(entry);         }         else         {             ppCur = &entry->pNext;         }     } } /**************************************************************************  * @brief 毫秒处理函数  **************************************************************************/ void Key_Ticks_1ms(void) {     KeyInfo_Def *pTarget;     for (pTarget = pHead_Node; pTarget; pTarget = pTarget->pNext)     {         if (pTarget == NULL)             return;         Key_handler(pTarget);     } }     /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #ifndef __BSP_KEY_H__ #define __BSP_KEY_H__
#include "bsp_includes.h"
#define DEBOUNCE_TICKS 10
#define ShortPress_Ticks        500 #define DoubleClickIdle_Ticks   300 #define Stuck_Ticks             20000 #define LongPressRepeat_Ticks   200
#define DPress_Enable    1 #define DPress_Disable    0
typedef uint8_t (*GetIOStatus)(void); typedef void (*KeyEventProcess)(void *, uint8_t);
typedef enum {     Released = 1,     Pressed = 0 } IOStatus_Def;
typedef enum {     Key_IDLE = 0,     Key_ACK,     Key_WaitDoublePress,     Key_WaitDoublePressIdle,     Key_LongPress,     Key_STUCK } KeyStatus_Def;
typedef enum {     KeyEvent_Idle = 0,     KeyEvent_PutDown,     KeyEvent_RealeaseUp,     KeyEvent_Click,     KeyEvent_DoubleClick,     KeyEvent_LongPressStart,     KeyEvent_LongPressRepeat,     KeyEvent_LongPressEnd,     KeyEvent_Stuck,     KeyEvent_Free } KeyEvent_Def;
typedef struct Key {     struct Key *pNext;     uint32_t    dwPressedTicks;     uint32_t    dwReleasedTicks;     uint32_t    dwLongPressRepeat_Ticks;     uint8_t     byDebounce_Count;     uint8_t     byEvent;     uint8_t     byKey_Level;     uint8_t     byKeyStatus;     uint8_t     byMultiplePressEnable;     GetIOStatus pGetIOLevel_Func;     KeyEventProcess pProcess_Func; } KeyInfo_Def;        

标签:Ticks,模块,KeyEvent,记录,pHandle,Key,按键,Level,Def
From: https://www.cnblogs.com/cc-cnblogs/p/17839060.html

相关文章

  • 淘宝商家私信脚本,自动批量阿里旺旺版,按键精灵源码分享
    在UI界面设置话术后用#号分割多条,然后启动就会自动给搜素下面的商家发送指定消息的私信,脚本代码和UI界面代码我下面会分享出来,自己粘贴就可以用。UI界面:  UI界面代码:====================================================界面1:{请在下面设置话术:{输入框:{名称:"......
  • 闲鱼捡漏扫货脚本,低价下单,全自动安卓按键精灵开源代码!
    之前给客户定制的,功能就是可以在最新发布区识别低价商品,符合价格条件的自动下单这么一个效果,省的人工一个个去看价格。UI界面:  UI界面代码:=====================================================界面1:{激活页面(检测速度不建议快):{输入框:{名称:"输入框11",提示内......
  • 硬件开发笔记(十二):RK3568底板电路电源模块和RTC模块原理图分析
    前言  做硬件做系统做驱动,很难从核心板做起,所以我们先依赖核心板,分析底板周围的电路,然后使用AD绘制原理图和设计PCB,打样我司测试底板,完成硬件测试,再继续系统适配,驱动移植,从而一步一步完善成为一个功能完善的底板,且搭载了我们跳完的系统和驱动。  本篇文章,先从底板的电源电......
  • 抖音自动评论脚本,可按关键词,实现批量点赞,按键精灵开源版!
    这个脚本是我之前给一个客户开发的,现在用着也没啥意义,开发了很多,我索性就把代码直接分享出来,给一些新手做学习研究用,里面很多结构都是自己花费了很大的心思和心血才弄出来的,所以价值很高。UI界面: ui界面代码:============================================界面1:{请在下面......
  • 抖音主播私信脚本,给直播间的主播发消息,按键精灵脚本开源
    这个脚本运行后会给正在直播的主播自动发送话术消息,也是用按键精灵写的,我自己测试运行没有任何问题,下面是UI和代码。UI界面:  界面代码:=================================================界面1:{请在下面设置话术:{输入框:{名称:"输入框1",提示内容:"提示用户应该......
  • 快手自动关注脚本,导入快手号和ID,按键精灵开源脚本
    用按键精灵写的一个脚本,界面里面你可以导入对方的快手号,也是ID,然后进入主页后启动脚本它会自动一个个给你关注,非常的高效率。ui界面:  ui界面代码:=======================================================界面1:{请在下面设置话术:{输入框:{名称:"输入框1",提示内......
  • 陌陌附近人打招呼脚本,可自动回复消息,按键精灵开源脚本
    用按键写的一个陌陌自动打招呼发送指定话术消息的一个脚本,它还会检测对方的消息,然后自动回复指定信息,下面是UI界面和代码,你可以直接粘贴到自己的按键精灵里面运行,不会出错,已经测试过。UI界面:  脚本代码:=====================================================Dim布局名......
  • 小红书自动点赞评论脚本,可以群控多账号,按键精开源版代码分享
    这个需要连接服务器,你可以在易语言配置一个服务端,然后设置好端口,脚本部署在模拟器或者云手机或者真机里面实现多账号点赞评论的效果,针对一个作品,按键精灵写的脚本,服务端的脚本需要自己写哈,我没保存,我只保存了客户端的,这边分享出来,技术供大家学习研究。UI界面:  界面代码:===......
  • 拼多多商家私信群发脚本,按键精灵版工具,源码分享
    也是用按键精灵写的,实现的功能就是通过图色识别拼多多商品列表然后逐个对商家客服进行私信,私信内容可以在脚本里面提前配置好,代码怎么部署?回答:粘贴到你的按键精灵就行了,因为代码完全开源。UI界面:  脚本代码:=============================================='创建布局名称......
  • 抖音导入ID,UID自动关注脚本,按键精灵开源版工具
    这个源码是按键精灵开发的,前几天刚给客户定制的,这边直接分享出来,你可以自己打开按键精安卓端的,然后把我分享的代码一键粘贴过去就能用。UI界面:  按键精灵完整代码:【手机】==================================================='创建布局名称Dim布局名称,点击坐标,话术,......