• 10_基于FPGA进行按键消抖


    10_基于FPGA进行按键消抖    

    实验原理

    计数器型消抖电路:

    计数器型消抖电路()

      计数器型消抖电路()是设置一个模值为(N+1)的控制计数器,clk在上升沿时,如果按键开关key_in='1',计数器加1key_in='0'时,计数器清零。当计数器值为2时,key_out输出才为1,其他值为0时。计数器值为N时处于保持状态。因此按键key_in持续时间大于Nclk时钟周期时,计数器输出一个单脉冲,否则没有脉冲输出。如果按键开关抖动产生的毛刺宽度小于N个时钟周期,因而毛刺作用不可能使计数器有输出,防抖动目的得以实现。clk的时钟周期与N的值可以根据按键抖动时间由设计者自行设定。

    下图为N3的波形仿真图,当按键持续时间大于3个时钟周期,计数器输出一个单脉冲,其宽度为1个时钟周期,小于3个时钟周期的窄脉冲用作模拟抖动干扰,从图1可以看出,抖动不能干扰正常的单脉冲输出。

    该方法的特点是能很好消除按键抖动产生的窄脉冲,还可以滤去干扰、噪音等其他尖峰波,但遇到脉宽大于NTclk时钟周期的干扰、噪音等时会有输出从而产生误操作,而对于按键操作要求按键时间必须大于NTclk时钟周期,否则按键操作也没有输出。

    计数器型消抖电路()

      计数器型消抖电路()是控制计数器工作一个循环周期(N+1个状态),且仅在计数器为0时输出为"1"。电路设计了连锁控制设施。在计数器处于状态0时,此时若有按键操作,则计数器进入状态1,同时输出单脉冲(其宽度等于时钟周期)。计数器处于其他状态,都没有单脉冲输出。计数器处于状态N时,控制en='0',导致计数器退出状态N,进入状态0。计数器能否保持状态0,取决于人工按键操作,若按键key_in='1',控制en='1'(计数器能正常工作)key_in='0',计数器状态保持。显见计数器处于状态0,人工不按键,则计数器保持状态0

    下图是N7的波形仿真图。在计数器状态为0时,key_in有按键操作,计数器开始连续计数直到计数器状态为0;计数器状态为1-7时,key_in任何操作对计数器工作无影响,计数器在状态为1时,输出一个单脉冲,脉冲宽度为1个时钟周期。

    该设计方法的特点是能很好消除按键抖动产生的连续脉冲,对按键时间没有要求,缺点是在计数器状态为0时,遇到干扰、噪音等时会有输出,从而产生误操作。

    状态机型消抖电路

    状态机型消抖电路采用有限状态机的设计方法来描述与实现,状态机有S0S1S2三种状态,在S0状态下key_out输出为低电平,并以clk时钟信号的频率采样按键输入信号,如果key_in='0',则保持在S0状态,并继续采样按键输入信号的状态,如果key_in='1',则转入S1状态;在S1状态下key_out输出仍为低电平,继续采样按键输入信号的状态,如果key_in='1',则转入S2状态,如果key_in='0'则转入S0状态;在S2状态下继续采样按键输入信号的状态,如果key_in='1',则保持在S2状态,key_out输出正脉冲,如果key_in='0',则转入S0状态,key_out输出低电平。

    下图为状态机型消抖电路波形仿真图

    硬件原理图

    实验代码

    计数器型消抖电路()程序:

    /********************************版权声明**************************************

    ** 大西瓜团队

    **

    **----------------------------文件信息--------------------------

    ** 文件名称: key.v

    ** 创建日期:

    ** 功能描述:按键控制led的亮灭

    ** 硬件平台:大西瓜第三代开发板,http://daxiguafpga.taobao.com

    ** 版权声明:本代码属个人知识产权,本代码仅供交流学习.

    **---------------------------修改文件的相关信息----------------

    ** 修改人:

    ** 修改日期:    

    ** 修改内容:

    *******************************************************************************/

    module key(clk,key,led);

    input clk,key;//按键与时钟输入

    output led;

     

    wire clk,key;

     

    reg led;

    reg [2:0] clk_counter;//时钟计数

    reg [14:0] div_counter;//分频计数

    reg key_out;

    reg clk_div;

    always @(posedge clk)

    begin

    if(div_counter==15'd25000)

    begin

    clk_div<=~clk_div;

    div_counter<=15'd0;

    end

    else

    div_counter<=div_counter+15'd1;

    end

     

    always @(posedge clk_div )

    begin

    if(key==1'b0)//判断按键是否按下

    begin

    if(clk_counter==3'b111)//计数到7

    begin

    clk_counter<=3'b000;

    key_out<=1'b1;

    end

    else

                 begin

                     clk_counter<=clk_counter+1'b1;

                 if(clk_counter==3'b110)//判断是否计到6

                     key_out<=1'b0;

                 else

                     key_out<=1'b1;

                 end

    end

    else

    clk_counter<=3'b000;

    end

    always @(negedge key_out)//对消抖后的按键信号进行判断

    begin

    if(!key_out)//判断按键是否按下

    begin

    led<=~led;//led灯状态反转

    end

    else

    led<=led;

    end

    endmodule

     

    状态机型消抖电路程序:

    /********************************版权声明**************************************

    ** 大西瓜团队

    **

    **----------------------------文件信息--------------------------

    ** 文件名称: key.v

    ** 创建日期:

    ** 功能描述:按键控制led的亮灭

    ** 硬件平台:大西瓜第三代开发板,http://daxiguafpga.taobao.com

    ** 版权声明:本代码属个人知识产权,本代码仅供交流学习.

    **---------------------------修改文件的相关信息----------------

    ** 修改人:

    ** 修改日期:    

    ** 修改内容:

    *******************************************************************************/

    module key(clk,led,key);

    input clk,key;

    output [7:0] led;

     

    wire clk;

    wire key;

     

    reg [7:0] led_temp;

    reg key_out;

    parameter s0=2'b00,s1=2'b01,s2=2'b10,s3=2'b11;

    reg [1:0] state;

     

    always @(posedge clk)

    begin

    case (state)

    s0:

    begin

    key_out<=1'b1;

         if(key==1'b0)

             state<=s1;

         else

         state<=s0;

         end

         s1:

         begin

         if(key==1'b0)

             state<=s2;

         else

         state<=s0;

         end

         s2:

         begin

         if(key==1'b0)

             state<=s3;

         else

         state<=s0;

         end

         s3:

         begin

         if(key==1'b0)

         begin

             key_out<=1'b0;

             state<=s3;

             end

            else

             begin

             key_out<=1'b1;

             state<=s0;

         end

         end

         default:

         state<=s0;

    endcase

    end

     

    always @(negedge key_out)

    begin

    if(!key_out)//判断按键是否按下

    begin

    if(led_temp==8'b1111_1111)

    led_temp<=8'b0;

    else

    led_temp<=led_temp+1'b1;

    end

    end

    assign led=~led_temp;

    endmodule

    实验操作

    实验效果

     

     

     

    大西瓜FPGA-->https://daxiguafpga.taobao.com

    配套开发板:https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-24211932856.3.489d7241aCjspB&id=633897209972

    博客资料、代码、图片、文字等属大西瓜FPGA所有,切勿用于商业! 若引用资料、代码、图片、文字等等请注明出处,谢谢!

       

    每日推送不同科技解读,原创深耕解读当下科技,敬请关注微信公众号"科乎"。

  • 相关阅读:
    最小顶点覆盖,最大独立集,最小边覆盖
    Security Badges
    异常
    List和Set
    数据结构
    Collection集合
    Excel序号递增
    VM虚拟机桥接模式无法联网解决办法
    mybatis-Plus方法指定更新的字段
    maven项目 导出相关依赖包到指定文件夹
  • 原文地址:https://www.cnblogs.com/logic3/p/15915902.html
Copyright © 2020-2023  润新知