[FPAG学习]第三部分:按键消抖

目录

一、按键消抖是什么?为什么要按键消抖?

二、理想按键与实际按键。

三、抖动时间 。

四、目的 。

五、解决办法。

六、Verilog代码。

七、按键消抖学习过程中必会的四个问题!


一、按键消抖是什么?为什么要按键消抖?

        按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

        在机械按键触点闭合和断开时,都会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理。 [1] 

        按键的抖动对于人类来说是感觉不到的,但对单片机来说,则是完全可以感应到的,而且还是一个很“漫长”的过程,因为单片机处理的速度在“微秒”级,而按键抖动的时间至少在“毫秒”级。 [2] 

        如果在触点抖动期间检测按键的通断状态,则可能导致判断出错,即按键一次按下或释放被错误地认为是多次操作,从而引起误处理。因此,为了确保单片机对一次按键动作只作一次响应,就必须考虑如何消除按键抖动的影响。

二、理想按键与实际按键。

理想按键
实际按键

三、抖动时间 。

        抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。这是一个很重要的时间参数,在很多场合都要用到。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。按键抖动会引起一次按键被误读多次。

        为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。

四、目的 。

        按键过后在键稳定部分得到一个标志信号。

五、解决办法。

        在按键按下以后等待一段时间,这段时间大于抖动时间,一般等待的时间为10ms,在等待完抖动后取得稳定值。

六、Verilog代码。

module KEY
(
    input       sys_clk     ,						//系统时钟为50MHz
    input       sys_rst_n   ,						//复位信号(一般为低电平)
    input       key         ,						//输入按键
    output      key_flag							//输出按键标志信号
);
//10ms计时器
parameter delay_10ms = 500_000;						//计满10ms的最大值
reg [18:0]cnt;										//计10ms的寄存器
always@(posedge sys_clk)
    if(!sys_rst_n)
        cnt <= 0;
    else if(key == 0)
        begin
            if(cnt == delay_10ms - 1)
                cnt <= cnt;
            else
                cnt <= cnt+1;
        end
    else
        cnt <= 0;
//使用assign对key_flag进行赋值
assign key_flag = (cnt == delay_10ms - 2)?1:0;
//使用always块对key_flag进行赋值
/*
always@(posedge sys_clk)
    if(!sys_rst_n)
        key_flag <= 0;
    else if(cnt == delay_10ms - 2)
        key_flag <= 1;
    else
        key_flag <= 0;
*/
endmodule

七、按键消抖学习过程中必会的四个问题!

问题一:在寄存器计到最大值减一时寄存器为什么保持不变?

        计时器是在按键按下时开始计数,由于按键抖动信号小于10ms,所以在抖动部分计时器计不满,当计时器计满10ms,即:

if(cnt == delay_10ms - 1)
    cnt <= cnt;

         此时,应得到按键标志信号,若寄存器cnt不保持,则又会重新计数,当下一次计满时又会出现一个按键标志信号,故当计时器计满10ms时,寄存器cnt应保持不变。

问题二:按键标志信号为什么只有一个时钟周期?

        按键在使用时通常是以一个信号的形式发挥作用,而理想按键就是按键按下就输出一个有效信号,如果按键标志信号为多个时钟周期,在使用时就会出现多个有效信号。

问题三:为什么要在计数器计到最大值减二时产生标志信号?

        标志信号产生的时刻是在计时器计满10ms的前一时刻,因为如果在计时器计满10ms是产生标志信号,那么当按键处于按下状态,计时器计满10ms后保持,此时标志信号也会一直处于拉高状态,使用时就会出现多个有效信号。所以

assign key_flag = (cnt == delay_10ms - 2)?1:0;

 这里括号里面的条件只要是在计时器计满的前一时刻就行。

问题四:三目运算符如何改写为always块?

        前面代码中assign赋值下面的注释部分就是always块,需要注意的是使用assign进行赋值时,赋值的对象只能是wire型,而always块里面的赋值的对象只能是reg型。在输入输出定义时,没写变量类型时默认为wire型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值