FPGA培训专家 V3学院带你学习 按键消抖 和 边缘检测

FPGA培训专家 V3学院  

  一般情况下,我们从按下按键到松开基本需要大于几十毫秒的时间,系统时钟的周期处于纳秒级,因此我们按下一次按键会被大于十万个时钟的上升沿采集到,然而我们希望的是按下一次按键只被一次上升沿采集到,不然会被认为按了多次按键,所以我们需要对我们的按键进行处理。假设按键在没被按下时为高电平,被按下时处于低电平,如图1所示的波形图。

图1 按键波形图

由图1 分析可知在key被按下时有且仅有一个key的上升沿和一个key的下降沿,我们可以通过检测key的上升沿或者下降沿来确定按键被按下一次,这就涉及到边缘检测,具体方法如图2所示,可以用clk的上升沿将key延时一个周期产生key_reg,通过key和key_reg的值同时判断key的上升沿或下降沿。由图2可知,当用clk的上升沿检测到key等于1的同时key_reg等于0,此时则为key的上升沿,若key等于0的同时key_reg等于1则为key的下降沿。

图2 边缘检测

由图2可知根据key的上升沿或下降沿可确定按了一次键,然而事实却不允许我们这么做。图3给出了一个按键的模型,当不按下按键s时,a、b两点是断开的,按下按键s时线路才接通,然而当按下按键时,会存在物理上的抖动现象,此时a、b两点会在断开和接通之间反复的一段时间,就会出现图4所示的抖动、稳定的波形。

图3 按键模型

图4 按键抖动

图4所示前抖动为按下时产生的抖动,后抖动为按键松开时造成的抖动,前、后抖动持续时间一般均为5~10ms,在有抖动的情况下,key会被clk上升沿采集到很多的上升沿和下降沿,因此用key的上升沿和下降沿判断按键一次就不成立了,我们需要寻找新的方法。

我们知道按键被按下时key值为低电平(0),在抖动期间key既有高电平也有低电平,我们可以使用clk的上升沿计算key连续为低电平的时间,期间当检测到key为高电平时,则从头开始计数,当计数超过5~10ms时,我们可以认定按键有被按下的时候,此时我们可以产生一个clk周期为高电平的标志,当该标志位高电平认为有一次按键即可,具体波形如图5所示。

图5 按键消抖波形图

此处我们认为key值有连续性的5ms时为按键被按下,时钟周期为50MHz,即20ns,可以算出5ms占250000个clk周期,也就是说cnt从0计数到249999为5ms,当cnt等于249999时可以将po_key_flag拉高一个周期,由于按键时间长短无法确定,因此cnt有可能多次达到249999这个值,会造成po_key_flag多次被拉高,这样有会出现按下一次键被当成按下多次,所以在图5中出现了cnt_flag变量,在遇到cnt等于249999时,cnt_flag就会被置高,直到遇到key等于高电平时才会被拉低,这样我们就可以将第一个cnt等于249999和后面的区分开,那么我们也可以用cnt和cnt_flag共同控制在一次按键中,保证po_key_flag有且仅有一个时钟周期的高电平。根据波形图可得到如下所示的代码。

代码示例:

1  //按键消抖模块

module       key_debounce(

input        wire    sclk            ,//系统时钟

input        wire    rst_n           ,

input        wire    key             ,//按键输入

6

output       reg     po_key_flag     //消抖后产生的标志

);

9

10 reg[17:0]    cnt             ;//消抖计数器

11

12 reg          cnt_flag        ;//计数器标志

13

14 //计数到5ms的最终值

15 parameter    CNT_END =       500000-1;

16

17 //产生消抖计数器

18 always@(posedge      sclk    or      negedge rst_n)

19      if(rst_n==1‘b0)

20              cnt     <=      18‘b0;

21      else if(key==1‘b0)

22              cnt     <=      cnt+1‘b1;

23      else

24              cnt     <=      18‘b0;

25

26 //产生消抖计数器的标志信号

27 always@(posedge      sclk    or      negedge rst_n)

28      if(rst_n==1‘b0)

29              cnt_flag        <=      1‘b0;

30      else if(cnt==CNT_END)

31              cnt_flag        <=      1‘b1;

32      else if(key==1‘b1)

33              cnt_flag        <=      1‘b0;

34

35 //产生消抖后的po_key_flag

36 always@(posedge      sclk    or      negedge rst_n)

37      if(rst_n==1‘b0)

38              po_key_flag     <=      1‘b0;

39      else if(cnt==CNT_END&&cnt_flag==1‘b0)

40              po_key_flag     <=      1‘b1;

41      else

42              po_key_flag     <=      1‘b0;

43

44 endmodule

代码解析:

① 第18行的always块实现了一个计数器,当key键按下(值为0)的时候开始计数,当检测到按键松开(值为1)的时候计数器归零,这样在抖动时候,该计数器会出现计数、归零循环的一个过程,直到key值一直为0,即按键持续被按下并且抖动过程结束,计数器才会持续计数到5ms;

② 第27行的always块产生一个标志,当检测到cnt第一次等于5ms的时候,该标志则被置为高电平,这样就可以将cnt第一次等于5ms和之后的cnt等于5ms区分开,直到key松开(值为1)时,该标志才被置为低电平;

③ 第30行的always块实现产生整个按键过程中的一个时钟周期高电平的标志,当cnt计数到5ms时,为了确保只有一次的po_key_flag有效,因此此处条件中不仅需要cnt==5ms,而且需要cnt_flag==0。

来自于v3学院  www.v3edu.org

时间: 2024-10-02 11:09:11

FPGA培训专家 V3学院带你学习 按键消抖 和 边缘检测的相关文章

