[原创] 独立按键消抖

一纸玫瑰   2016-10-28 17:43 楼主

独立按键消抖

一、独立按键简介

   我们用的机械按键有一种物理特性按键按下时会抖动5~10ms,当我们想要用按键来控制我们的外设时就必须对按键进行消抖。

二、按键的实际波形

  
file:///C:/Users/wwt/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png
  

我们采用计数器的方法来做按键消抖(滤波)波形图如下

  
file:///C:/Users/wwt/AppData/Local/Temp/msohtmlclip1/01/clip_image004.png
  

三、代码

  
module key_filter(
  
    input      wire          sclk,
  
    input      wire          rst_n,
  
    input      wire          key_in,
  
   
  
    output     reg        key_flag
  
);
  
  
parameter  CNT_10MS_MAX  = 24'd499_999;
  
  
reg [23:0] cnt_10ms;
  
reg        cnt_flag;
  
  
//10ms计数器计数
  
always@(posedge sclk or negedge rst_n)
  
    if(!rst_n)
  
       cnt_10ms <= 24'd0;
  
    else if(key_in == 1'b0)
  
       cnt_10ms <= cnt_10ms + 1'b1;
  
    else
  
       cnt_10ms <= 1'b0;
  
      
  
//10ms标志位产生
  
always@(posedge sclk or negedge rst_n)
  
    if(!rst_n)
  
       cnt_flag <= 1'b0;
  
    else if(cnt_10ms == CNT_10MS_MAX)
  
       cnt_flag <= 1'b1;
  
    else if(key_in == 1'b1)
  
       cnt_flag <= 1'b0;               
  
  
//按键标志产生
  
always@(posedge sclk or negedge rst_n)
  
    if(!rst_n)
  
       key_flag <= 1'b0;
  
    else if(cnt_10ms == CNT_10MS_MAX && cnt_flag == 1'b0)
  
       key_flag <= 1'b1;
  
    else
  
       key_flag <= 1'b0;   
  
  
endmodule
  

四、测试

测试脚本我们利用一个40ms的计数器在产生我们的按键波形,如图所示

  
file:///C:/Users/wwt/AppData/Local/Temp/msohtmlclip1/01/clip_image006.png
  


  
`timescale 1ns/1ns
  
  
module tb_key_filter();
  
  
    reg         sclk;
  
    reg         rst_n;
  
    reg         key_in;
  
   
  
    wire            key_flag;
  
   
  
    reg [20:0]  cnt_40ms;
  
  
key_filter key_filter_inst(
  
    .sclk       (sclk        ),
  
    .rst_n      (rst_n   ),
  
    .key_in     (key_in ),
  
  
    .key_flag   (key_flag    )
  
);
  
  
initial sclk = 1;
  
always #10 sclk = ~sclk;
  
  
initial begin
  
     rst_n <= 0;
  
    #35
  
     rst_n <= 1;
  
end
  
  
always@(posedge sclk or negedge rst_n)
  
    if(!rst_n)
  
         cnt_40ms <= 21'd0;
  
    else if(cnt_40ms == 21'd1_999_999)  
  
         cnt_40ms <= 20'd0;
  
    else
  
         cnt_40ms <= cnt_40ms + 1'b1;
  
         
  
always@(posedge sclk or negedge rst_n)
  
    if(!rst_n)
  
         key_in <= 1'b1;
  
    else if(cnt_40ms < 249_999)
  
         key_in <= 1'b1;
  
    else if(cnt_40ms < 499_999 && cnt_40ms > 249_999)
  
         key_in <= {$random};
  
    else if(cnt_40ms < 999_999 && cnt_40ms > 499_999)
  
         key_in <= 0;
  
    else if(cnt_40ms > 999_999 && cnt_40ms < 1_499_999)
  
         key_in <= {$random};
  
    else
  
         key_in <= 1'b1;                     
  
  
endmodule
  











回复评论 (3)

不错,我做过一个,就是对cloc计数,达到计数值才输出有效电平。
点赞  2016-10-28 19:09
引用: mars4zhu 发表于 2016-10-28 19:09
不错,我做过一个,就是对cloc计数,达到计数值才输出有效电平。

这样做比用状态机简单多了
点赞  2016-10-28 19:44
简单延时?
点赞  2016-11-20 10:50
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复