[文章]

HI3861驱动【通用按键框架-单击,长按,连发(带加速);组合键;组合长按】

2020-11-13 22:33:32  93 人机交互 鸿蒙系统 HarmonyOS 鸿蒙OS
分享

按键驱动视频

小按键,大学问按键是最常用的人机交互的输入方式,但是按键有很多学问,你知道吗?
问:你知道按键怎么获取键值吗?
我:按键就是获取按下的键值,一般电路下,没按下的时候是高电平,按下就是低电平,获取到低电平就触发。
问:那我要松手触发呢?
我:...
问:长按呢?
我:就按下的时候延时呗
问:那怎么保证其他程序的实时性,不被延时打断?
我:...
问:双击呢?
我:...
问:按下连续触发呢?
我:...
问:组合按键呢?
我:...
问:组合长按呢?
我:...
没错,这就是我第一次出来找工作的时候被问到的问题,那时候我刚毕业,以年少轻狂,桀骜不驯的心态去找工作,也是第一次被问得无地自容,一个最常用的按键,竟然有这么大的学问,那时候也看到了自己的不足,一个小小的按键都有这么大的学问,我需要学的地方还很多啊。
按键的处理方式,以及滤波处理
用过按键都知道,按下的时候会有抖动,需要加滤波,但是绝大部分人都只处理按下的时候的抖动,而忘记了松手的抖动,这个松手抖动也是我工作中遇到的问题,特此分享一下,处理按键滤波需要处理按下抖动和松手抖动!
单击,也分按下触发和抬起触发,不同的场景需要不同的处理方式
长按,单击不松开,并计数到长按的时间,触发长按
双击,本篇没有添加双击,但实现思路不难,检测到单击松手后,开始计数,在100ms内如果再次检测到单击,则判断为双击,如果超时没有检测到单击,则此次为单击
连发,连发机制为按下后开始计时,当超过长按时间后执行连发
组合,其实就把组合当做一个按键来处理即可,只要你传组合的键值给处理代码,代码就处理组合的键值
1.如果让你设计一个按键模块,你会怎么设计?
初学者可能会这样设计
   
  1. <span role="presentation"><span class="cm-keyword">if</span>(<span class="cm-variable">readkey_pin</span> <span class="cm-operator">==</span> <span class="cm-number">0</span>)</span>
  2. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>{</span>
  3. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-variable">delay</span>(<span class="cm-number">10</span>);</span>
  4. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-keyword">if</span>(<span class="cm-variable">readkey_pin</span> <span class="cm-operator">==</span> <span class="cm-number">0</span>)</span>
  5. <span role="presentation">        {</span>
  6. <span role="presentation">           <span class="cm-comment">//do somthing</span></span>
  7. <span role="presentation">        }</span>
  8. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>}</span>
复制代码

有的人会用考虑到实时性,采用中断的方式。
还有的人会使用定时器扫描的方式,也就是优化第一种里面的延时,在主循环里面获取键值。
但是遇到按键多的时候,处理起来比较麻烦,用延时方式肯定是会堵塞其他程序运行,用中断的方式,可能会占用比较多的中断源,所以采用扫描的方式比较合适一般的工程。
2.本框架的实现思路和特点
本框架采用扫描的方式,对每一个按键注册相应的功能,对每一个按键进行扫描,如果扫描到某个按键,则进入处理程序处理
采用软件滤波机制,滤波时间可调,长按时间可调,连发加速时间可调,移植方便,通用性强
简单的说就是,你给什么键值过来,我就处理什么键值的按键,然后根据注册的功能返回相应的执行键值(如:A键按下的值是1,那么经过处理,返回A短按键值是0,长按是1,连发是2...)
本框架使用的是读取GPIO高低电平扫描的方式,但是开发板上3个按键都是接入GPIO5,但只有一个是可以直接读取电压,其他两个是需要读取AD值来判断按键,所以本教程需要自己外接按键,也比较符合实际项目中的按键设计处理

