[讨论] 关于按键的抖动问题,想了好几天都没想透彻,痛苦啊…………

dxstar   2010-4-16 11:57 楼主
关于按键的处理,几乎所有的书,所有的教程都会有这么一句“由于按键会产生5ms-8ms的抖动,所以要进行相关消抖”。无论是软件消抖,还是中断消抖,都会用一种“先检测一次,过10ms后再检测一次”的理论。但我自己在开发板上试的时候,不用“10ms后再次检测”,就检测一次,从来都没出现过按一次键,会相应N次的情况。这下我就郁闷了。如果真的会产生5ms-8ms的抖动那,我应该会出现几次不正常的情况呀,那怕偶尔几次也好啊。关于这点,你请教各位,有人深入了解过这种按键的吗?我现在有以下几种想法想跟大家讨论:
  1.按键的抖动可能存在,但根本没有达到5ms-8ms这么长
  2.因为执行其它的程序也需要时间,这段时间就相当于是给按键消抖了
  3.最重要的一点,如果我想看这按键到底有没有抖动,或者抖动时间有多长,应该怎么来测试?(除了用示波器,因为我没有示波器)比如写一个什么程序,按一次键会出现数码管显示的值连跳N个值之类的。
  关于这个按键抖动的问题,我是想了那几天,试了N多的方法,都没有把这个问题想透彻,真的很痛苦啊,希望得到各位的帮助,大家一起进步吧

回复评论 (30)

不知道你什么开发板,什么程序,什么功能,抖动肯定是有的,你可以编写串口程序,看传到电脑上的按键响应次数
点赞  2010-4-16 13:03
我的见解:
1. 正如你所说,按键抖动的时间可能并没有5ms-8ms。但为什么还这么做呢,只是为了拉长按键的有效间隔,认为5ms-8ms之间的按键操作是无效的。
2. 这要的理解是偏颇的,如果是用for或while实现的延时就有你说的问题,这段时间被按键消抖独占了,但是如果用中断的话,就可以避免这样的问题。
3.  把按键接外部中断,内部用定时器计数,然后打印出两次外部中断之间定时器计数间隔。

个人见解,欢迎拍砖
点赞  2010-4-16 13:04
和你讨论一下测试方法
硬件:
把按键一端接地(MCU负电源端)另一端接AT89S51-MCU的P3.2脚。

软件:
变量声明
unsignet int i;
初始化中编
IT0=1;
EX0=1;
EA=1;
i=0;
外部中断0中编
i++;
运行程序,按下按键,观察变量i的值,如果为0,则没有抖动,否则,有抖动,而且i是抖动的次数。
你可以继续琢磨编程测试抖动维持了多少时间(我还没想好)

证明抖动的另一个方法是:编制一个按键次数累计显示程序,不要做去抖动处理,看看是不是每按一次就加1,如果是,就没有抖动,否则,证明有抖动。

再做一个按键控制LED发光二极管指示程序,不做去抖动处理,每按一次,发光二极管取反,测试是不是每次都能从不亮到亮,从亮到不亮。

甲按键和乙按键,控制同一个灯泡,甲按键控制灯泡亮,乙按键控制灯泡灭,编制程序,分别编去抖动和不去抖动,结果发现,这个功能做不做去抖动处理其效果都一样,也就是说,实现这个功能不需要做去抖动处理。不做去抖动处理也没发现问题,不代表按键抖动不存在。

抖动是绝对存在的,质量好的按键在1mS以内,质量差的在10mS以上,大多数在2-6mS范围(经验值)。

[ 本帖最后由 xu__changhua 于 2010-4-16 13:23 编辑 ]
点赞  2010-4-16 13:21
可以放在定时器里面判定,10ms以后再判断一次是否按键还存在,或者判定两次,这样就会好点了。
南京璞晓电子   www.cpx0.com需要 msn:njlianjian@hotmail.com
点赞  2010-4-16 14:01
我用FPGA也在学这个方面,这几天的问题也差不多是这个,来学习了!
有目的的学习是最有效的学习!
点赞  2010-4-16 14:20

回复 沙发 gavin84xu 的帖子

什么开发板应该没什么关系吧……。程序就是很简单的“按一次键,加一,数码管显示”。串口通信,现在我还没看到这部分内容。
点赞  2010-4-16 15:38

回复 板凳 chenzhufly 的帖子

谢谢你的回复,现在我也就你的回复谈谈我的看法。
1.按键延时10ms,这是编写按键的一个规范,我也很明白,自己以后写按键程序也会这么写,但问题是这个抖动到底对程序能有多大的影响,我却看不到心里很没底啊。
2.呵呵,就算用中断也会出现“消抖”可能的。首先我用的是动态扫描数码管的方式显示数字,每个数码管的时间是2ms,一共有六位,那么扫描一遍也就是说要12ms。也就是说在12ms内发生的事件,其实在数码管上显示的却只有一种状态。
3.这个方法就得另外接外围电路了……,这种方法做一个备案,实在不行就去弄弄……。我最想知道的就是如果不消抖,我就普普通通的写个按键程序,这个抖动能产生多大的影响。我并不是没事去钻什么牛角尖,个人感觉弄明白这个还是很重要的。
点赞  2010-4-16 16:02

回复 4楼 xu__changhua 的帖子

谢谢你的回复,你所说的测试方法,我回头试试,因为现在身边没那些元器件,我不太可能把开发板上的按键取下来吧……,呵呵
  先把我自己的加1代码贴出来,大家也帮忙看看,是否是我的程序本身出现了问题。
        首先定义一个bit flag=0;按键状态标志位
