基于FPGA的按键消抖(含代码)

        机械按键在按下和松开有一个抖动的过程,这个过程大概在10ms到15ms之间,具体取决于实际情况。如果不消除这个抖动,那么我们想要的效果将会得到一个很不确定的值,比如我想要的是按一下数码管显示1,再按一下数码管管显示2,依次显示3,4,5,6;如果不消抖,我按键按一下上面的每一个值都可能显示,所以无法达到我想要的目的。

真实按键效果如下:

想要的效果如下:

当然,也有机械按键不需要消抖的设计,比如说复位按键,复位按键要求我在按下复位按键后系统回归到原始状态或者一个设定的状态,那么按键按下和松开期间抖动了多少次对结果并没有影响,所以可以不用消抖。

现在我们明确一点,按键有按下,按下后没有松开的等待过程和松开的过程,只有按键按下和松开有机械抖动的效果。那么我们要做的就是判断按键按下的那一刻做一个20ms的延时,然后等待按键松开的那一刻,再做一个延时,整个过程就完成了。

        下面给出Verilog程序设计:(系统时钟50M,低电平复位,低电平按键按下)

module shake(		
	input      clk   ,		  
	input      rstn  ,    
	input      key   ,      //按键信号
	output reg shape        //消抖信号
	);
	
//例化模块
//shake shake1(		
//	.clk   (clk  ),		  
//	.rstn  (rstn ),    
//	.key   (key  ),      
//	.shape (shape)  
//);

	parameter delay=999999; //20ms计数,仿真建议50
	reg [19:0]t20ms;
	reg       t    ;
	reg [ 1:0]cm   ;

	always@(posedge clk)    //按键信号延时一个时钟
		t <= key;
	wire thl = t&&(!key);    //t————|____key,下降沿
	wire tlh = (!t)&&key;    //t____|————key,上升沿

	always@(posedge clk or negedge rstn)
		begin
			if(!rstn)begin
				shape <= 0;
				t20ms <= 0;
				cm    <= 0;
			end else case(cm)
				0:begin
					if(thl)begin  //等待按键发生
						cm    <= 1;
						shape <= 0;
						t20ms <= 0;
					end else begin
						shape <= 0;
						t20ms <= 0;
						cm    <= 0;
					end 
				end
				1:begin
					if(t20ms == delay)begin    //20ms延时
						shape <= 0;
						t20ms <= 0;
						cm    <= 2;
					end else begin
						shape <= 0;
						t20ms <= t20ms+1;
						cm    <= 1;
					end
				end
				2:begin 
					if(tlh)begin  //等待按键松开
						shape <= 0;
						t20ms <= 0;
						cm    <= 3;
					end else begin
						shape <= 0;
						t20ms <= 0;
						cm    <= 2;
					end
				end
				3:begin
					if(t20ms == delay)begin    //20ms延时,同时给出消抖信号
						shape <= 1;
						t20ms <= 0;
						cm    <= 0;
					end else begin
						shape <= 0;
						t20ms <= t20ms+1;
						cm    <= 3;
					end
				end
				default:begin
					shape <= 0;
					t20ms <= 0;
					cm    <= 0;
				end
			endcase
		end
	
endmodule

        如果要实现按键按一下,计数器加一下,就可以把shape波形作为计数器的时钟。

       下面给出Verilog程序设计:(系统时钟50M,低电平复位,低电平按键按下)

module shake(		
	input            clk   ,		  
	input            rstn  ,    
	input            key   ,      //按键信号
	output reg [3:0] count        //按键个数,10进制
	);
	
//例化模块
//shake shake1(		
//	.clk   (clk  ),		  
//	.rstn  (rstn ),    
//	.key   (key  ),      
//	.count (count)  
//);

	parameter delay=999999; //20ms计数,仿真建议50
    reg       shape;
	reg [19:0]t20ms;
	reg       t    ;
	reg [ 1:0]cm   ;

	always@(posedge clk)    //按键信号延时一个时钟
		t <= key;
	wire thl = t&&(!key);    //t————|____key,下降沿
	wire tlh = (!t)&&key;    //t____|————key,上升沿

	always@(posedge clk or negedge rstn)
		begin
			if(!rstn)begin
				shape <= 0;
				t20ms<= 0;
				cm    <= 0;
			end else case(cm)
				0:begin
					if(thl)begin  //等待按键发生
						cm    <= 1;
						shape <= 0;
						t20ms<= 0;
					end else begin
						shape <= 0;
						t20ms<= 0;
						cm    <= 0;
					end 
				end
				1:begin
					if(t20ms== delay)begin    //20ms延时
						shape <= 0;
						t20ms <= 0;
						cm    <= 2;
					end else begin
						shape <= 0;
						t20ms <= t20ms+1;
						cm    <= 1;
					end
				end
				2:begin 
					if(tlh)begin  //等待按键松开
						shape <= 0;
						t20ms<= 0;
						cm    <= 3;
					end else begin
						shape <= 0;
						t20ms<= 0;
						cm    <= 2;
					end
				end
				3:begin
					if(t20ms== delay)begin    //20ms延时,同时给出消抖信号
						shape <= 1;
						t20ms <= 0;
						cm    <= 0;
					end else begin
						shape <= 0;
						t20ms <= t20ms+1;
						cm    <= 3;
					end
				end
				default:begin
					shape <= 0;
					t20ms <= 0;
					cm    <= 0;
				end
			endcase
		end

    always@(posedge clk or negedge rstn)
        begin
            if(!rstn)begin
                count <= 0;
            end else begin
                if((count == 9)&&(shape))begin   //按键10进制计数器
                    count <= 0;
                end else if(shape)begin
                    count <= count+1;
                end else begin
                    count <= count; 
                end
            end
        end
	
endmodule

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绯红姜梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值