[应用方案] 如何设计按键检测的松手检测

[复制链接]
 楼主| Thethree 发表于 2016-8-9 08:58 | 显示全部楼层 |阅读模式
说到按键,我还是有不少研究的,其实按键没我们想的那么简单,要把按键程序写好也不是一件容易的事,功能要求:单击、双击、长按及组合,按下不动,返回有效值速度越来越快,多用在参数调节,这些都是值得大家去研究的,还有8个IO口,让16个独立按键与8个独立按键共同使用这是没有问题的。
        扯远了,今天只讨论如何做松手检测,松手检测意义,很简单,就是按下按键只对应一次操作,不会因为按着不动就不停的返回按键值,我们大多时候见到的松手检测程序就是 “while(!k1)”,一种等待式写法,打个比方,这就如同你插上热得快烧水,你坐在旁边看着,等着水热,拜拜浪费时间。这种写法根本不适应实际应用,拜拜浪费CPU时间。看一下代码:
       功能:按键检测子函数,四个独立按键接在P2口高四位,调用时返回按键值1,2,3,4,没有按键按下返回0.
  1. char ReadKey(void)
  2. {
  3.          static Key_on_off = 0;
  4.          unsigned char num,temp = 0;
  5.         num = P2;                                 //  读取P2口状态
  6.          num&= 0xf0;                         //  屏蔽第四位
  7.          if(num != 0xf0)             //  判断是否有按键按下
  8.           {
  9.             if(Key_on_off == 0)         //  自锁变量
  10.                  {
  11.                          /***********  相对高级的松手检测          ****************/
  12.                  Key_on_off = 1;   // 如果屏蔽这句话,将没有松手检测,数字将加的很快
  13.                           switch(num)                          //  读取按键信息
  14.                                  {
  15.                                    case 0xe0: temp=1;break;
  16.                                    case 0xd0: temp=2;break;
  17.                                    case 0xb0: temp=3;break;
  18.                                    case 0x70: temp=4;break;
  19.                                  }
  20.                 /***********  最笨的松手检测          ****************/
  21.                 /*                while(num != 0xf0)             //  判断是否有按键按下
  22.                                  {
  23.                                     num = P2;                         //  读取P2口状态
  24.                                     num&= 0xf0;                         //  屏蔽第四位

  25.                                  }          */
  26.                   }
  27.           }
  28.          else
  29.           {
  30.             Key_on_off = 0;    //  当没有任何按键按下时  解锁
  31.           }
  32.                 return temp;
  33. }


 楼主| Thethree 发表于 2016-8-9 08:59 | 显示全部楼层
利用一个静态变量Key_on_off,记住一定要是静态的或者全局的,初始化为零,当检测到按键按下的时候,同时要满足Key_on_off等于0,才进入里面判断是哪个按键,同时将Key_on_off置1,那么当按键还没有松开,函数又被第二次及以上调用时,由于Key_on_off等于1,就不按键值解析里面去,按键值返回的是默认的0,属于无效值,着就相当于上了一把锁,那么什么时候解锁了,看下面当检测到没有按键按下的时候,Key_on_off = 0 , 一担松手就解锁,当再次按下的时候出一次有效按键值,再次上锁。如此往返。。。
今天有人提到了我的程序中没有去抖动检测,关于按键的抖动,别人教你的一半都是延时5~10MS再次检测, 想说的是,延时去抖动会拖慢的系统,5MS在我看着这么多么的奢侈,5MS可以执行完成太多的任务,就这么浪费了, 痛心、痛心。
    本函数调用要求为:20~50ms调用一次,就能得到很好的消抖动效果,你可以想象一下,在时间轴上,0时刻检测到按键按下,到10ms时刻再次检测到按键按下,就确定按键按下。首先大家要明白一点,只有按键按下的时候才有电平抖动,没有按按键是没有按键抖动的,去按键抖动是为了防止一次按下按键而而检测到几次按下。在看看我的设计,0时刻检测到按键按下,那么按键肯定按下了,我已经返回了有效值,20MS后抖动已经过去,低电平已经稳定,不会再返回按键有效值,达到去抖动目的。。。
[url=][/url]
落叶行健ywm 发表于 2016-8-9 09:04 | 显示全部楼层
利用有限状态量就解决了,延时都是学习时使用的。实际根本不会考虑的。
598330983 发表于 2016-8-9 11:25 | 显示全部楼层
松手检测意义,很简单,就是按下按键只对应一次操作,不会因为按着不动就不停的返回按键值
598330983 发表于 2016-8-9 11:26 | 显示全部楼层
画了一下波形图,发现也可以通过边沿检测中断实现,比如上升沿中断
bblb 发表于 2016-8-9 14:51 | 显示全部楼层
分享,谢了
天灵灵地灵灵 发表于 2016-8-9 21:59 | 显示全部楼层
中断的效果应该是最好的,不会影响别的。
天灵灵地灵灵 发表于 2016-8-9 22:00 | 显示全部楼层
但是如果在主函数体里面,那就中断用不得了,反过来,如果按着不丢,系统会不会看门狗复位
bobde163 发表于 2016-8-9 23:32 | 显示全部楼层
学习一下,希望楼主能再对另外几种情况的分析一下,比如长按有效、放开才有效的情况
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

236

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部