ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

按键去抖动模块的实现

2022-06-10 10:04:36  阅读:175  来源: 互联网

标签:模块 抖动 sys key 按键 input reg


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

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

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

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

 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有