目录
RS触发器
软件消抖
RS触发器
在按键个数较少时可用硬件方法消除键抖动。如图 所示的 RS 触发器为常用的硬件去抖。
图中两个与非门构成一个 RS 触发器。当按键未按下时,输出为 0;
当键按下时,输出为 1。此时即使用按键的机械性能,使按键因弹性抖动而产生瞬时断开(抖动跳开 B),只要按键不返回原始状态 A,双稳态电路的状态不改变,输出保持为 0,不会产生抖动的波形。也就是说,即使 B 点的电压波形是抖动的,但经双稳态电路之后,其输出为正规的矩形波。这一点通过分析RS 触发器的工作过程很容易得到验证
软件消抖
如果按键个数较多,常用软件方法去抖,即检测出按键闭合后执行一个延时程序,根据抖动的时间为 5ms~10ms,我们产生一个 20ms 的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。
我们添加一个名为 cnt_20ms 用于计数 20ms 时间的计数器,每当系统检测到按键输入信号为低电平时 cnt_20ms 计数器就开始计数,在 cnt_20ms计数器计数期间内,如果再次检测到按键为高电平则说明上次检测到的低电平一定是个抖动,那么我们就将这个计数器清零,这样就最大程度保证延时的20ms时间不会太短. 因为我们不能保证20ms对每一次按键都适用。
另外,为了避免检测按键的结果出现长电平,而不是脉冲如下图
?其根本原因是 cnt_20ms 计数器计数到 999_999 后保持在999_999 的时间太久导致的。 (999999是20ms的clk计数值)
又发现 cnt_20ms 计数器计数到 999_998 的次数只有一个,而且最接近 999_999,在既保证去抖动时间的前提下使 key_flag 信号只产生一个脉冲信号。最终的波形结果如图? 所示。?
附上Verilog
module key
#(
parameter MAX_CNT = 20'd99_9999
)
(
input wire sys_clk,
input wire sys_rst_n,
input wire key_in, //按键输入
output reg key_flag //键值判断位
);
reg [19:0] clk_cnt_20ms; //20ms的CLK计数器存储在这里
//每到高电平就清0,低电平就自加
always @(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
clk_cnt_20ms <= 20'b0;
else if(key_in == 1'b1)
clk_cnt_20ms <= 20'b0;
else
clk_cnt_20ms <= clk_cnt_20ms + 1'b1;
//低电平20ms之后,按键还是低电平,说明真的有按键按下
always @(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
key_flag <= 1'b0;
else if(clk_cnt_20ms == (MAX_CNT - 1'b1) && (key_in == 1'b0))
key_flag <= 1'b1;
else
key_flag <= 1'b0;
endmodule
方法来自于火哥,感谢
|