3.重点移植代码讲解
程序模块放在key_driver.c 和 key_driver.h 里边
key_driver.c里的枚举设置经过处理的键值,在主程序中根据这些键值进行逻辑处理
  1. <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n44" mdtype="fences"><span role="presentation">typedef enum</span>
  2. <span role="presentation">{</span>
  3. <span role="presentation"><span cm-text="">​</span></span>
  4. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>KEY_DOWN_POWER=1,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* POWER键按下 */</span>
  5. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>KEY_UP_POWER,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>    /* POWER键弹起 */</span>
  6. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>KEY_LONG_POWER,<span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>  <span class="cm-tab" role="presentation" cm-text="        ">  </span>/* POWER键长按 */</span>
  7. <span role="presentation" class="cm-tab-wrap-hack"><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  8. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>KEY_DOWN_ADD,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* ADD键按下 */</span>
  9. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>KEY_LONG_ADD,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* ADD键长按 */</span>
  10. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>KEY_DOWN_DEC,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* DEC键按下 */</span>
  11. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>KEY_LONG_DEC,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* ADD键长按 */</span><span role="presentation" class="cm-tab-wrap-hack"><span class="cm-tab" role="presentation" cm-text="        ">  </span></span>
  12. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>Couple_down,<span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>//组合按键按下</span>
  13. <span role="presentation" class="cm-tab-wrap-hack"><span class="cm-tab" role="presentation" cm-text="        ">    </span>Couple_long,<span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span><span role="presentation"><span cm-text="">​</span></span>
  14. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>KEY_REPEAT_POWER,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span> /* POWER键连发 */</span>
  15. <span role="presentation">}KEY_ENUM;</span></pre><p cid="n45" mdtype="paragraph" class="md-end-block md-p"><span md-inline="plain" class="md-plain">头文件宏定义</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n46" mdtype="fences"><span role="presentation">/* 按键滤波时间50ms, 单位10ms(按键扫描函数要放在10ms定时器或者任务中)</span>
  16. <span role="presentation"> 只有连续检测到50ms状态不变才认为有效,包括弹起和按下两种事件</span>
  17. <span role="presentation">*/</span>
  18. <span role="presentation">#define BUTTON_FILTER_TIME <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>5</span>
  19. <span role="presentation">#define BUTTON_LONG_TIME <span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>200<span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 持续2秒,认为长按事件 */</span>
  20. <span role="presentation">#define BUTTON_REPEAT_TIME<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>30<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 300ms 重复按键 */</span>
  21. <span role="presentation">#define BUTTON_DOWN_TIME<span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>10       /* 100ms 按下后20ms执行 */</span>
  22. <span role="presentation">#define KEY_NONE  0<span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 0 表示按键事件 */</span>
  23. <span role="presentation"><span cm-text="">​</span></span>
  24. <span role="presentation">#define REPEAT_SPEED_UP_EN  1<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 重复按键加速,由默认的300ms重复->200ms->100ms->50ms  重复速度越来越快  */</span>
  25. <span role="presentation">#define SpeedUp_Period<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>3000<span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 重复按键切换速度的周期,设定3秒后切换 */</span>
  26. <span role="presentation"><span cm-text="">​</span></span></pre><p cid="n47" mdtype="paragraph" class="md-end-block md-p"></p><p cid="n48" mdtype="paragraph" class="md-end-block md-p"><span md-inline="plain" class="md-plain">BUTTON_T这个结构体是定义一个按键的功能</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n49" mdtype="fences"><span role="presentation">typedef struct</span>
  27. <span role="presentation">{</span>
  28. <span role="presentation">/* 下面是一个函数指针,指向判断按键手否按下的函数 */</span>
  29. <span role="presentation">uint8_t (*IsKeyDownFunc)(uint8_t buffer); /* 按键按下的判断函数,1表示按下 */</span>
  30. <span role="presentation">uint8_t Count;<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 滤波器计数器 */</span>
  31. <span role="presentation">uint8_t FilterTime;<span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 滤波时间(最大255,表示2550ms) */</span>
  32. <span role="presentation">uint16_t ShortCount;<span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 短按计数器 */</span>
  33. <span role="presentation">uint16_t LongCount;<span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 长按计数器 */</span>
  34. <span role="presentation">uint16_t LongTime;<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 按键按下持续时间, 0表示不检测长按 */</span>
  35. <span role="presentation">uint8_t  State;<span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 按键当前状态(按下还是弹起) */</span>
  36. <span role="presentation">uint8_t KeyCodeUp;<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 按键弹起的键值代码, 0表示不检测按键弹起 */</span>
  37. <span role="presentation">uint8_t KeyCodeDown;<span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 按键按下的键值代码, 0表示不检测按键按下 */</span>
  38. <span role="presentation">uint8_t KeyCodeLong;<span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 按键长按的键值代码, 0表示不检测长按 */</span>
  39. <span role="presentation">uint8_t RepeatSpeed;<span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 连续按键周期 */</span>
  40. <span role="presentation">uint8_t RepeatCount;<span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 连续按键计数器 */</span>
  41. <span role="presentation">uint8_t SpeedUpCount;<span class="cm-tab" role="presentation" cm-text="        ">   </span>/* 连发加速计数器 */</span>
  42. <span role="presentation">}BUTTON_T;</span></pre><p cid="n50" mdtype="paragraph" class="md-end-block md-p"><span md-inline="plain" class="md-plain">使用的时候根据按键的多少来创建多大的结构体数组,本例程使用了4个按键,故设置按键功能的结构体数组如下</span></p><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n51" mdtype="fences"><span role="presentation">BUTTON_T ButtonType[4]={</span>
  43. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>{</span>
  44. <span role="presentation">        IsKeyDownPower,  <span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>/* 按键按下的判断函数,1表示按下 */</span>
  45. <span role="presentation">        BUTTON_FILTER_TIME/2, <span class="cm-tab" role="presentation" cm-text="        ">  </span>//单次扫描为10ms</span>
  46. <span role="presentation">        BUTTON_FILTER_TIME, <span class="cm-tab" role="presentation" cm-text="        ">    </span>//滤波时间 0~255 最大2550ms</span>
  47. <span role="presentation">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>   /* 短按计数器初始值设为0 */</span>
  48. <span role="presentation">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>   /* 长按计数器初始值设为0 */</span>
  49. <span role="presentation">        BUTTON_LONG_TIME, <span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>//长按时间 在宏定义设置,这里使用连发或者长按都要设置</span>
  50. <span role="presentation">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span> <span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>   //当前按键的状态,初始化为0</span>
  51. <span role="presentation">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>   //按键抬起的键值,</span>
  52. <span role="presentation">        KEY_REPEAT_POWER,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>//按键按下的键值,</span>
  53. <span role="presentation">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>   //按键长按键值,设为0则不使能长按<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>   </span>
  54. <span role="presentation">        BUTTON_REPEAT_TIME, <span class="cm-tab" role="presentation" cm-text="        ">    </span>//连发周期,也就是隔多久按一下,宏定义修改,这里设置不为0,则使能连发</span>
  55. <span role="presentation">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span>       <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>    //连发计数器     </span>
  56. <span role="presentation">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>   //连发加速计数器</span>
  57. <span role="presentation">    },</span>
  58. <span role="presentation">    </span>
  59. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>{</span>
  60. <span role="presentation">        IsKeyDownAdd,    </span>
  61. <span role="presentation">        BUTTON_FILTER_TIME/2, </span>
  62. <span role="presentation">        BUTTON_FILTER_TIME, </span>
  63. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  64. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  65. <span role="presentation" class="cm-tab-wrap-hack">        BUTTON_LONG_TIME, <span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  66. <span role="presentation">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>    </span>
  67. <span role="presentation" class="cm-tab-wrap-hack">        KEY_DOWN_ADD, <span class="cm-tab" role="presentation" cm-text="        ">  </span></span>
  68. <span role="presentation" class="cm-tab-wrap-hack">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  69. <span role="presentation" class="cm-tab-wrap-hack">        KEY_LONG_ADD,<span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  70. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  71. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  72. <span role="presentation">        0</span>
  73. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>},</span>
  74. <span role="presentation" class="cm-tab-wrap-hack"><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  75. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>{</span>
  76. <span role="presentation">        IsKeyDownDec,    </span>
  77. <span role="presentation">        BUTTON_FILTER_TIME/2, </span>
  78. <span role="presentation">        BUTTON_FILTER_TIME, </span>
  79. <span role="presentation" class="cm-tab-wrap-hack">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  80. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  81. <span role="presentation" class="cm-tab-wrap-hack">        BUTTON_LONG_TIME, <span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  82. <span role="presentation" class="cm-tab-wrap-hack">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  83. <span role="presentation" class="cm-tab-wrap-hack">        KEY_DOWN_DEC, <span class="cm-tab" role="presentation" cm-text="        ">  </span></span>
  84. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  85. <span role="presentation" class="cm-tab-wrap-hack">        KEY_LONG_DEC, <span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  86. <span role="presentation" class="cm-tab-wrap-hack">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  87. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  88. <span role="presentation">        0</span>
  89. <span role="presentation">    },</span>
  90. <span role="presentation" class="cm-tab-wrap-hack"><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  91. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>{</span>
  92. <span role="presentation">        IsKeyDownDecADD, </span>
  93. <span role="presentation">        BUTTON_FILTER_TIME/2, </span>
  94. <span role="presentation">        BUTTON_FILTER_TIME, </span>
  95. <span role="presentation" class="cm-tab-wrap-hack">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  96. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  97. <span role="presentation" class="cm-tab-wrap-hack">        BUTTON_LONG_TIME, <span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  98. <span role="presentation" class="cm-tab-wrap-hack">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  99. <span role="presentation" class="cm-tab-wrap-hack">        Couple_down, <span class="cm-tab" role="presentation" cm-text="        ">   </span></span>
  100. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  101. <span role="presentation" class="cm-tab-wrap-hack">        Couple_long, <span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  102. <span role="presentation" class="cm-tab-wrap-hack">        0, <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  103. <span role="presentation" class="cm-tab-wrap-hack">        0,<span class="cm-tab" role="presentation" cm-text="        ">  </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span><span class="cm-tab" role="presentation" cm-text="        ">    </span></span>
  104. <span role="presentation">        0</span>
  105. <span role="presentation"><span class="cm-tab" role="presentation" cm-text="        ">    </span>},</span>
  106. <span role="presentation">};</span>
  107. <span role="presentation"><span cm-text="">​</span></span>
  108. <span role="presentation"><span cm-text="">​</span></span>
  109. <span role="presentation">//获取执行按键是否按下函数 </span>
  110. <span role="presentation">uint8_t IsKeyDownPower(uint8_t buffer) <span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>{if ((buffer == 0x01)) return 1; return 0;}  </span>
  111. <span role="presentation">uint8_t IsKeyDownAdd(uint8_t buffer) <span class="cm-tab" role="presentation" cm-text="        ">   </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>{if ((buffer == 0x02)) return 1; return 0;}<span class="cm-tab" role="presentation" cm-text="        "> </span>    </span>
  112. <span role="presentation">uint8_t IsKeyDownDec(uint8_t buffer)        {if ((buffer == 0x04)) return 1; return 0;} </span>
  113. <span role="presentation">uint8_t IsKeyDownDecADD(uint8_t buffer)<span class="cm-tab" role="presentation" cm-text="        "> </span><span class="cm-tab" role="presentation" cm-text="        ">    </span>{if ((buffer == 0x03)) return 1; return 0;}</span></pre><p cid="n52" mdtype="paragraph" class="md-end-block md-p"></p><p cid="n53" mdtype="paragraph" class="md-end-block md-p"></p>
