按键开关是各种电子设备不可或缺的人机接口。在实际应用中,很大一部分的按键是机械按键。在机械按键的触点闭合和断开时,都会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理。
在系统设计中,有各种各样的消除按键抖动的设计方法,硬件电路和软件设计都很成熟。不过我们这里要从另外一个角度来讨论按键的消抖,并给出一个用verilog给出一个具体的实现。
首先,看一个普通的机械按键的触点在闭合与断开时的波形(用示波器抓取)。
下面的四张图都是按键在闭合的时候抓到的波形。可以看到两个明显的趋势:
1. 按键在几个us之内就可以达到稳定状态,从高电平转换到底电平;
2. 在高电平转换到低电平的过程中,触点有非常明显的抖动。
下面的两张图是按键在断开的时候抓到的波形。也可以看到两个明显的趋势:
1. 按键的变化趋势比较缓慢,从低电平变为高电平需要大概10~20ms的时间;
2. 按键断开时没有闭合时那么大的抖动
下面两张图是用手迅速闭合按键然后就断开时,按键的输出波形。
在处理按键抖动的程序中,必须同时考虑消除闭合和断开两种情况下的抖动。所以,对于按键消抖的处理,必须按最差的情况来考虑。我们从上面的图上可以看到,按键输出的信号的跳变时间(上升沿和下降沿)最大是在20ms左右。按键一次闭合最短的时间大概是120ms左右。
如果我们把按键的输出做为一个时钟域(时钟频率未知,但信号的slow rate是已知的,既最大20ms左右)的信号,用另外一个时钟来采集这个按键的输出,则就可以把按键的消抖归结为一个最基本的CDC问题来处理。而问题的核心是如何确定采集时钟的频率。假设采集时钟的周期小于20ms,那么,采集时钟就有可能两次采到按键断开时的不确定的值,就没有办法避免采用CDC电路所想避免的问题。所以采集时钟的周期必须要大于20ms。假设采集时钟的周期大于120ms的话,就有可能采不到按键的闭合信号,所以采集时钟的周期必须小于120ms。我们在这里选用周期为25ms的采集时钟(频率为40Hz)。
下面的verilog实现实际上是一个标准的CDC电路,直接可以用来做按键的消抖。
module RMV_BJ (
BJ_CLK, //采集时钟,40Hz
RESET, //系统复位信号
BUTTON_IN, //按键输入信号
BUTTON_OUT //消抖后的输出信号
);
input B_CLK;
input RESET;
input BUTTON_IN;
output BUTTON_OUT;
reg BUTTON_IN_Q, BUTTON_IN_2Q, BUTTON_IN_3Q;
always @(posedge BJ_CLK or negedge RESET)
begin
if(~RESET)
begin
BUTTON_IN_Q <= 1'b1;
BUTTON_IN_2Q <= 1'b1;
BUTTON_IN_3Q <= 1'b1;
end
else
begin
BUTTON_IN_Q <= BUTTON_IN;
BUTTON_IN_2Q <= BUTTON_IN_Q;
BUTTON_IN_3Q <= BUTTON_IN_2Q;
end
end
wire BUTTON_OUT = BUTTON_IN_2Q | BUTTON_IN_3Q;
endmodule
在实际的实现中,我们首先要生成一个40Hz的时钟,然后有多少个按键就将上面的模块例化多少次就可以了。比如说我们有4个按键,那么下面的实现就可以了。其中KEY_CTL[3:0] 是按键的输入,KEY_OUT[3:0]是按键的输出。
RMV_BJ RMV_BJ0( .BJ_CLK(BJ_CLK), .RESET(RESET), .BUTTON_IN(KEY_CTL[0]), .BUTTON_OUT(KEY_OUT[0]) );
RMV_BJ RMV_BJ1( .BJ_CLK(BJ_CLK), .RESET(RESET), .BUTTON_IN(KEY_CTL[1]), .BUTTON_OUT(KEY_OUT[1]) );
RMV_BJ RMV_BJ2( .BJ_CLK(BJ_CLK), .RESET(RESET), .BUTTON_IN(KEY_CTL[2]), .BUTTON_OUT(KEY_OUT[2]) );
RMV_BJ RMV_BJ3( .BJ_CLK(BJ_CLK), .RESET(RESET), .BUTTON_IN(KEY_CTL[3]), .BUTTON_OUT(KEY_OUT[3]) );
下面的波形是实测出来的按键消抖前后的波形,红色的为消抖前,白色的为消抖后。
要注意的是,经过处理后的按键信号,实际上是一个时钟域为40Hz的信号,如果我们要将按键送给后级电路使用,那么必须要将其转换到后级电路的时钟域中,转换的方法与上面所述CDC电路相同。
另外不同的按键的闭合,断开抖动时间都是有差异的,上面所讲的例子只参照了一种普通的机械按键,所以可能不具有普遍性。但对于不同的按键,处理方法都是一样的,只要根据按键特性,选定采集时钟的频率就可以了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)