查看: 835|回复: 0

【小脚丫Step FPGA】FPGA学习记录(2)----微风细雨

[复制链接]
  • TA的每日心情
    郁闷
    2017-12-4 18:33
  • 签到天数: 94 天

    连续签到: 1 天

    [LV.6]常住居民II

    发表于 2015-11-19 09:00:14 | 显示全部楼层 |阅读模式
    分享到:
    说话算数,这一节讲解按键消抖。先百度百科一下“按键消抖”。
    常用的按键开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了消除这种抖动带来的不良影响就必须进行按键消抖。
    先科普一下按键的抖动时间。抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。键抖动会引起一次按键被误读多次。为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。

    消抖是为了避免在按键按下或是抬起时电平剧烈抖动带来的影响。按键的消抖,可用硬件或软件两种方法。
    在按键数量较少的情况下,可以采用硬件消抖。盗图一张:

    但一般而言,为了简化电路,在含有控制器的电路中,绝大多数工程师都会选择软件消抖。软件消抖,即检测出键闭合后执行一个延时程序,5ms~10ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序。
    一般来说,软件消抖的方法是不断检测按键值,直到按键值稳定。实现方法:假设未按键时输入1,按键后输入为0,抖动时不定。可以做以下检测:检测到按键输入为0之后,延时5ms~10ms,再次检测,如果按键还为0,那么就认为有按键输入。延时的5ms~10ms恰好避开了抖动期。
    下面开始本人创作了。。。。
    查看了不少人的FPGA实现的按键消抖,发现大多数选择定时采样,将多次采样值进行逻辑运算,进而获知按键是否按下。
    例如百科中所提到的Verilog实现代码:
      assign key_done = (dout1 | dout2 | dout3); //按键消抖输出  always @(posedge count[17])  begin          dout1 <= key_in;          dout2 <= dout1;          dout3 <= dout2;  end  always @(negedge key_done[0])  begin          keyen = ~keyen; //将琴键开关转换为乒乓开关  end程序解释如下:
    程序中所用的方法是不断检测按键值。每当Count[17]上升沿到来,就进行检测输入信号。其中dout1,dout2,dout3分别为当前、上个Count[17]上升沿、上上个Count[17]上升沿输入数值。正常情况下为1,假如连续三次为0,三个信号作或运算,使得key_done信号为0,出现下降沿,这样就认为是有按键。
    点评如下:
    首先,这种直接将信号作为触发信号的形式是不可取的,应选择相同时钟,对信号进行判断执行。其次,这个采样方式只是将三次采样值进行逻辑操作,并没有实现按键消抖原理中所说的,检测出键闭合后执行一个延时程序,让前沿抖动消失后再一次检测键的状态。当然这样也有可取之处,代码精简,容易实现。在资源有限的情况下,可以使用。
    本人严格按照按键消抖原理,利用有限状态机(FSM)进行设计,实现了带上下拉参数的按键消抖模块。
    主要代码如下:
                            Idle:begin //等待触发                                if(btn_h2l || btn_l2h)begin                                        state_next = Wait;                                        if(btn_h2l)                                                btn_value_pre_next = 1'b0; //获取当前值                                        else                                                btn_value_pre_next = 1'b1;                                end                                else begin                                        state_next = Idle;                                end                        end                                                Wait:begin //延时20ms                                if(counter == 32'd499999)begin                                        counter_next = 0;                                        if(btn_value_pre == btn)begin //判断延时后检测按键值是否与之前相同                                                state_next = Stop;                                        end                                        else begin                                                state_next = Idle;                                        end                                end                                else begin                                        counter_next = counter + 1'b1;                                end                        end                                                Stop:begin                                btn_value_next = btn_value_pre;//稳定输出按键值                                state_next = Idle;                        end                                                default:begin                                state_next = Idle;                        end利用Analog Discovery进行检测,可以看出在检测到第一个上升沿后,延时20ms,再次检测按键值,确定按键按下后输出按键值。测试结果如下:
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-19 00:43 , Processed in 0.112318 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.