赞
踩
目录
由于机械按键的物理特性,按键被按下的过程中,存在一段时间的抖动,同 时在释放按键的过程中也存在抖动,这就导致在识别的时候可能检测为多次的按键按下,而通常检测到一次按键输入信号的状态为低电平,就可以确认按键被按下了,所以我们在使用按键时往往需要消抖,以确保按键被按下一次只检测到一次低电平。
我们理想中的按键是下面这样:
但是实际中的按键是这样的:
一般开发板上的按键都是机械按键,所以在按下的时候,会产生回弹的时刻,称为机械的弹性开关。机械按键在按下和松开有一个抖动的过程,这个过程大概在10ms到15ms之间,具体取决于实际情况。这导致你按键按下但不一定真的按下了,按键弹起来了但不一定真的弹起来了。 如果不消除这个抖动,那么我们想要的效果将会得到一个很不确定的值。
为了能够得到准确的按键信号,我们需要在检测到按键抖动时,延迟20ms再进行采样,即可得到稳定的按键信号。
设计思路如下:
(1)使用一个寄存器,将按键信号打一拍,将按键信号打一拍后的值与当前按键信号进行比较,来检测按键是否稳定。
(2)只要检测到按键不稳定,即还在抖动,就清零计数器,重新开始计数。
(3)只有当按键稳定后才启动计数器进行20ms的计数。
(4)如果按键信号未能稳定20ms时,key_flag <= 1'b0;认为按键值无效。
(5)只有当按键信号稳定20ms时,key_flag <= 1'b1;此按键值有效。
- module key_debounce
- #(parameter DELAY_CNT = 'd1_000_000)//50M时钟时的20ms计数值
- ( //防抖模块端口声明
- input clk ,//50M
- input rst_n ,
- input key ,//定义按键输入
-
- output key_out//定义按键输出
- );
- reg key_value ;//用于反馈key的值
- reg key_flag ;//按键标志
- reg [$clog2(DELAY_CNT) - 1:0] delay_cnt ;//用于延时计数
- reg key_reg ;//用于记住上一刻key的值
- assign key_out = key_flag & ~key_value;
- always @ (posedge clk or negedge rst_n) begin
- if (!rst_n) begin //复位,key_reg置1,即未按下,延时计数清0
- key_reg <= 1'b1;
- delay_cnt <= 'd0;
- end
- else begin
- key_reg <= key; //key_reg记下此时key的值
- if (key_reg != key) //若按键不稳定
- delay_cnt <= DELAY_CNT; //延时计数置满
- else if (key_reg == key) begin
- if (delay_cnt > 0)
- delay_cnt <= delay_cnt - 1'd1;
- //若20ms延时没结束,每次延时计数减1
- else
- delay_cnt <= delay_cnt;
- end
- end
- end
-
- always @ (posedge clk or negedge rst_n) begin
- if (!rst_n) begin
- key_flag <= 1'b0; //复位时按键标志置0
- key_value <= 1'b1; //按键值置1
- end
- else begin
- if (delay_cnt == 'd1) begin
- //20ms延时结束,按键标志置1,反馈值记下此时key的值
- key_flag <= 1'b1;
- key_value <= key;
- end
- else begin //20ms延时未到按键标志置0
- key_flag <= 1'b0;
- key_value <= key_value;
- end
- end
- end
-
- endmodule
-
该模块可以当成IP核使用,根据自己的FPGA时钟频率,计算出20ms需要的计数值,调用模块时,在顶层修改参数即可使用。如100M时钟时的调用如下所示:
- key_debounce #(.DELAY_CNT('d2_000_000))//100M时钟的计数值
- u_key_debounce(
- .clk (clk ),
- .rst_n (rst_n ),
- .key (key ),
- .key_out(key_out)
- );
将设计参数化,放入自己的代码库,供有需要时直接使用。相比于官方提供的封闭的IP核,自己设计的IP核虽然性能比不过,但是更灵活,方便进行个性化修改。FPGA其实就像搭积木一样,只要自己的代码库够丰富,设计只会越来越轻松! 此合集持续分享一些笔者自己设计的可复用硬件模块:FPGA搭积木
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。