复制代码

注意:
在设置读取键值的时候,应和此处判断是否按下的键值一致
如 uint8_t IsKeyDownPower(uint8_t buffer)                 {if ((buffer == 0x01)) return 1; return 0;}  
此处函数键值设为1,则读取到的某个按键键值应设置为 1
1.在设置按键功能的时候应注意逻辑冲突,如按键抬起的键值,不建议和其他功能一起使用,比如同时设置了按下触发和抬起触发,那么就会返回两个值,一个是按下的一个是抬起的,除非你的项目真的需要这样的处理。
2.设置连发应注意不要使能长按,连发的机制是超过了长按的时间就会触发,如果你使能了长按的键值,那么就会先返回长按的键值,再触发连发
3.使能连发需把连发触发周期值设置,和按下的键值,连发就是返回你多次按下的键值,所以需要设置
4.使能连发加速 需要在宏定义使能 REPEAT_SPEED_UP_EN  设为 1


当构建完按键功能函数之后,只需要在定时器中或者任务中调用 bsp_KeyPro(uint8_t _KeyCode); KeyCode为读取到IO口的键值,周期为10ms
获取经过处理的键值函数为 uint8_t bsp_GetKey(void),就可以获取经过处理的键值了
在Hi3861上移植步骤1.创建按键组合
创建一个.c文件用来处理执行扫描函数
先定义处理一下按键组合,此处定义了3个按键,但是处理函数那里初始化了4个,因为有判断函数,如果没有获取到那个键按下,是不会处理相应的功能的,这里是为了演示,实际项目中应注意节省空间
#define G_SET_BIT(a,b)                            (a |= (1 << b))
#define G_CLEAR_BIT(a,b)                          (a &= ~(1 << b))