FPGA培训专家 V3学院带你学习 使用modesim仿真工具

首先我们建立LED灯的功能模块和  LED灯仿真模块: 打开modesim,新建工程, 选择工程保存路径, 添加需要仿真的功能文件和仿真文件 进行编译,检查错误 没有错误,添加仿真波形 进行仿真

FPGA培训专家 V3学院 FPGA专家 带你学习Verilog语言top_down书写技巧

此文章为原创出自 V3学院 www.v3edu.org,FPGA培训专家 为了提高我们代码的复用率,我们可以将不同的功能的代码分模块书写,然后在顶层连线即可.我们举一个简单的例子,如下程序,我们实现的是LED流水. 我们在led模块中先将系统时钟分频为1HZ的时钟,然后用分频后的时钟控制LED灯的流水,但我的分频和LED灯流水完全不是相同的工程,只是把分频后的时钟作为LED灯的控制时钟.这样我们会发现如果我再次用到流水灯的模块的话需要修改很多地方,那么为了让我们的模块复用率更高.更容易复用,我们

FPGA培训专家 v3学院 教你FPGA-赋值语句

此文章为v3学院原创 www.v3edu.org 开发过程中,我们用的最多的恐怕就是赋值语句了,我们常用的赋值方式有两种:阻塞赋值和非阻塞赋值.我刚开始学的时候就被这两种赋值方式搞晕了,当时脑子里面有几个问题总是一团乱麻-什么是阻塞赋值?什么是非阻塞赋值?什么时候用阻塞赋值?什么时候用非阻塞赋值?这两种赋值方式到底有哪些不同?什么时候两种赋值方式结合起来用? 当时由于好的教材比较少,因此我被这些简单的问题困扰了很久,今天通过本节课程的学习,我们将通过一些实际的例子来说明这些问题. 一非阻塞赋值语

V3学院带你学习-缩短汉明码Hamming(12,8)的FPGA实现

此文章为原创出自 V3学院 www.v3edu.org,FPGA培训专家汉明码是一种实现简单并且可以检测和纠正错误的编码, 汉明码是在原编码的基础上附加一部分数据比特,使其满足纠错码的条件.它属于线性分组码,由于线性码的编码和译码容易实现,至今仍是应用最广泛的一类码.V3学院FPGA Verilog 汉明码实现,Hamming(12,8)表示数据位长K=8,编码后码字长N=12,校验位长R=12-8=4,最小汉明距离是H=3(观察其生成矩阵,不同行向量间最少不同比特的数量),纠错能力为(H-1)

V3学院带你学习-缩短汉明码Hamming(12,8)的FPGA实现-第二部分

此文章为原创出自 V3学院 www.v3edu.org,FPGA培训专家 测试激励模块 tb_hamming_12_8.V //功能描述:给被测模块提供时钟激励,并统计解码后数据的正确性 `timescale 1ns/1ns module tb_hamming_12_8; reg sclk; wire [11:0] ham_o; wire ham_ov; wire [11:0] deham_o; wire deham_ov; reg [31:0] err_cnt; reg [23:0] buff

V3学院带你学习-如何让chipscope里面的信号不被优化掉

此文章为原创出自 V3学院 www.v3edu.org,FPGA培训专家 在用ise对FPGA开发的时候,从仿真工具仿真的结果来看,功能都是能实现的,但是实际下载之后却不能实现具体的功能.这时我们一般会用ise自带的chipscope即在线逻辑分析仪对信号进行采样,查看硬件中具体的状态.但是很多时候,这个软件也有令我们失望的时候,因为ise里面的综合器的功能比较强大,把工程里面的一些信号给优化掉了,chipscope里面踩不到这些信号,而我们恰好是需要查看这些信号的.这时就可以用下面调取ip核的

v3学院带你学习《驱动蜂鸣器演奏歌曲》

此文章为原创出自 V3学院 www.v3edu.org,FPGA培训专家 一.实验背景(一)蜂鸣器的介绍1.蜂鸣器的作用蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机.打印机.复印机.报警器.电子玩具.汽车电子设备.电话机.定时器等电子产品中作发声器件.2.蜂鸣器的分类蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型.3.蜂鸣器的电路图形符号蜂鸣器在电路中用字母"H"或"HA"(旧标准用"FM"."LB"

v3学院带你学习数码管

在很多初级开发板上面,数码管属于标配的外设,其基本的单元是发光二极管,一般是由八个发光二极管组成"8"字形的结构,如图1所示. 图1 数码管二极管结构 八个发光二极管中的一端会连接一起,若是阳极(正极)连到一起称为数码管共阳极,阴极(负极)连到一起称为共阴极,没有连接到一起的一端分别连接到FPGA芯片的八个引脚上.当我们想在数码管上显示所需的数字时,只需要导通对应的发光二极管即可. 一般来说在一个开发板上面可能会有多个数码管,每一个数码管需要占用FPGA芯片的八个引脚,如此FPGA芯片

v3学院带你学习-时序逻辑中时钟上升沿对齐数据变化时的处理技巧的FPGA实现

此文章为原创出自 V3学院 www.v3edu.org 时序逻辑中,数据都是在时钟的上升沿或者下降沿时刻进行采样的,以上升沿为例,时钟采数据时应该采的是时钟上升沿左边变量的值,运算的结果体现在时钟上升沿的右边,但是,在用modelsim等一些仿真工具进行仿真的时候,如果时钟上升沿刚好和数据变化对齐,就会出现与上述理论不一致的原因,如下仿真波形图: 上图中的例子是用时钟上升沿控制变量a和b按位或运算并且把结果赋值给c的小实验,根据前面说的理论,黄线位置处,时钟上升沿采的变量a和b的值都为0,进行或