zoukankan      html  css  js  c++  java
  • 基于verilog——长短单击双击按键识别(改版)

      看着之前编写的,感觉有点问题。首先状态机格式就有点不对头,改了下,再加上了单击和双击的辨别。感觉这次好多了。

      不过还没完,还有个功能在研究中。。。看看怎么和NIOS II连接起来,做成一个完整的项目。

    module key(clk,reset,key_in,STOP_RUN,UPDOWN,RST,CONFIG);

    input clk;
    input reset;
    input key_in;
    output reg RST; //复位信号RST ,高电平有效
    output reg UPDOWN; //车行方向指示,为0是去行,为1时是回行
    output reg STOP_RUN; //停车态或行车态, 0停车态 1行车态
    output reg CONFIG; //CONFIG=1,表示进入设置状态



    reg [2:0] STATE; //状态

    parameter S0=3'b000,
    S1=3'b001,
    S2=3'b010,
    S3=3'b011,
    S4=3'b100,
    S5=3'b101,
    S6=3'b110,
    S7=3'b111; //状态机编码


    //**********************************************
    reg[19:0] cnt; //分频计数器

    always@(posedge clk or negedge reset)
    begin
    if(!reset)
    cnt<=20'd0;
    else if(cnt==20'd5_000)
    cnt<=20'd0; //计数50_000个时钟
    else
    cnt<=cnt+20'd1;
    end


    //**********************************************
    reg [9:0] count_d;
    reg [9:0] count; //
    //**********************************************
    always@(posedge clk or negedge reset)
    begin
    if(!reset)
    begin
    STATE<=S0;
    STOP_RUN <= 1'b0; //停车态
    UPDOWN <= 1'b0;
    RST <= 1'b0;
    CONFIG <= 1'b0;
    count_d <= 1'b0;
    count <= 1'b0;

    end
    else if(cnt==20'd4_999) //10ms扫描一次
    begin
    case(STATE)
    //----
    S0: //判别是否有按键按下
    begin
    if(key_in==0)
    STATE<=S1;
    else
    begin
    count <= 10'd0;
    //STATE<=S0;
    //STOP_RUN <= 1'b0;
    RST <= 1'b0;
    end
    end
    //----
    S1: //判别短单击
    begin
    if(key_in==0)
    begin
    if(count>=10'd210) //按键按下的时间超过2.1s,跳转下个状态
    STATE<=S2;
    else //
    count <= count + 10'd1;
    end
    else
    begin
    if(count>=10'd3) //30ms,防抖
    begin
    count <= 10'd0;
    STATE<=S5;
    end
    else //按键有按下,但时间太短,不允响应,跳转S0
    STATE<=S0;
    end
    end
    //----
    S2: //复位
    begin
    if(key_in==0)
    begin
    if(count>=10'd400)
    STATE<=S3;//按键按下的时间超过4s,跳转下个状态
    else
    count <= count + 10'd1;
    end

    else
    begin
    if(count>=10'd220) //大于等于2.2s 产生复位信号
    begin
    RST <= 1;
    count <= 10'd0;
    STATE<=S0;
    end
    else //按键有按下,但时间不足3s,不允响应,跳转S0
    STATE<=S0;
    end
    end
    //----
    S3: //设置指示
    begin
    if(key_in==0)
    begin
    if(count>=10'd800)
    STATE<=S4; //按键按下的时间超过8s,跳转下个状态
    else
    count <= count + 10'd1;
    end
    else
    begin
    if(count>=10'd420) //大于等于4.2s CONFIG置位
    begin
    CONFIG <= ~CONFIG;
    count <= 10'd0;
    STATE<=S0;
    end
    else //按键有按下,但时间不足5s,不允响应,跳转S0
    STATE<=S0;
    end
    end
    //----
    S4: //按键按下超过8s一直没放开
    begin
    if(key_in==0) //按键一直没有释放,一直处于S4
    STATE <= S4;
    else //按键释放,跳转S0
    STATE <= S0;
    end
    //----
    S5: //判别一次按键后短时间内是否有第二次按键
    begin
    if(key_in)
    begin
    if(count_d>=50)//两次按键如果大于0.5s ,则不予响应,跳转S6--STOP_RUN
    begin
    count_d <= 10'd0;
    STATE<=S6;
    end
    else
    count_d <= count_d + 10'd1;
    end
    else //两次按键如果小于0.5s,表明有双击,跳转S7
    STATE<=S7;
    end
    //----
    S6: //单击 输出STOP_RUN
    begin
    if(count_d==0)
    begin
    STOP_RUN <= ~STOP_RUN;
    STATE <= S0;
    end
    end
    //----
    S7: //双击 输出UPDOWN
    begin
    if(key_in)
    begin
    if(count_d<=49 && count_d>=2)
    begin
    UPDOWN <= ~UPDOWN;
    STATE <= S0;
    count_d <= 10'd0;
    end
    else //两次按键如果小于20ms ,表明有抖动,重新跳回S5
    STATE<=S5;
    end
    end
    //----
    default:
    STATE <= S0;
    //----
    endcase
    end

    else
    ;
    end

    //******************************************************************
    endmodule
  • 相关阅读:
    SQL开窗函数
    mysql中可以实现类似if判断的方法
    sql中COUNT(*)、COUNT(字段名)的区别
    shiro学习笔记_0600_自定义realm实现授权
    shiro学习笔记_0500_授权
    shiro学习笔记_0400_自定义realm实现身份认证
    shiro学习笔记_0300_jdbcRealm和认证策略
    shiro学习笔记_0200_认证
    点击div跳转的方法
    jq获取网页url
  • 原文地址:https://www.cnblogs.com/xuanxiaochen/p/2366625.html
Copyright © 2011-2022 走看看