verilog之按键消抖的理解

 按键在按下时会产生抖动,释放时也会产生抖动,所以在设计键盘扫描程序时必须考虑按键的消抖,我们一般只考虑按下时的抖动,而放弃对释放时抖动的消抖。抖动时间一般为20ms左右。按下的最终结果是低电平。

  按键去抖思路是:检测到按下时延时20ms,再检测,如果状态仍为按下,则确认是按下的;如果状态为弹起的,则确认是干扰,无按键按下。

  假如rst_in 为一个按键,直接连接至FPGA里面的复位引脚作为全局复位,所以按键消抖的原理为:当rst_in按键按下时可能会出现抖动,需要停20ms之后再去检测这个按键是否按下(FPGA里面的这个引脚的电平是否改变),这样就达到了按键消抖的目的

 如下图所示:

有一个概念要理一下,按键按下时会有抖动,也就是说我们其实只按一次,但是实际产生的“按下”却是许多次的,这些许多次集中在这20ms里。我们按的只是一次,而实际却产生了许多次,那么就必须滤除其他的次数。为了得到真正的“按下”,通过延时20ms,把其他的“按下”(也就是抖动)给滤除了。然后再次判断是否有按下,因为有的时候干扰很大。

   而在FPGA中,基于下面的程序,理解如下:在这个程序里检测按键是否按下的方法是脉冲边沿检法。而在单片机里是判断是否为低电平的方法(那么在FPGA中可不可以也用这个方法呢?)第一次检测到后,启动20ms计数器,时间到后再检测。这里的检测方法跟脉冲边沿检测法有异曲同工之处,FPGA过20ms检测按键是否按下,存储检测到的值,并且按位取反与前一个20ms检测的值相与,得到一个值,如果为1,则判断按键按下,否则则无按下。所以跟单片机按键扫描的原理是一样的,不同的是检测方法不一样。

 图2 FPGA按键的理解示意图

// Module name: key_test.v
// 描述: 检测开发板上的四个按键 KEY1~KEY4, 当检测到按键按下时,相应的 LED 灯翻转
//======================================================
`timescale 1ns / 1ps
module key_test (
clk, // 开发板上输入时钟: 50Mhz
key_in, // 输入按键信号(Reset, KEY1~KEY3)
led_out // 输出 LED 灯,用于控制开发板上四个 LED(LED1~LED4)
);
//========================================================
// PORT declarations
//========================================================
input clk;
input [3:0] key_in;
output [3:0] led_out;
wire rst_n=1'b1;
//寄存器定义
reg [19:0] count;
reg [3:0] key_scan; //按键扫描值 KEY
//==============================================
// 采样按键值,20ms 扫描一次,采样频率小于按键毛刺频率,相当于滤除掉了高频毛刺信号。
//==============================================
黑金 FPGA 原创教程
黑金动力社区 84 / 426
always @(posedge clk or negedge rst_n) //检测时钟的上升沿和复位的下降沿
begin
if(!rst_n) //复位信号低有效
count <= 20'd0; //计数器清 0
else
begin
if(count ==20'd999_999) //20ms 扫描一次按键,20ms 计数(50M/50-1=999_999)
begin
count <= 20'b0; //计数器计到 20ms,计数器清零
key_scan <= key_in; //采样按键输入电平
end
else
count <= count + 20'b1; //计数器加 1
end
end
//====================================================
// 按键信号锁存一个时钟节拍
//====================================================
reg [3:0] key_scan_r;
always @(posedge clk)
key_scan_r <= key_scan;
wire [3:0] flag_key = key_scan_r[3:0] & (~key_scan[3:0]); //当检测到按键有下降沿变化时,代表该按键被按下,按键有效
//=====================================================
// LED 灯控制,按键按下时,相关的 LED 输出翻转
//=====================================================
reg [3:0] temp_led;
always @ (posedge clk or negedge rst_n) //检测时钟的上升沿和复位的下降沿
begin
if (!rst_n) //复位信号低有效
temp_led <= 4'b1111; //LED 灯控制信号输出为低, LED 灯全灭
else
begin
if ( flag_key[0] ) temp_led[0] <= ~temp_led[0]; //按键 KEY1 值变化时,LED1 将做亮灭翻转
if ( flag_key[1] ) temp_led[1] <= ~temp_led[1]; //按键 KEY2 值变化时,LED2 将做亮灭翻转
if ( flag_key[2] ) temp_led[2] <= ~temp_led[2]; //按键 KEY3 值变化时,LED3 将做亮灭翻转
if ( flag_key[3] ) temp_led[3] <= ~temp_led[3]; //按键 KEY4 值变化时,LED4 将做亮灭翻转
end
end
assign led_out[0] = temp_led[0];
assign led_out[1] = temp_led[1];
assign led_out[2] = temp_led[2];
assign led_out[3] = temp_led[3];
endmodule

每 20ms 程序会检查一下按键的状态, 如果这次检测为低电平而且上次检测为高电平的话,说明有按键按下,相对应的 LED 灯反转。 一般按键按下时的按键抖动为低于 20ms 的脉冲信号,这些高频脉冲信号会被滤除。提高了按 键的可靠性。
 

发布了38 篇原创文章 · 获赞 73 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/woshiyuzhoushizhe/article/details/100917995