按键去抖动模块的实现
作者:互联网
按键去抖动算是除了流水灯外最常见的入门案例吧,通常使用的开关为机械弹性开关,当按下或松开按键时, 由于弹片的物理特性,不能立即闭合或断开,往往会在断开或闭合的短时间内产生机械抖动。而消除这种抖动的过程即称为按键消抖。
如下图为一般的按键抖动模型:
按键有明显的前抖动及后抖动,由于机械按键按下到有效响应的时间比较长。所以一般去抖方式都是在前抖动与后抖动间加延时,以便检测稳定电平的状态。笔者迄今看过很多的去抖动代码,方法各异,有的很灵活,有的简单明了,感兴趣的可自行检索了解。下面自贴出笔者觉得最简单灵活的一种以及正点原子的方法。
正点原子的很多项目是开源的,可以去了解。去抖代码如下:
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