#define KEY_NUM 3
//这里定义的按键IO口为GPIO0 1 2
WifiIotGpioIdx key_io_array[KEY_NUM] = {WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_NAME_GPIO_2};  //IO口数组
WifiIotGpioValue singlekey_value_array[KEY_NUM] = {1, 1, 1};  //设置上拉输入,没有按下的时候是1
创建一个任务,初始化按键IO口,并执行
void Key_Function_Init(void)
{
    osThreadAttr_t attr;
    GpioInit();
    //复用引脚为GPIO
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_FUNC_GPIO_0_GPIO);
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_FUNC_GPIO_1_GPIO);
    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_IO_FUNC_GPIO_2_GPIO);

    //设置为输入
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_GPIO_DIR_IN);
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_GPIO_DIR_IN);
    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_GPIO_DIR_IN);

    //设置上拉输入
    IoSetPull(WIFI_IOT_IO_NAME_GPIO_0, WIFI_IOT_IO_PULL_UP);
    IoSetPull(WIFI_IOT_IO_NAME_GPIO_1, WIFI_IOT_IO_PULL_UP);
    IoSetPull(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_IO_PULL_UP);
    attr.name = "Key_Scan_Task";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024;
    attr.priority = 26;

    if (osThreadNew((osThreadFunc_t)Key_Scan_Task, NULL, &attr) == NULL) {
        printf("[Key_Scan] Falied to create Key_Scan_Task!\n");
    }
    printf("Key scan task init succes!\r\n");
}

    SYS_RUN(Key_Function_Init);     
      
