FPGA学习altera 系列 第十九篇 单独按键消抖设计

2020-12-29 17:20:58 浏览数 (1)

大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。

今天给大侠带来“FPGA学习系列 altera"系列,持续更新。此学习心得是本人之前所写,所用设计软件为Quartus II 13.1,现Quartus II 新版本已更新到19 ,以下仅供初学者学习参考。后续会更新其他系列,敬请关注。话不多说,上货。

对于每一个的小实验,我们都可以把它看作是一个小项目,逐步的去分析,设计,调试,最后完成功能。下面我们就开始我们的“小项目”。

项目名称:单独按键消抖

具体要求:消除按键按下以及抬起时所带来的抖动。

项目分析:

1. 按键电路

2. 抖动的产生

通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。

3. 按键抖动带来的危害

键抖动会引起一次按键被误读多次。为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。

4. 抖动的一些参数

抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。这是一个很重要的时间参数,在很多场合都要用到。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。

5. 解决办法

一是延时重采样;二是持续采样。从理论上来说,延时(如10ms)重采样的准确率肯定低于持续采样。笔者采用持续采样。

架构图如下:

  • key_n:带有抖动的低电平有效的按键输入(按键按下为低电平)
  • click_n:滤除抖动之后的低电平有效的按键波形

系统设计:

1. 工程的名称:key_filter

2. 状态转移图如下:

MASK_TIME : 持续采样的时间(笔者选择为10ms)

设计代码如下:

代码语言:javascript复制
/*
模块名称:key_filter
模块功能:消除按键按下以及抬起时所带来的抖动。
作者:郝旭帅
邮箱:746833924@qq.com
*/
module key_filter (clk, rst_n, key_n, click_n);

  input clk;
  input rst_n;
  input key_n;

  output reg click_n;

parameter MASK_TIME = 500_000;//驱动时钟为50M,10ms
//为500_000个周期

  reg [18:0] cnt;
  reg state;

  localparam s0 = 1'b0,
          s1 = 1'b1;

  always @ (posedge clk or negedge rst_n)
    begin
      if (!rst_n)
        begin
          click_n <= 1'b1;
          cnt <= 19'd0;
          state <= s0;
        end
      else
        begin
          case (state)
            s0 : begin
                if (key_n == 1'b0)
                  begin
                    if (cnt < MASK_TIME - 1)
                      begin
                        cnt <= cnt   1'b1;
                      end
                    else
                      begin
                        state <= s1;
                        cnt <= 19'd0;
                        click_n <= 1'b0;
                      end
                  end
                else
                  begin
                    click_n <= 1'b1;
                    cnt <= 19'd0;
                    state <= s0;
                  end
              end

            s1 : begin
                if (key_n == 1'b1)
                  begin
                    if (cnt < MASK_TIME - 1)
                      begin
                        cnt <= cnt   1'b1;
                      end
                    else
                      begin
                        click_n <= 1'b1;
                        state <= s0;
                        cnt <= 19'd0;
                      end
                  end
                else
                  begin
                    click_n <= 1'b0;
                    cnt <= 19'd0;
                    state <= s1;
                  end
              end

            default : state <= s0;

          endcase
        end
    end

endmodule

激励代码如下:

代码语言:javascript复制
/*
模块名称:key_filter_tb
模块功能:为key_filter模块提供激励信号
作者:郝旭帅
邮箱:746833924@qq.com
*/
`timescale 1ns/1ps

module key_filter_tb;

  reg clk;
  reg rst_n;
  reg key_n;

  wire click_n;

  initial begin
    clk = 1;
    key_n = 1;
    rst_n = 0;
    #200.1
    rst_n = 1;

    #200
    key_n = 0;
    #10
    key_n = 1;//模仿按键按下时的抖动
    #20
    key_n = 0;
    #80
    key_n = 1;

    #200
    key_n = 0;

    #400//按下的时间超过滤除抖动的时间

    key_n = 1;
    #10
    key_n = 0;//模仿按键抬起时的抖动
    #20
    key_n = 1;
    #80
    key_n = 0;

    key_n = 1;

    #800 $stop;
  end

  always #10 clk = ~clk;//本地晶振为50MHz

  key_filter 
    #(
.MASK_TIME(5)//仿真时,将滤除抖动的时间改成5个时钟周期
    )  
    key_filter_dut(
      .clk(clk), 
      .rst_n(rst_n), 
      .key_n(key_n), 
      .click_n(click_n)
    );

endmodule

解析:

模仿按键抖动时,抖动的时间(低电平或者高电平的持续时间)一定不要超过,否则将会被认为按键按下或者抬起。模仿按键真正按下或者真正抬起时,给予的时间一定要超过抖动(低电平或者高电平的持续时间)的时间。

仿真波形如下:

本次设计成功地将按键按下以及抬起时的抖动滤除。

如果本地晶振和笔者的设计不同,请自行更改设计,以保证设计的正确性。如果还是有不明白的读者可以发邮件到我邮箱或者加群询问。

END

0 人点赞