按键消抖记录

按键消抖

1.产生原因

根据机械按键的构造和原理,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。所以在按键闭合及断开的瞬间均伴随有一连串的抖动。
按键抖动

2.消抖方法

分为硬件和软件消抖。
由于硬件消抖一般会增加器件,不方便且对电路板的制作有一定影响。这里采取软件消抖的方法。
检测出按键闭合后执行一个延时程序,根据抖动的时间为 5ms~10ms,我们产生一个 20ms 的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。

3.软件消抖
  1. 设计模块
    要计数过滤掉按键抖动的时间,所以计数器是必不可少的,那么需要时钟,还需要复位信号,以及按键信号。
    模块
  2. 时序图模拟

抖动的时间一般小于10ms,当有20ms 的时间内都没有抖动就说明按键已经处于稳定状态了。所以可以设计一个计数器,计数20ms,这期间没有抖动则此时是什么电平就是什么电平。那么我们需要找到一段20ms没有抖动的区间。当系统检测到按键为低电平时 , 计数器就计数,当检测到按键为高电平时计数器就清零。
时序图
上图注意到按键按下的时间较长时,是让cnt继续保持计数最大值,这样可以避免产生多个输出脉冲。

  1. 代码
module	key_filter
#(
	parameter	CNT_MAX = 20'd999999
)
(
	input	wire	sys_clk,
	input	wire	sys_rst_n,
	input	wire	key_in,
	
	output	reg	key_out
);

reg		[19:0]	cnt;

always@(posedge	sys_clk or negedge	sys_rst_n)
	if (sys_rst_n == 0 || key_in == 1'b1)
		cnt <= 20'd0;
	else	if (cnt == CNT_MAX)
		cnt <= CNT_MAX;
	else	if (key_in == 1'b0)
		cnt <= cnt + 1;

always@(posedge	sys_clk or negedge	sys_rst_n)
	if (sys_rst_n == 0)
		key_out <= 1'b0;
	else	if (cnt == CNT_MAX - 1)
		key_out <= 1'b1;
	else	
		key_out <= 1'b0;	

endmodule
  1. 仿真代码
`timescale	1ns/1ns

module	tb_key_filter();

reg		sys_clk, sys_rst_n, key_in;
wire	key_out;

reg		[7:0]	tb_cnt;		//利用tb_cnt来模拟按键抖动计数器

initial
	begin
		sys_clk = 1'b1;
		sys_rst_n <= 1'b0;
		key_in <= 1'b1;
		#20
		sys_rst_n <= 1'b1;
	end

always #10 sys_clk = ~sys_clk;
//tb_cnt:按键过程计数器,通过该计数器的计数时间来模拟按键的抖动过程
always@(posedge	sys_clk or negedge	sys_rst_n)
	if (sys_rst_n == 0 )
		tb_cnt <= 8'd0;
	else	if (tb_cnt == 8'd249)
		tb_cnt <= 8'd0;
	else
		tb_cnt <= tb_cnt + 1;
//key_in:产生输入随机数,模拟按键的输入情况		
always@(posedge	sys_clk or negedge	sys_rst_n)
	if (sys_rst_n == 0 )
		key_in <= 1'd1;
	else	if ((tb_cnt >= 8'd19 && tb_cnt <= 8'd49) || 
				(tb_cnt >= 8'd169 && tb_cnt <= 8'd199))
//在该计数区间内产生非负随机数 0、1 来模拟 10ms 的前抖动和 10ms 的后抖动
		key_in <= ($random) % 2;	
	else	if (tb_cnt >= 8'd49 && tb_cnt <= 8'd149)	
		key_in <= 1'b0;
	else
		key_in <= 1'b1;

key_filter
#(
	.CNT_MAX(20'd24)
)	
key_filter_inst
(
	.sys_clk	(sys_clk),
	.sys_rst_n	(sys_rst_n),
	.key_in		(key_in),			
	.key_out	(key_out)
); 


endmodule
  1. RTL视图
    在这里插入图片描述

  2. 仿真时序图

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值