FPGA实现按键消抖(任意位宽)

文章详细介绍了按键的工作原理,特别是当按键按下时电路的通断变化。针对按键的抖动问题,提出了两种消抖解决方案:延迟采样和状态机实现。在延迟采样中,通过检测下降沿并计时20ms来确保稳定的按键信号。状态机实现则通过定义不同状态来跟踪按键的按下和释放过程,同样达到消抖效果。这两种方法都可应用于任意位宽的按键信号处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、按键原理

硬件原理图

在这里插入图片描述

  • 当按键KEY1按下时,D3V3(也就是电源)通过电阻R(原理图上折线的那一段)然后再通过按键KEY1最终进入GND形成一条通路,那么这条线路的全部电压都加到了R这个电阻上,KEY1(最左边四个IO口)这个引脚就是个低电平。
  • 当松开按键后,线路断开,就不会有电流通过,那么KEY1和D3V3就应该是等电位,是一个高电平。我们就可以通过KEY1这个IO口的高低电平来判断是否有按键按下。

二、按键消抖

2.1 原理

  按键抖动通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。当按下一次按键,可能在A点检测到一次低电平,在B点检测到一次高电平,在C点又检测到一次低电平。同时抖动是随机,不可测的。那么按下一次按键,抖动可能会误以为按下多次按键。
  所以我们在使用按键时往往需要消抖,以确保按键被按下一次只检测到一次低电平
在这里插入图片描述

2.2 解决方法

延迟采样
在这里插入图片描述

2.2.1 设计思路

  通常我们认为按键的抖动时间存在于20ms之间,因此可以设计在第一次检测到有下降沿时开始计时,到计满20ms后,我们认为此时的按键信号保持稳定,则输出一个脉冲信号表示按键确实按下。
  首先需要一个模块来检测按键是否抖动,如果抖动,→ 给计时模块一个标志位开始计时,记满20ms,→ 再给输出消抖后按键信号模块一个标志位进行采样。

2.2.2 时序图分析

在这里插入图片描述

  • clock:我们的整个程序都是在时钟的控制下运行的,所有的always模块都对时钟的上升沿敏感,本人使用的开发板时钟频率是50MHz,也就是一秒震动50_000_000次,一个周期就是20ns
  • key_in:这是按键输入信号,低电平有效
  • key_r0:同步打拍后的信号,为了滤除掉小于一个周期的抖动,对key_in推迟一个周期进行同步
  • key_r1 :这个信号是把同步信号再延时一个周期,主要是为了保存key_r0上一个周期的值(打一拍),来判断是否出现下降沿
  • key_r2:与key_r1同理,再延时一个时钟周期
  • nedge:检测key_r0是否出现下降沿,若出现,则将标志位flag设为1,也是计时器开启的条件
  • add_cnt:计时器开启条件,用flag表示
  • end_cnt:计时器结束条件,记满20ms,也是采样模块的开启条件
  • key_down:计时器记满,则开始采样,key_down拉高一个周期(脉冲信号),代表按键按下
2.2.3 代码设计

key_debounce.v

/**************************************功能介绍***********************************
Date	: 2023年7月27日11:07:19
Author	: Ruminating.
Version	: 1.1
Description: 按键消抖模块(任意位宽实现)
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module key_debounce #(parameter WIDTH = 4,//WIDTH为按键位宽(以4位宽为例)
                                TIME_20MS = 20'd1000_000//20ms计数器
)( 
    input	wire    		        clk		,//时钟信号
    input	wire    		        rst_n	,//复位信号
    input	wire    [WIDTH-1:0]		key_in  ,//输入按键信号
    output  wire    [WIDTH-1:0]     key_out  //输出脉冲信号
);								 
//---------<参数定义>--------------------------------------------------------- 
    // parameter TIME_20MS = 1000_000;//20ms

//---------<内部信号定义>-----------------------------------------------------
    reg     [WIDTH-1:0]     key_down;//输出信号寄存器
    reg     [WIDTH-1:0]     key_r0  ;//同步打拍
    reg     [WIDTH-1:0]     key_r1  ;//打一拍
    reg     [WIDTH-1:0]     key_r2  ;//打两拍
    wire    [WIDTH-1:0]     n_edge  ;//下降沿
    reg                     flag    ;//计数器计数的标志信号(按键按下抖动标志)

    reg		[19:0]	        cnt_20ms	;//20ms计数器
    wire				    add_cnt_20ms;//开始计数条件
    wire				    end_cnt_20ms;//结束计数条件

//****************************************************************
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值