[X]关闭

按键去抖(教程程序),求大神指导

文档创建者:Damon
浏览次数:7005
最后更新:2016-01-14
module Button(Clk,Rst,Sw1,Sw2,Led);// 模块接口
        input Clk; // 时钟信号
        input Rst; // 复位信号
        input Sw1; // 按钮SW1输入,0表示按下,1表示抬起
        input Sw2; // 按钮SW2输入
        output [1 : 0] Led; // led 输出
       
        /*
        教程中的开发板是4 个LED,本开发板2 个LED 稍作修改
        */
        reg [20 : 0]C1; //去抖动延时计时器C1
        reg [20 : 0]C2; //去抖动延时计时器C2
        reg [0 :0 ]Ledn; // 指示那个LED 输出
        reg [1 :0 ]Led; //Led 输出
        reg Sw1D,Sw1D1,Sw2D,Sw2D1; //同步延时中间信号
        wire Sw1_IsDwon,Sw2_IsDwon;//标示按钮按下的信号
       
        // 通过同步电路,实现判断按钮按下一次
        // 当按钮按下前一个时钟Sw1D1=0,Sw1D=0,Sw1_IsDwon=0
        // 挡按钮按下第一个时钟Sw1D1=0,Sw1D=1,Sw1_IsDwon=1
        // 挡按钮按下第二个时钟Sw1D1=1,Sw1D=1,Sw1_IsDwon=0
        assign Sw1_IsDwon = !Sw1D1 && Sw1D;
        //按钮SW2 的同步信号和SW1 一样
        assign Sw2_IsDwon = !Sw2D1 && Sw2D;
       
        // 此模块把按钮按下的判断信号延时1个时钟
        always @(posedge Clk ) begin
                if( !Rst )begin //
                        Sw1D1 <= 1'b0;
                        Sw2D1 <= 1'b0;
                end
                else begin
                        Sw1D1 <= Sw1D;
                        Sw2D1 <= Sw2D;
                end
        end
       
        always @(posedge Clk )
                if( !Rst )begin
                        Sw1D <= 1'b0;
                        Sw2D <= 1'b0;
                end
                else begin
                        //如果C1[20] 为1 则Sw1D 置1 表示按钮按下
                        // 如果按钮按下,则必须等到C1=0 才置Sw1D 为0 表示按钮抬起
                        if( C1[ 20 ] ) Sw1D <= 1'b1;
                        else if( Sw1D && C1==0 ) Sw1D <=1'b0;
                        //按钮SW2 和SW1 一样
                        if( C2[ 20 ] ) Sw2D <= 1'b1;
                        else if( Sw2D && C2==0 ) Sw2D <=1'b0;
                end
               
        always @(posedge Clk )
                if( !Rst )begin
                        C1 <= 21'd0;
                        C2 <= 21'd0;
                end
                else begin
                        // 如果按钮SW1 按下,则C1 开始计数,否则减计数,实现去抖动
                        if( !Sw1 ) begin
                                if( !C1[ 20 ] ) C1 <= C1 + 1'b1;
                                end
                        else if( C1 > 0 ) C1 <= C1 - 1'b1;
                        // 如果按钮SW2 按下,则C2 开始计数,否则减计数,实现去抖动
                        if( !Sw2 ) begin
                                if( !C2[ 20 ] ) C2 <= C2 + 1'b1;
                                end
                        else if( C2 > 0 ) C2 <= C2 - 1'b1;
                end
               
        //控制LED 的输出模块
        //每次按下LED 后,LED 移动移位
        //移动方向由按钮控制
        always @( posedge Clk )
                if(!Rst)begin
                        Ledn <= 1'd0;
                        Led <= 2'h0;
                end
                else begin
                if( Sw1_IsDwon ) Ledn <= Ledn + 1'b1;
                else if( Sw2_IsDwon ) Ledn <= Ledn - 1'b1;
                Led <= 2'h0; //LED 0 灭掉
                Led[Ledn] <= 1'b1; //LED 1 点亮
                //有些开发板是0 点亮,1 灭掉
                end
endmodule
上面是教程里的按键去抖程序,有点不理解,求大神帮忙介绍下这个去抖原理。
另外,
always @(posedge Clk )
                if( !Rst )begin
                        C1 <= 21'd0;
                        C2 <= 21'd0;
                end
                else begin
                        // 如果按钮SW1 按下,则C1 开始计数,否则减计数,实现去抖动
                        if( !Sw1 ) begin
                                if( !C1[ 20 ] ) C1 <= C1 + 1'b1;
                                end
                        else if( C1 > 0 ) C1 <= C1 - 1'b1;
                        // 如果按钮SW2 按下,则C2 开始计数,否则减计数,实现去抖动
                        if( !Sw2 ) begin
                                if( !C2[ 20 ] ) C2 <= C2 + 1'b1;
                                end
                        else if( C2 > 0 ) C2 <= C2 - 1'b1;
                end
这个always块里面,减计数,去抖是怎么实现的,为什么减计数就可以去抖,还有就是C1 >0,和上面!c2[20]有重合的部分,不理解。

发表评论已发布 3

shiwuge

发表于 2016-1-11 21:24:39 来自手机 | 显示全部楼层

按键在有效时,有大概20ms的不稳定期,必须确认按键是正确触发的,而不是误触发,这是消抖的本质

贾文洋

发表于 2016-1-12 09:08:58 | 显示全部楼层

减计数是为了让C1为0,只有C1为0时,才表示按钮抬起!那两个没有重合的部分,一个为正,另一个则为负~

贾文洋

发表于 2016-1-14 10:49:00 | 显示全部楼层

module key_filter(
        input clk,
                  input rst_n,
                  input key_in,
                  output reg key_flag,
                  output reg key_state);
                  //鐘舵
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则