• 按键消抖(整理)


    http://blog.csdn.net/zc20060102/article/details/8194789

     机械按键在按下和弹起时会出现短时间抖动,抖动时间一般持续为15ms。

       在按键吃紧的设计中,往往会进行按键的复用。常用的方法是根据键按下时间的长与短进行判断。因此按键复用经常是利用按键消抖后的下降沿(如果键按下是高电位的话)。

      假设按键为key_in。

       一、按键消抖的步骤:

       1.设定两个采样寄存器key_in_Sam(1 downto 0)对按键key_in进行监控采样

       2.判断key_in_Sam的值是否一致,不一致意味着可能有键的动作,将事件寄存到in_event_latch(1 downto 0)的低位,之后向高位移位以阻塞后续15ms内的抖动,同时启动15ms延时计数器,15ms之后清除in_event_latch寄存器,为下一次消抖做准备

       3.15ms延时完毕,对key_in进行采样保存到key_in_latch(1 downto 0)的低位,此值是消抖后的键值,而前一次采样的消抖键值向高位移位

       4.设定两个采样寄存器in_latch_Sam(1 downto 0),in_latch_Sam低位寄存刚消抖后的键值key_in_latch(0),之后向高位移动,根据in_latch_Sam的组合就可以判断出按键是上升沿还是下降沿

       5.如果是按键上升沿,则启动0.3S延时计数器(根据实际情况设定)

       6.按键释放后,电路重复执行1-4步骤

       7.0.3S延时计数器到达0.15S时,短按指示short_press_latch置1,到达0.3S时,长按指示long_press_latch置1

       8.如果是按键下降沿,则根据short_press_latch和long_press_latch的值,输出应该是短按还是长按,同时将short_press_latch和long_press_latch清除

       9.在延迟按键下降沿将短按或长按清除,这样信号只有一个时钟周期有效 

    http://home.eeworld.com.cn/my/space.php?uid=334757&do=blog&id=46566

    module sw(clk,rst_n,sw_n,led);
    input clk,rst_n,sw_n;
    output [7:0]led;
    reg key_rst;
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
    key_rst<=1'b1;
    else 
    key_rst<=sw_n;
    reg key_rst_r;
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
    key_rst_r<=1'b1;
    else 
    key_rst_r<=key_rst;
    wire key_an;
    assign key_an=key_rst_r&(~key_rst);
    reg [19:0]counter;
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
    counter<=20'd0;
    else if(key_an)
    counter<=20'd0;
    else 
    counter<=counter+1'b1;
    reg low_sw;
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
    low_sw<=1'b1;
    else if(counter==20'hfffff)
    low_sw<=sw_n;
    reg low_sw_r;
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
    low_sw_r<=1'b1;
    else
    low_sw_r<=low_sw;
    wire led_ctrl;
    assign led_ctrl=low_sw_r&(~low_sw);
    reg d1;
    always@(posedge clk or negedge rst_n)
    if(!rst_n)
    begin
    d1<=1'b0;
    end
    else 
    begin
    if(led_ctrl)
    d1=~d1;
    end
    assign led[0]=d1?1'b1:1'b0;
    assign led[1]=d1?1'b1:1'b0;
    assign led[2]=d1?1'b1:1'b0;
    assign led[3]=d1?1'b1:1'b0;
    assign led[4]=d1?1'b1:1'b0;
    assign led[5]=d1?1'b1:1'b0;
    assign led[6]=d1?1'b1:1'b0;
    assign led[7]=d1?1'b1:1'b0;
    endmodule

    http://zhidao.baidu.com/link?url=xmA0RUdYXuLxVa9qoNw153GGlXIep8gs67nvFwgiE3WEw-VZ6tOWAuowDB5owvDm9zUcs8vrGFutQkHw-iCaxa

    //按键消抖处理部分
    assign key_done = (dout1 | dout2 | dout3); //按键消抖输出
    always @(posedge count[17])
    begin
    dout1 <= key_in;
    dout2 <= dout1;
    dout3 <= dout2;
    end
    always @(negedge key_done[0])
    begin
    keyen = ~keyen; //将琴键开关转换为乒乓开关
    end

    还有下面这段程序
    //按键检测并消抖
    always @(posedge divclk)
    begin
    if(!s3) begin
    case(count3)
    0: count3 <= count3 + 1'b1;
    1: s3down <= 1'b1;
    endcase
    end
    else begin
    count3 <= 1'b0;
    s3down <= 1'b0;
    end
    end

    消抖分为硬件消抖和软件消抖:硬件消抖是使用积分器或是低通滤波器等手段滤除按键抖动,而软件消抖是通过编程来解决。消抖是为了避免在按键按下或是抬起时电平剧烈抖动带来的影响。一般来说,软件消抖的方法是不断检测按键值,直到按键值稳定。实现方法:假设未按键时输入1,按键后输入为0,抖动时不定。可以做以下检测:检测到按键输入为0之后,延时20ms,再次检测,如果按键还为0,那么就认为有按键输入。延时的20ms恰好避开了抖动期。

    程序中所用的方法是不断检测按键值。每当Count[17]上升沿到来,就进行检测输入信号。其中dout1,dout2,dout3分别为当前、上个Count[17]上升沿、上上个Count[17]上升沿输入数值。正常情况下为1,假如连续三次为0,三个信号相与,使得key_done信号为0,出现下降沿,这样就认为是有按键。

    另外,你问为什么是count[17],由于你本身没写清楚count[17]的定义,所以没有确定答案。不过据猜测,count[17]只是一个延时信号而已。很有可能count是一个18位的计数器,每一个时钟周期计数一次,那么他计数262143次为一个周期,出现一次上升沿。如果按照26M时钟计算的话,count[17]出现两个上升沿之间间隔约为10ms,连续检测3次就是在0ms,10ms,20ms处都检测到0,才算是有按键输入。

    如果不明白可继续追问。

     

    http://bbs.21ic.com/icview-383820-1-1.html

    reg key_reg1,key_reg2,key_out;
    always @( posedge clk)//CLK 50M
        begin
        count2<=count2+1;
        if(count2==500000)
        begin
            key_reg1<=key1; 
            count2<=0;
        end
        key_reg2<=key_reg1; 
        key_out<=key_reg2&(!key_reg1); 
    end

    意思为定义2个寄存器,存储按键在2个周期内的数据,计数器是决定按键的采样频率,如果我们把按键的采样频率调高,那么 按键就会有2次相应,我试过吧计数器去掉,但是一直都是双数增加,很让我费解,在苦思冥想之际,悟出了可以通过延时,吧后面松手的一个电平跳变滤掉,哈哈!!顿时给大家分享下最简单的防抖动,
    key1 是低电平按下,当按下的时候,  key_out输出的是一个高电平。

    ------------------------------------------------------------------------------------------------

    reg[2:0] syn_key1_reg;
    always@(posedge clk)// 50M
    begin
       syn_key1_reg <= {syn_key1_reg[1:0],key1};
    end

    always@(posedge clk)
    begin
       if(rst)
          begin
             cnt2 <= 0;
          end
       else
          begin
             if(syn_key1_reg[2:1] = 2'b10)
               begin
                  cnt2 <= 50000;
               end
             else
               begin
                 cnt2 <= cnt2 - (|cnt2); 
               end
          end
    end
    always@(cnt2,syn_key1_reg)
    begin
       if((cnt2 == 1) && (syn_key1_reg[1] == 1'b0))
         begin
            key_out = 1'b1;
         end
       else
         begin 
            key_out = 1'b0;
         end
        
    end

  • 相关阅读:
    WebForm跨页面传值---内置对象
    后台获得集合,变成json字符串,放到EL表达式,js进行获取遍历
    Delphi 编写DLL动态链接库文件的知识和样例(有详细步骤,很清楚)
    DELPHI美化界面(2009开始TPanel增加了ParentBackGround)
    在Delphi中创建线程,请一定使用BeginThread()代替CreateThread()创建线程!(更好的管理异常)
    delphi中最小化其他程序及所有程序最小化(使用 shell.minimizeAll 和自己寻找窗口这两种办法)
    电脑睡眠状态(ACPI规范定义了七个状态,使用powercfg -a进行查看)
    javascript
    Master-Worker模式
    程序员的基础和解决问题的思维
  • 原文地址:https://www.cnblogs.com/habyjingloveDY/p/3301217.html
Copyright © 2020-2023  润新知