然后在任务函数中扫描按键,并把键值放进按键处理函数
void *Key_Scan_Task(const char arg[])
{
    (void)arg;
    bsp_InitButtonQueqe();
    uint8_t Key_Value = 0;
    while (1)
    {
        for (uint8_t i = 0; i < KEY_NUM; i++)  //这样处理就可以比较方便的获得组合按键的键值
        {
            GpioGetInputVal(key_io_array, &singlekey_value_array);

            if (singlekey_value_array == 0)
            {
                G_SET_BIT(Key_Value, i);
            }
            else
            {
                G_CLEAR_BIT(Key_Value, i);
            }           
        }
         bsp_KeyPro(Key_Value);
       // printf("Keyvalue is %d!\r\n", Key_Value);      
        usleep(10000);          //10ms
    }
    return NULL;
}
外部文件调用按键模块
既然按键模块做好了,那实际应用应该是在主函数中调用的,对吧,那么我们只需把这个按键模块包含到你的主函数中,再包含头文件,再获取按键就行了。
1.先把按键模块编进系统,在application/sample/wifi-iot/app/BUILD.gn 中添加编译指令
e1a440abf17840f889d337c13843827.png
我的主函数是mainapp,所以需要另外创建一个app(小白可以直接用官方教程Hi3861开发板第二个示例程序(my_first_app))作为主函数调用各个模块
然后修改你的主函数下的BUILD.gn,包含按键模块的路径
dfa32151a24b32cfd8c8dd875fccda0.png
最后可以在主函数中调用按键模块啦
先包含头文件
#include "key_driver.h"
然后创建一个任务,在任务函数的while(1)里面添加
  
  1. <span role="presentation"> if(bsp_GetKey() > 0)</span>
  2. <span role="presentation">    {</span>
  3. <span role="presentation">       printf("key value is %d \r\n",bsp_GetKey());          </span>
  4. <span role="presentation">    }</span>
复制代码

打印的数字即为你设定的返回的键值
总结实话说,这个框架不是特别好,主要还是在使能按键功能这里,需要设置的参数比较多,另外没有加入双击,下一版本优化一下吧。
打算下个教程把这个AD检测的按键处理方式给加进去,方便更多人使用

0

harmonyos_key.zip

13.73 KB, 下载次数: 0, 下载积分: 积分 -1 分

评分

参与人数 1积分 +5 收起 理由
dianzi_0101 + 5 您的帖子很精彩,期待您分享的下一个帖子!

查看全部评分

2020-11-13 22:33:32   评论 分享淘帖
您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发表新帖