按键消抖实验

                                                  按键消抖模块的设计与验证
1.章节导读
按键是最为常见的电子元器件之一,在电子设计中应用广泛。在 FPGA 的实验工程中,我们可以使用其作为系统复位信号或者控制信号的外部输入;在日常生活中,遥控器、玩具、计算器等等电子产品都使用按键。目前按键种类繁多,常见的有自锁按键、薄膜按键等等。我们开发板上使用的机械按键也是按键的一种,特点是:接触电阻小,手感好,按键按下或弹起时有―滴答‖清脆声;但由于其构造和原理,在按键闭合及断开的瞬间均伴随有一连串的抖动。本章节中,我们要根据机械按键的构造与原理,设计并实现按键消抖模块。来用modelsim来模拟按键抖动。
2.理论学习
如图 1 所示,我们所使用的按键开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而做的措施就是按键消抖,按键抖动原理图如图 2 所示。  

                                                                                图1 机械按键外观图

                                                                           图2 机械按键抖动原理图

抖动时间的长短由按键的机械特性决定,一般为 5ms~10ms。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。按键抖动会引起一次按键被误读多次。为确保控制器对按键的一次闭合仅作一次处理,必须去除按键的抖动。在按键闭合稳定时读取按键的状态,并且必须判别到按键释放稳定后再作处理。消抖是为了避免在按键按下或是抬起时电平剧烈抖动带来的影响。按键的消抖,可用硬件或软件两种方法。本文采取软件的方法去消抖。

软件消抖
如果按键个数较多,常用软件方法去抖,即检测出按键闭合后执行一个延时程序,根据抖动的时间为 5ms~10ms,我们产生一个 20ms 的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。

3.实战演练

3.1 实验目标

利用所学知识,设计并实现一个按键消抖模块,将外部输入的单比特按键信号做消抖处理后输出,输出信号正常可被其他模块调用

3.2 模块框图

因为我们要计数过滤掉按键抖动的时间,所以计数器是必不可少的,所以我们设计的模块一定会用到时序电路,所以时钟 s_clk 和复位 s_rst_n 信号一定先加上,而且是输入信号,另外还有一个输入信号就是按键的输入 key_in,我们最终要实现的就是对输入的key_in 信号进行去抖动,输出信号为去抖动后的稳定的按键信号 key_flag。根据上面的分析设计出的 visio 框图如图 3 所示。

3.3 波形图绘制 

3.4  代码书写

模块代码:

module Key_filter(

input                 s_clk               ,
input                 s_rst_n             ,
input                 key_in              ,
output    reg         key_flag          

);


//================================================================================|
//******************   Parameter and  Internal Signals        *********
//================================================================================|
reg      [19:0]    cnt_20ms             ;

parameter        CNT_MAX   =20'd999_999     ;


//================================================================================|
//   ********************  Main  Code     *****************************
//================================================================================|

//cnt_20ms
always@(posedge s_clk or negedge s_rst_n)begin  
   if(s_rst_n==1'b0)
      cnt_20ms <= 20'd0;
   else if(key_in==1'b1)
      cnt_20ms <= 20'd0;
   else if(cnt_20ms==CNT_MAX&&key_in==1'b0)
      cnt_20ms <=cnt_20ms;
   else
      cnt_20ms <=cnt_20ms+1'b1;
end 
//key_flag
always@(posedge s_clk or negedge s_rst_n)begin  
   if(s_rst_n==1'b0)
      key_flag <= 1'b0;
   else if(cnt_20ms==CNT_MAX-1'b1)
      key_flag <= 1'b1;
   else
        key_flag <= 1'b0;
end 

endmodule

测试代码:

`timescale  1ns/1ps

module tb_Key_filter();

reg                s_clk;
reg                s_rst_n;
reg                key_in ;
wire               key_flag;
//输入一个按键计数
reg      [21:0]        tb_cnt   ;
defparam            Key_filter_inst.CNT_MAX='d24;
parameter CNT_1MS = 20'd19 ,
          CNT_11MS = 21'd69 ,
          CNT_41MS = 22'd149 ,
          CNT_51MS = 22'd199 ,
          CNT_60MS = 22'd249 ;
//初始化输入信号
 initial begin
        s_clk = 1'b1;
        s_rst_n <= 1'b0;
        key_in <= 1'b0;
        #20
        s_rst_n <= 1'b1;
  end
  
  
always #10 s_clk = ~s_clk;

//tb_cnt
always@(posedge s_clk or negedge s_rst_n)begin
   if(s_rst_n==1'b0)
     tb_cnt <= 22'd0;
    else if(tb_cnt==CNT_60MS)
	 tb_cnt<=22'd0;
	else 
	  tb_cnt<=tb_cnt+1'b1;
end 
//key_in
always@(posedge s_clk or negedge s_rst_n)begin
   if(s_rst_n==1'b0)
      key_in<= 1'b0;
    else if(tb_cnt>=CNT_1MS&&tb_cnt<=CNT_11MS||tb_cnt>=CNT_41MS&&tb_cnt<=CNT_51MS)
	 key_in<={$random} % 2;
	else if(tb_cnt>=CNT_11MS&&tb_cnt<=CNT_41MS)
	  key_in<= 1'b0;
	else
	  key_in<= 1'b1;
end


Key_filter          Key_filter_inst(

.s_clk                                 (s_clk     ),
.s_rst_n                               (s_rst_n   ),
.key_in                                (key_in    ),
.key_flag                              (key_flag  )					          
);



endmodule

仿真效果:

 

 

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值