搜索
bottom↓
回复: 33

关于按键扫描,长按短按的问题。

[复制链接]

出0入4汤圆

发表于 2015-1-8 08:42:32 | 显示全部楼层 |阅读模式


最近在做一个产品需要用到4按键扫描。

要用到 长按 短按 连按,甚至组合按键等。
参考了一些例程 。

如关于按键扫描程序的终极讨论 http://www.cnblogs.com/craftor/p/3811748.html
还有  很好的按键扫描程序 http://wenku.baidu.com/link?url=fPJW7Gx_AhmZ4KzhJoQFeAmqLn5G3-H2fOluindOZoBLagHGs2Aya3TnncJbKrQlwReOSeJK29-fekzxkfH92crQfdvYDYe-urz7WGJ_tcO



在实验长按短按的时候,发现短按正常,长按的时候 除了响应长按的结果, 每次都会触发一下短按。不知有什么办法解决。

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2015-1-8 08:54:45 | 显示全部楼层
时间控制  首先0.5s以内算短按,大于1s算长按;其次判断短按要排除连按。

出0入0汤圆

发表于 2015-1-8 09:03:13 | 显示全部楼层
短按要检测按键弹起,要不然区分不了短按和长按

出0入0汤圆

发表于 2015-1-8 09:22:53 | 显示全部楼层
用时间限制 做下滤波算法

出0入0汤圆

发表于 2015-1-8 09:29:21 | 显示全部楼层
组合按键, 扫描...
小心处理

出0入264汤圆

发表于 2015-1-8 09:43:25 | 显示全部楼层
处理感兴趣的按键事件就好了
keyscan  ---> keyvalue | keydown | keyrepeat | keylong | keyup

处理感兴趣按键事件:
if(keyvalue != keynull)
{
    if(keyvalue & keylong == keylong )
   {
        //长按处理
   }
}

出0入4汤圆

 楼主| 发表于 2015-1-8 09:50:13 | 显示全部楼层
myin4 发表于 2015-1-8 09:03
短按要检测按键弹起,要不然区分不了短按和长按

现在的算法可以区分长按和短按,但是没办法解决的是 每次长按抬起的时候 会多识别一次短按,也就是说无法识别长安抬起的还是短按抬起。 - -

出0入0汤圆

发表于 2015-1-8 09:56:48 | 显示全部楼层
执行短按程序时先判断下有没有长按处理过。

出0入4汤圆

 楼主| 发表于 2015-1-8 10:51:09 | 显示全部楼层
liuyonguo 发表于 2015-1-8 09:56
执行短按程序时先判断下有没有长按处理过。

如果处理过就不执行短按了吗,那要是有过长按的案件如何处理短按。

出0入0汤圆

发表于 2015-1-8 11:11:57 | 显示全部楼层
看看~~~~~~~~~~~~~~

出0入0汤圆

发表于 2015-1-8 11:33:38 | 显示全部楼层
本帖最后由 zljcat3721 于 2015-1-8 11:34 编辑

按下与抬起都进行时间计数,如果按键没抬起过,就不再进行按键处理

编辑原因:漏字了

出0入0汤圆

发表于 2015-1-8 11:44:48 | 显示全部楼层
比较赞成2楼的实现方式。。。

出0入0汤圆

发表于 2015-1-8 12:35:02 | 显示全部楼层
参考一下~

[转]新型的按键扫描程序

出0入0汤圆

发表于 2015-1-8 14:30:40 | 显示全部楼层
对第一次按下开始的特定时间内的按钮做判断

出0入4汤圆

 楼主| 发表于 2015-1-8 14:48:14 | 显示全部楼层
deedeezi 发表于 2015-1-8 12:35
参考一下~

[转]新型的按键扫描程序

参考过了,很遗憾 他的办法也有这个 bug  - -

出0入0汤圆

发表于 2015-1-8 22:21:05 来自手机 | 显示全部楼层
要么检测按键抬起,

出0入0汤圆

发表于 2015-1-8 22:25:20 来自手机 | 显示全部楼层
靠,还没写完按错回车了,继续:要么使用间隔,即按键有效后间隔几百ms才能重新扫描检测

出0入0汤圆

发表于 2015-1-9 19:20:03 | 显示全部楼层
在长按处理过程中增加一个长按处理过标志,在短按处理过程中检测到有长按处理过标志的话就不处理短按处理。

出0入0汤圆

发表于 2015-1-9 19:28:41 | 显示全部楼层
本坛很多精典的例子,首推马老师书中!下面是其中一位网友分享的
http://www.amobbs.com/forum.php? ... =%E6%8C%89%E9%94%AE

