0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何设计一个实用的按键模块

FPGA之家 来源:FPGA之家 作者:FPGA之家 2022-09-05 09:19 次阅读

一.简介

这是FPGA之旅的第二个设计实例了,按键在项目中的作用是非常大的,使用的很频繁,本例将带大家设计一个实用的按键模块。

二. 按键电路

按键为输入设备,通过电路图可以知道,当按键按下的时候,FPGA会检测到低电平,按键没有按下的时候,FPGA检测到的是高电平。

e32b1824-2cad-11ed-ba43-dac502259ad0.png

三. Verilog代码编写

直接来一段最简单的按键检测的代码编写,都不用仿真

按键按下,LED灯状态取反。

module KEY(  input    clk,    input    rst_n,    input    key,    output  reg  led);    always@(posedge clk or negedge rst_n)    begin        if(rst_n == 1'b0)             led <= 1'b0;        else if(key == 1'b0)            led <= ~led;        else            led <= led;    endendmodule 

当按键按下后,LED的状态取反,这个在仿真的时候是可以看到变化的,但是实际上板测试的话,是没有效果的,因为clk的时钟周期一般为20ns,每次按键按下的持续时间可以达到ms以上,所以LED会多次取反,所以这么简单粗暴是不可以的,需要我们做一些额外处理。此外在按键按下的瞬间,电平会出现不稳定的情况,也需要进行处理。解决这些问题,正是这个例程的重点。

四. 解决方案设计

按键按下的时候,一共有两个问题

电平不稳定

短时间内重复检测

第一个问题可以通过按键消抖来解决,第二个问题,可以在按键消抖的基础上,增加一些判断来解决,于是就有了以下三种模式

模式一,按下生效,释放,算一次

模式二,按下,释放生效,算一次

模式三,按下,一段时间算一次

这里通过状态机的方式来实现,第一步就是要分析一共有几个状态。

空闲态:按键没有按下时,所处的状态。

消抖态: 按键按下后,进入消抖态,在此期间,如果按键释放了的话,回到空闲态,否则进入延时态。

延时态:延时,直到按键释放。

释放态:按键释放,回归到空闲态。

模式一,可以在消抖态完成后,生效。

模式二,可以在释放态,生效。

模式三,可以在延时态,生效。

完美,这不就全部都解决了嘛! 代码如下。

//按键消抖module btn_dis_shake(        input      clk,  input      rst_n,    input      ikey,        //按键输入outputokey//按键输出);//模式//0   按下生效,抬起,算一次//1   按下抬起,算一次//2  按下后,一段时间算一次parameter      mode = 2;
localparam      S_IDLE    =    'd0;localparam      S_DIS_SHAKE =       'd1;localparam      S_DEALY    =    'd2;localparam      S_UP    =    'd3;
localparam      DIS_SHAKE  =  'd6000;    //消抖延时localparam      DELAY    =  'd50000;  //模式2中,一段时间
reg[3:0] state  ,  next_state;
wire neg_key,pos_key;  //按键下降沿上升沿reg   key0,key1;      //按键状态储存
reg[30:0]  delay_cnt;
assign    neg_key =  key1 & (~key0);    //判断按键信号的下降沿assignpos_key=(~key1)&key0;//判断按键信号的上升沿//根据模式来判断按键输出assignokey=(mode==0&&state==S_DIS_SHAKE&&delay_cnt==DIS_SHAKE)?1'b1:(mode==1&&state==S_UP)?1'b1:(mode==2&&state==S_DEALY&&delay_cnt==DELAY)?1'b1:1'b0;always@(posedge clk or negedge rst_n)begin  if(rst_n  == 1'b0)  begin      key0 <= 1'b1;      key1 <= 1'b1;  end  else  begin    key0 <= ikey;    key1 <= key0;  endendalways@(posedge clk or negedge rst_n)begin  if(rst_n == 1'b0)    state <= S_IDLE;  else    state <= next_state;end
always@(*)begin  case(state)    S_IDLE:      if(neg_key  ==  1'b1)        next_state <= S_DIS_SHAKE;      else        next_state <= S_IDLE;    S_DIS_SHAKE:      //按下消抖        if(delay_cnt == DIS_SHAKE)          next_state <= S_DEALY;        else if(pos_key == 1'b1)          next_state <= S_IDLE;        else          next_state <= S_DIS_SHAKE;    S_DEALY:      //延时      if(delay_cnt == DELAY  && pos_key == 1'b1)        next_state <= S_UP;      else if( pos_key == 1'b1)        next_state <= S_UP;      else        next_state <= S_DEALY;    S_UP:      next_state <= S_IDLE;    default:  next_state <= S_IDLE;  endcaseend
//延时计数always@(posedge clk or negedge rst_n)begin  if(rst_n == 1'b0)    delay_cnt <= 'd0;  else if(state != next_state)    delay_cnt  <= 'd0;  else if(state == S_DIS_SHAKE)    delay_cnt <= delay_cnt + 1'b1;  else if(state == S_DEALY && delay_cnt == DELAY)    delay_cnt <= 'd0;  else if(state == S_DEALY)    delay_cnt <= delay_cnt + 1'b1;  else    delay_cnt <= 'd0;end
endmodule 

代码是写完了,对不对呢 ? 上仿真!!!仿真的时候别忘记了将DIS_SHAKE这个参数调小一点了,可以设置为2就可以了,否则,你可以试试哦,就只对模式一进行仿真,其他的模式,也可以自行尝试喔!

`timescale  1ns/1psmodule testbeach();
    reg clk;    reg rst_n;    reg ikey;    wire okey;      always#50clk<= ~clk;     initial begin       clk = 1'b0;       rst_n = 1'b1;       ikey = 1'b1;                #100        rst_n = 1'b0;        #100        rst_n = 1'b1;                ikey = 1'b0;  //按下        #400        ikey = 1'b1;  //释放        #200        ikey = 1'b0;  //按下        #600        ikey = 1'b1;  //释放    end
btn_dis_shake #(.mode(0))btn_dis_shakeHP(          .clk    (clk),    .rst_n  (rst_n),      .ikey    (ikey),        //按键输入    .okey  (okey)      //按键输出);    endmodule

当当当当!!!完美对应起来,测试通过!

e335a618-2cad-11ed-ba43-dac502259ad0.png 

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1629

    文章

    21754

    浏览量

    604235
  • 模块
    +关注

    关注

    7

    文章

    2718

    浏览量

    47560
  • led灯
    +关注

    关注

    22

    文章

    1592

    浏览量

    108108
  • 代码
    +关注

    关注

    30

    文章

    4801

    浏览量

    68735

原文标题:FPGA实现按键模块

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何设计按键信号进行计数的计数器?

    detect_module模块用于检测按键信号的下降沿,当检测到下降沿后,输出时钟周期的高电平。
    的头像 发表于 10-10 14:27 1780次阅读
    如何设计<b class='flag-5'>一</b><b class='flag-5'>个</b>对<b class='flag-5'>按键</b>信号进行计数的计数器?

    按键控制另一个按键

    大家好,我想问问题,我想用按键和另一个按键
    发表于 03-04 00:58

    介绍事件驱动型按键驱动模块MultiButton

    MultiButton MultiButton,小巧简单易用的事件驱动型按键驱动模块,作者 0x1abin,目前收获 222 star
    发表于 01-10 07:28

    如何制作单片机独立按键扫描的模块

    如何制作单片机独立按键扫描的模块
    发表于 02-17 06:38

    【BPI-Pico-RP2040 开发板】+GPIO口的使用

    观察效果,这里为引脚13接上一个外挂的LED模块,并通过导线将引脚2接地来模拟按键按下的效果。经程序的下载,其运行效果如图2所示,若断开引脚2的连线,则LED灯熄灭,说明程序设计正确。图2 点亮LED
    发表于 03-20 11:00

    标记的用法,用按键控制1LED灯的亮灭,按键去抖

    标记的用法,用按键控制1LED灯的亮灭,按键去抖 这课,我们学习怎么用
    发表于 08-09 10:39 2.4w次阅读
    标记的用法,用<b class='flag-5'>一</b><b class='flag-5'>个</b><b class='flag-5'>按键</b>控制1<b class='flag-5'>个</b>LED灯的亮灭,<b class='flag-5'>按键</b>去抖

    使用51单片机和nRF24L01无线模块用4不同的按键控制点亮4不同的灯

    哈哈,穷吊死,自己做的超简单的板还没有电源提供,只得借助我的大开发板啦。其实这2模块
    发表于 06-06 17:51 5次下载
    使用51单片机和nRF24L01无线<b class='flag-5'>模块</b>用4<b class='flag-5'>个</b>不同的<b class='flag-5'>按键</b>控制点亮4<b class='flag-5'>个</b>不同的灯

    微雪电子8独立按键模块按钮简介

    8独立按键模块 8位按键 可用作输入 或进行I/O测试 提供测试程序(AVR、STM8、STM32) 型号 8 Push Buttons
    的头像 发表于 12-30 09:13 2470次阅读
    微雪电子8<b class='flag-5'>个</b>独立<b class='flag-5'>按键</b><b class='flag-5'>模块</b>按钮简介

    微雪电子5 IO 按键模块 小键盘介绍

    5 IO 按键模块 - 10按键 1摇杆 10按键
    的头像 发表于 12-30 09:12 1316次阅读
    微雪电子5 IO <b class='flag-5'>按键</b><b class='flag-5'>模块</b> 小键盘介绍

    微雪电子AD按键模块简介

    AD按键模块 16按键 仅占用1AD口 检测接口(被接入方需具备AD检测功能)提供测试程序(STM32) 型号 AD Key
    的头像 发表于 12-30 09:28 1875次阅读
    微雪电子AD<b class='flag-5'>按键</b><b class='flag-5'>模块</b>简介

    微雪电子电容触摸 按键模块简介

    电容按键模块 I2C 或 I/O接口 8按键 1滑条 取代传统按钮 电容式触摸按键
    的头像 发表于 12-30 09:36 2285次阅读
    微雪电子电容触摸 <b class='flag-5'>按键</b><b class='flag-5'>模块</b>简介

    dfrobotADkey 按键模块介绍

    ADKey 键盘模块让你使用1路模拟口即可读取5按键的状态,为Arduino节约IO口。
    的头像 发表于 11-29 16:40 3475次阅读
    dfrobotADkey <b class='flag-5'>按键</b><b class='flag-5'>模块</b>介绍

    单片机独立按键模块(含短按,长按,连发功能)

    最近看了很多按键扫描的文章,发现各有长处,后来自己花了点时间做了单片机独立按键扫描的模块
    发表于 12-22 19:46 23次下载
    单片机独立<b class='flag-5'>按键</b><b class='flag-5'>模块</b>(含短按,长按,连发功能)

    stm32单片机如何实现按键切换两程序?

    ,非常实用。下面,我们将详细介绍如何在STM32单片机上实现按键切换两程序。 、 STM32单片机
    的头像 发表于 09-14 14:22 6197次阅读

    应用于单片机的按键处理模块

    应用于单片机的按键处理模块
    的头像 发表于 10-24 16:28 751次阅读
    <b class='flag-5'>一</b><b class='flag-5'>个</b>应用于单片机的<b class='flag-5'>按键</b>处理<b class='flag-5'>模块</b>!