if(flag)
{
        if(key1==0)  //检测到按下
        {
                g_num++;  //自加1
                flag=0;                //标志位清零                       
        }
}
else
{
        if(key1==1)    //检测到如果按键松开,标志位置1
        {
                flag=1;
        }
}
Display();          //显示函数
点赞  2010-4-16 16:11

回复 5楼 njlianjian 的帖子

呃……,似乎版主大人没怎么明白我的意思哦。我现在想的不是如何消抖的问题,而是不消抖对程序的影响有多大的问题……呵呵
点赞  2010-4-16 16:13

回复 6楼 zqzq501311 的帖子

共同学习,共同讨论,共同进步
点赞  2010-4-16 16:13
哦,明白你的意思了,不去消抖的话,那么,就会出现有可能出现多个按键的误触发信号。你可以看到,你按一个按键以后,就会出现很多个按键增加的数据。另外,一般处理按键方式有问题:
1、按键没有松开,是延时多长时间以后默认第二次按键还是必须要按一次松开后才算一次按键?
2、按键消除抖动以后,则要判定本次按键是否有效,是否等到下次的按键才能继续执行程序?
你写的程序,可能会出现多次干扰现象。因为抖动的时间中按键的IO就会出现01的不断变化的。
南京璞晓电子   www.cpx0.com需要 msn:njlianjian@hotmail.com
点赞  2010-4-16 16:23

回复 8楼 dxstar 的帖子

第一,在定时中断里面的时候,不适宜做等待的工作。
第二,在定时中断里面,你2ms已经很快了。
第三,写中断程序的时候,扫描做在最前面。每一位的扫描程序结束后,可以扫描按键,如果有按键按下,写下一个标志位,然后等到下个中断的时候,先判断标志位,然后进行判断按键,按键还是保持状态,再判断是否有10ms或者20ms后按键是否有效,就默认此次按键有效。执行按键的程序。
第四。明白了么?按键的扫描和数码管的扫描也是一致的
南京璞晓电子   www.cpx0.com需要 msn:njlianjian@hotmail.com
点赞  2010-4-16 16:31

回复 12楼 njlianjian 的帖子

谢谢版主大人的回复呵。其实我就是想看到,我不消抖的话,按一次键出现多次按键这种情况。然而无论我怎么测试都“不存在抖动”,于是就对这个按键抖动对程序到底有多大的影响心里没底了。基础对这个“按键抖动”产生的怀疑……
还有,为什么版主这么容易加威望和芯币啊?
我也要加威望,我也要加芯币:@
我也要加威望,我也要加芯币:@
我也要加威望,我也要加芯币:@
点赞  2010-4-16 16:53

回复 4楼 xu__changhua 的帖子

呵呵,谢谢你给的检测方法哦。现在我重新找了一个按键按你的方法接单片机的外部中断。的确是有抖动的,多按几次后,会发现有那么一两次会加2之类的。呵呵,我怎么就没想到用外部中断测脉冲的方法来检测这个抖动呢,唉。
对了,你所说的抖动时间也可以用这种方法来检测的,相当于检测这个脉冲的高/低电平时间嘛,用计数器来计数就行啊,呵呵
点赞  2010-4-16 21:07

回复 14楼 dxstar 的帖子

评分按钮可以实现的 但是随着论坛级别越高 评分的分值会越多
加油!在电子行业默默贡献自己的力量!:)
点赞  2010-4-16 22:00
引用: 原帖由 dxstar 于 2010-4-16 21:07 发表
呵呵,谢谢你给的检测方法哦。现在我重新找了一个按键按你的方法接单片机的外部中断。的确是有抖动的,多按几次后,会发现有那么一两次会加2之类的。呵呵,我怎么就没想到用外部中断测脉冲的方法来检测这个抖动呢,唉 ...
偶尔显示加2,抖动次数应远远超过2,想深入研究或者验证的话,汇编语言编程,运行,按下按键,抬起按键,用仿真器查寄存器看结果,你会发现,抖动次数大的惊人。
按键还是接在p3.2到地之间:
        org 0000h
        sjmp main
        org 0003h
        inc dptr
        reti
        org 0020h
main:
        setb it0
        setb ex0
        setb ea
        mov dptr,#0
        sjmp $
        end
在仿真器中启动运行命令,全速运行程序,按下按键,松开按键,暂停运行程序,看看dph和dpl的值,抖动次数为dph*256+dpl
建议做这个实验是因外:
1----c语言运行程序效率低,切换频道时延时时间长,无意间对消除抖动做了贡献。
2----你说加1程序偶尔加了2,因为不知道你的编程机制,显示程序是需要时间的,这个时间是不是也被用对去抖动做贡献了,也未可知。
点赞  2010-4-17 00:16
另外,要想观察抖动明显,P3.2不要接触任何除按键以外的元件,特别是电容器,按键阴线也要尽可能短。
此外,若12M晶振,对于小于2us的抖动周期51单片机是检测不到的。
最后,FPGA的频率高,可以用FPGA检测到更多的抖动次数。
点赞  2010-4-17 00:24

回复 16楼 soso 的帖子

哇哦,管理员都出来,看来我这帖子发得很有水准嘛
还有我说的加威望之类的纯粹玩笑话
点赞  2010-4-17 01:14

回复 17楼 xu__changhua 的帖子

非常感谢你的回复,关于这个按键抖动的问题,你总是给出具体的解决方法,而且我也的确从中得到相应的帮助。关于更深入的探究,小弟实在不才,初学单片机,一时半会也深入不到哪去,还是就此打住,至少我现在把这个按键抖动理解了七七八八了。呵呵
点赞  2010-4-17 01:28
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复