出0入0汤圆

发表于 2015-1-10 00:46:41 | 显示全部楼层
马老师的书不错!!

出0入0汤圆

发表于 2015-1-10 09:32:02 来自手机 | 显示全部楼层
在按键按下的时候置位 按下 标志,并开始计时,在按键抬起的时候,计算按键事件,时间足够长则为长按键,否则,开始按键抬起超时计数,如果超时了,按键还没有按下,则为单击按键,如果再次按下,则为双击。所有计时推荐在定时期内,并通过状态机轮转。

出0入0汤圆

发表于 2015-1-10 09:44:17 | 显示全部楼层
看这个.
http://www.amobbs.com/forum.php?mod=viewthread&tid=5542774

出0入4汤圆

 楼主| 发表于 2015-1-12 08:34:43 | 显示全部楼层
jackybany 发表于 2015-1-9 19:28
本坛很多精典的例子,首推马老师书中!下面是其中一位网友分享的
http://www.amobbs.com/forum.php?mod=vie ...

看了下他的代码,貌似也没有谈论同一个按键 既有长按又有短按的情况。

我现在基本解决问题了。虽然bug还隐含存在,不过几率小很多、

在短按的时候增加了短按时常限制,必须落在范围内的才算有效短按。

部分代码如下:

  1. void    KEY_SCAN(void)
  2.         {
  3.                 u8  keys_val;
  4.                 READ_KEYS(keys_val);

  5.                 //按键端口上拉了,默认是高电平,有按键时变低。这里取反,有按键时变高。
  6.                 pinNow = 0xff - keys_val;

  7.                 pinSet_now = pinNow     & !SET;
  8.                 pinUp_now = pinNow>>1   & !UP;
  9.                 pinDown_now = pinNow>>2 & !DOWN;
  10.                 pinOk_now = pinNow>>3   & !OK;
  11.                     if(pinSet_now & pinSet_last)
  12.                         {
  13.                         set_cnt++;
  14.                         if(set_cnt>LONG_PRESS)              /*设置长按*/
  15.                             {
  16.                             set_cnt=0;
  17.                             set_long=TRUE;
  18.                            
  19.                             }
  20.                         }
  21.                      else
  22.                         {

  23. //                            else if (set_cnt>SHORT_PRESS)        /*设置短按*/
  24.                              if ((set_cnt>SHORT_PRESS)&&(set_cnt<SHORT1_PRESS))
  25.                                 {
  26.                                   set_cnt = 0;
  27.                                   set_short = TRUE;

  28.                                 }
  29.                               else
  30.                                 {
  31.                                 set_cnt = 0;
  32.                                 }

  33.                         }
  34.                        

  35.                     if (pinUp_now & pinUp_last)
  36.                         {
  37.                         up_cnt++;
  38.                         if (up_cnt>MID_PRESS)                   /*up连按*/
  39.                             {
  40.                             up_short = TRUE;
  41.                             up_cnt = up_cnt - REPEAT_PRESS;
  42.                             }
  43.                         }
  44.                     else
  45.                         {
  46.                         if (up_cnt>SHORT_PRESS)                 /*up短按*/
  47.                             {
  48.                             up_short = TRUE;
  49.                             up_cnt = 0;
  50.                             }
  51.                         }
  52.                     if (pinDown_now & pinDown_last)
  53.                         {
  54.                         down_cnt++;
  55.                         if (down_cnt>MID_PRESS)                 /*down连按*/
  56.                             {
  57.                             down_short = TRUE;
  58.                             down_cnt = down_cnt - REPEAT_PRESS;
  59.                             }
  60.                         }
  61.                     else
  62.                         {
  63.                         if (down_cnt>SHORT_PRESS)                 /*up短按*/
  64.                             {
  65.                             down_short = TRUE;
  66.                             down_cnt = 0;
  67.                             }
  68.                         }
  69.                     if  (pinOk_now & pinOk_last)
  70.                         {
  71.                             ok_cnt++;
  72.                             if(ok_cnt>LONG_PRESS)                   /*ok长按*/
  73.                             {
  74.                                 ok_long=TRUE;
  75.                                 ok_cnt=0;
  76.                             }
  77.                         }
  78.                     else
  79.                             {
  80.                                 if(ok_cnt>SHORT_PRESS)              /*ok短按*/
  81.                                 {
  82.                                     ok_short=TRUE;
  83.                                     ok_cnt=0;
  84.                                 }
  85.                                 else
  86.                                     ok_cnt=0;
  87.                             }
  88.                         
  89.                         pinSet_last = pinSet_now;
  90.                         pinUp_last = pinUp_now;
  91.                         pinDown_last = pinDown_now;
  92.                         pinOk_last = pinOk_now;
  93.         }

  94. void    KEY_ANSWER(void)
  95.         {
  96.             u8  i;
  97.             if(set_long)
  98.             {
  99.                 if(!set_flag)
  100.                 {
  101.                 if(load_val)
  102.                 {
  103.                     show16(6,48,2,0,hz[9]);             /*载人*/
  104.                     load_val=0;
  105.                     dat_set[22]=9;
  106.                     set_long=FALSE;
  107.                 }
  108.                 else
  109.                 {
  110.                     show16(6,48,2,0,hz[10]);
  111.                     load_val=1;
  112.                     dat_set[22]=10;
  113.                     set_long=FALSE;
  114.                 }
  115.                 EEPROM_WRITE(22, dat_set[22]);
  116.                 }
  117.                 else set_long=FALSE;
  118.             }
  119.             if(ok_long)
  120.             {
  121.                 if(!set_flag)
  122.                 {
  123.                 if(sound_val)
  124.                 {
  125.                     MUTE=1;
  126.                     show16(0,48,2,0,sound[1]);
  127.                     sound_val=0;
  128.                     ok_long=FALSE;
  129.                 }
  130.                 else
  131.                 {
  132.                     MUTE=0;
  133.                     show16(0,48,2,0,sound[0]);
  134.                     sound_val=1;
  135.                     ok_long=FALSE;
  136.                 }
  137.                 }
  138.             }
  139.             if(set_short)
  140.             {
  141.                 set_flag=1;
  142.                 set_short=FALSE;
  143.                 set_num++;
  144.                 if(set_num==22)
  145.                     set_num=0;
  146.             }
  147.             if(up_short)
  148.             {
  149.                 up_num++;
  150.                 if(up_num>40)
  151.                     up_num=0;
  152.                 up_short=FALSE;
  153.             }
  154.             if(down_short)
  155.             {
  156.                 up_num--;
  157.                 if(up_num>40)
  158.                     up_num=40;
  159.                 down_short=FALSE;
  160.             }
  161.             if(ok_short)
  162.             {
  163.                 if(set_flag)
  164.                     {
  165.                     set_flag=0;
  166.                     set_num=-1;
  167.                     ok_short=FALSE;
  168.                     for(i=0;i<22;i++)
  169.                     EEPROM_WRITE(i, dat_set[i]);
  170.                     }

  171.             }

  172.         }
