其他分享
首页 > 其他分享> > 按键去抖动模块的实现

按键去抖动模块的实现

作者:互联网

  按键去抖动算是除了流水灯外最常见的入门案例吧,通常使用的开关为机械弹性开关,当按下或松开按键时, 由于弹片的物理特性,不能立即闭合或断开,往往会在断开或闭合的短时间内产生机械抖动。而消除这种抖动的过程即称为按键消抖。

  如下图为一般的按键抖动模型:

  按键有明显的前抖动及后抖动,由于机械按键按下到有效响应的时间比较长。所以一般去抖方式都是在前抖动与后抖动间加延时,以便检测稳定电平的状态。笔者迄今看过很多的去抖动代码,方法各异,有的很灵活,有的简单明了,感兴趣的可自行检索了解。下面自贴出笔者觉得最简单灵活的一种以及正点原子的方法。

  正点原子的很多项目是开源的,可以去了解。去抖代码如下:

 1 //****************************************Copyright (c)***********************************//
 2 //原子哥在线教学平台:www.yuanzige.com
 3 //技术支持:www.openedv.com
 4 //淘宝店铺:http://openedv.taobao.com
 5 //关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
 6 //版权所有,盗版必究。
 7 //Copyright(C) 正点原子 2018-2028
 8 //All rights reserved
 9 //----------------------------------------------------------------------------------------
10 // File name:           key_debounce
11 // Last modified Date:  2019/4/14 16:23:36
12 // Last Version:        V1.0
13 // Descriptions:        按键消抖
14 //----------------------------------------------------------------------------------------
15 // Created by:          正点原子
16 // Created date:        2019/4/14 16:23:36
17 // Version:             V1.0
18 // Descriptions:        The original version
19 //
20 //----------------------------------------------------------------------------------------
21 // Modified by:            正点原子
22 // Modified date:
23 // Version:
24 // Descriptions:
25 //
26 //----------------------------------------------------------------------------------------
27 //****************************************************************************************//
28 
29 module key_debounce(
30     input        sys_clk ,
31     input        sys_rst_n ,
32 
33     input        key ,         //外部输入的按键值
34     output  reg  key_value ,   //消抖后的按键值
35     output  reg  key_flag      //消抖后的按键值的效标志
36 );
37 
38 //reg define
39 reg [19:0] cnt ;
40 reg        key_reg ;
41 
42 //*****************************************************
43 //**                    main code
44 //*****************************************************
45 
46 //按键值消抖
47 always @ (posedge sys_clk or negedge sys_rst_n) begin
48     if(!sys_rst_n) begin
49         cnt <= 20'd0;
50         key_reg <= 1'b1;
51     end
52     else begin
53         key_reg <= key;           //将按键值延迟一拍
54         if(key_reg != key) begin  //如果当前按键值和前一拍的按键值不一样,即按键被按下或松开
55             cnt <= 20'd100_0000;  //则将计数器置为20'd100_0000,
56                                   //即延时100_0000 * 20ns(1s/50MHz) = 20ms
57         end
58         else begin                //如果当前按键值和前一个按键值一样,即按键没有发生变化
59             if(cnt > 20'd0)       //则计数器递减到0
60                 cnt <= cnt - 1'b1;  
61             else
62                 cnt <= 20'd0;
63         end
64     end
65 end
66 
67 //将消抖后的最终的按键值送出去
68 always @ (posedge sys_clk or negedge sys_rst_n) begin
69     if(!sys_rst_n) begin
70         key_value <= 1'b1;
71         key_flag  <= 1'b0;
72     end
73     //在计数器递减到1时送出按键值
74     else if(cnt == 20'd1) begin
75         key_value <= key;
76         key_flag  <= 1'b1;
77         end
78     else begin
79         key_value <= key_value;
80         key_flag  <= 1'b0;
81     end
82 end
83 
84 endmodule

  以下是笔者最常用的方法:

 1 //**************************************************************************
 2 // *** file name      : Key_dejitter.v
 3 // *** version        : 1.0
 4 // *** Description    : Key_dejitter
 5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
 6 // *** Author         : Galois_V
 7 // *** Date           : 2022.5.12
 8 // *** Changes        : Initial
 9 //**************************************************************************
10 `timescale  1ns/1ps 
11 module Key_dejitter
12 #(
13     parameter                    SYS_FRE        = 100_000_000
14 )
15 (
16     input                        i_sys_clk       ,
17     input                        i_key_jitter    ,
18     output                       o_key_dejitter            
19 );
20 
21     
22     //Debounce the keys, generally 5ms-10ms.Here is 10ms
23     localparam            T_CNT    = 10 * SYS_FRE /1000;
24     localparam            WIDTH    = log(T_CNT);
25     
26     reg            [WIDTH-1:0]        r_cnt;
27     
28     function integer log;
29         input    [31:0]    i_data;
30         begin
31             for(log=0;i_data >0; log = log + 1)
32             begin
33                 i_data = i_data >> 1;
34             end
35         end
36     endfunction    
37     
38     always@(posedge i_sys_clk)
39     case(i_key_jitter)
40         0:  if(r_cnt[WIDTH-1]) r_cnt <= r_cnt;        //Only take the highest bit,so debounce time is in 5ms~10ms.
41             else r_cnt <= r_cnt + 1'b1;
42         1:  r_cnt <= 'd0;
43     endcase
44     
45     assign o_key_dejitter = r_cnt[WIDTH-1];
46     
47 endmodule

  笔者的方法是只对前去抖部分做延时,后去抖是松开按键部分,笔者觉得按键响应稳定时间足够长,没必要再对松开按键再进行一次去抖,只要保证输出按键信号无抖动即可。代码是按键低有效,仿真波形图结果如下:

  上图去抖仿真笔者是缩短了仿真时间,不然仿真时间过长,会浪费时间。红框处信号前抖动做了延时,后抖动直接在抖动前就完成。去抖后产生的输出信号没有抖动,实验成功。

 

标签:模块,抖动,sys,key,按键,input,reg
来源: https://www.cnblogs.com/WenGalois123/p/16360216.html