复制代码


出0入0汤圆

发表于 2015-1-12 09:32:58 | 显示全部楼层
按键的状态一般分为:短按,短按抬,上按,上按抬,连按,连按抬。
做好按键的这几个功能就可以了

出0入0汤圆

发表于 2015-1-12 10:33:57 | 显示全部楼层
我写给师弟去看的,参考马老师的状态机,你可以看看

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-1-12 11:10:46 | 显示全部楼层
中断方式实现的是可以的。

出0入0汤圆

发表于 2015-1-12 11:12:10 来自手机 | 显示全部楼层
一个小小的程序要做完美也是不容易

出0入4汤圆

 楼主| 发表于 2015-1-13 09:07:47 | 显示全部楼层
wongT 发表于 2015-1-12 10:33
我写给师弟去看的,参考马老师的状态机,你可以看看

多谢,先下载研究下。

出0入8汤圆

发表于 2015-9-23 23:00:31 | 显示全部楼层
学习一下,有没有不在一个口的散按键的写法,如果这样写是不是代码太多了,

出0入8汤圆

发表于 2015-9-23 23:02:45 | 显示全部楼层
学习一下,有没有不在一个口的散按键的写法,如果这样写是不是代码太多了,

出0入8汤圆

发表于 2015-9-23 23:04:36 | 显示全部楼层
学习一下,有没有不在一个口的散按键的写法,如果这样写是不是代码太多了,

出100入143汤圆

发表于 2015-9-23 23:13:18 | 显示全部楼层
huarana 发表于 2015-1-8 14:48
参考过了,很遗憾 他的办法也有这个 bug  - -

我一般是按键共分为:按下,释放,长按,重复,有效;按下并弹起事件为有效状态,“短按”=“有效”;也就是 按下≠短按

出0入4汤圆

 楼主| 发表于 2015-9-24 11:31:50 | 显示全部楼层
liaihua1997 发表于 2015-9-23 23:00
学习一下,有没有不在一个口的散按键的写法,如果这样写是不是代码太多了, ...

散按键 一样的做法  很简单的。

出0入0汤圆

发表于 2015-10-14 10:58:46 | 显示全部楼层
这个问题可以参考你的写法
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 10:35

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表