按键消抖学习记录-VIVADO-附代码(注释)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

详细记录按键消抖的学习记录,以后如果有用到的地方可以及时回来回顾;对一些代码作出详细的注释,方便以后自己理解。

按键消抖其实和容易理解,按下去,弹上来,这是大多数按键的操作,机械式的操作就会带来我们不需要的变量,比如在刚刚按下去的时候,接触点断断续续,这个过程大约持续5ms-10ms,弹起来同理,这就是所谓的抖动。为了确保按键的精确性,所以要做消抖处理。


提示:以下是本篇文章正文内容,下面案例可供参考

一、如何消抖

既然知道了为什么抖动,那么就在按键抖动的时候不采样嘛,当按键在某个状态持续够某个时间时,再认为他被按下啦,这不就行了。

我们通常把这个时间设定为20ms(这不是绝对的,你可以长一点,或者短一点,不要太短,因为可能还是抖动),当该按键的状态发生变化时,变化后的状态是否持续20ms,如果有,则判定该按键有效,如果没有持续20ms,则判定为抖动。

二、模块划分

1.pll模块

这个简单,直接调用ip core就行,输入时钟50Mhz,输出时钟我设了两个50Mhz和100Mhz;下面是pll例化部分,我把pll的ip core 命名为u1_pll

pll u1_pll(
        .clk_out1(clk_50M       ),  // output clk_50Mhz
        .clk_out2(clk_100M      ),  // output clk_100Mhz
        .reset   (~rst_n        ),  // input reset
        .locked  (                ),  // output locked
        .clk_in1 (clk           )   // input clk_50Mhz
    );    

2.key_debounce模块

第二个模块就是消抖模块,参考了黑金和正点原子,从TIME_VAL 递减,减完产生一个按键按下的信号或者是按键弹起的信号,是上升沿还是下降沿有key_value和key_flag共同juedin

//======================================================================
//Company			: 
//Filenam			: .v
//Author			: 
//Created On		: 2023-12-14 10:20
//Last Modified		: 2023-12-14 18:10
//Description		: 
//				  
//				  
//======================================================================

module key_debounce(
    input                           clk                ,   //
    input                           rst_n              ,   //
    input                           key                ,   //
    output       	reg			    key_value          ,   //
    output       	reg			    key_flag               //
    );
    parameter                       FREQ        =   50    ;   // Mhz
    parameter                       TIME_MAX    =   20    ;   // ms
    localparam                      TIME_VAL    =   TIME_MAX * FREQ * 1000    ;   //

    reg         [   19:0    ]       key_cnt               ;   //
    reg                             key_r1                ;   //
    reg                             key_r2                ;   //

/**************************************************************************
//
**************************************************************************/
    always  @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            key_r1 <= 1'b1;
            key_r2 <= 1'b1;
        end
        else begin
            key_r1 <= key;
            key_r2 <= key_r1;
        end
    end 

    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            key_cnt <= 20'd0;
        end
        else begin
            if( key_r2 == !key_r1)begin
                key_cnt <= TIME_VAL;
            end 
            else begin
                if( key_cnt > 20'd0) 
                    key_cnt <= key_cnt - 1'b1;
                else 
                    key_cnt <= 20'd0;
            end                
        end
    end
    
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            key_value <= 1'b1;
            key_flag  <= 1'b0;
        end
        else if (key_cnt == 20'd1)begin
            key_value <= key;
            key_flag  <= 1'b1;
        end 
        else begin
            key_value <= key_value;
            key_flag  <= 1'b0;       
        end
    end

endmodule


3.key_count模块

实现的功能是,按键按下,四个led变化,刚开始led=4'b1111,全灭,按下一次,变为led=4'b1110;再按一次变为led=4'b1100;以此类推;

//======================================================================
//Company			: 
//Filenam			: .v
//Author			: 
//Created On		: 2023-12-14 18:22
//Last Modified		: 
//Description		: 
//				  
//				  
//======================================================================
`timescale 1ns / 1ps

module key_count(
    input                           clk               ,    //
    input                           rst_n             ,    //
    input                           key_flag          ,    //
    input                           key_value         ,    //
    output   reg  [    3:0    ]     led                    //

    );

    reg         [    3:0    ]       led_cnt           ;   //

    always  @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            led_cnt  <= 4'b1111;
        end
        else if(key_flag&&!key_value)begin
            led_cnt <= led_cnt + 1'b1;
        end
        else begin
            led_cnt <= led_cnt ;
        end
    end

    always  @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            led  <= 4'b1111;
        end
        else begin
            led <= led_cnt ;
        end
    end


endmodule

4.顶层模块key_ctrl

//======================================================================
//Company			: 
//Filenam			: .v
//Author			: 
//Created On		: 2023-12-14 18:33
//Last Modified		: 
//Description		: 
//				  
//				  
//======================================================================
`timescale 1ns / 1ps

module key_ctrl(
    input                           clk               ,    //
    input                           rst_n             ,    //
    input                           key               ,    //
    output   wire  [    3:0    ]    led                    //
    
    );
    wire                            key_value         ;   //
    wire                            key_flag          ;   //
    wire                            clk_50M           ;   //
    wire                            clk_100M          ;   //

    pll u1_pll(
        .clk_out1(clk_50M       ),  // output clk_50Mhz
        .clk_out2(clk_100M      ),  // output clk_100Mhz
        .reset   (~rst_n        ),  // input reset
        .locked  (		        ),  // output locked
        .clk_in1 (clk           )   // input clk_50Mhz
    );                      
    key_debounce u2_debounce(
       .clk      ( clk         ),        
       .rst_n    ( rst_n       ),       
       .key      ( key         ),        
       .key_value( key_value   ),   //
       .key_flag ( key_flag    )    //     
    );

    key_count u3_count(
       .clk      ( clk         ),  //
       .rst_n    ( rst_n       ),  //
       .key_flag ( key_flag    ),  //
       .key_value( key_value   ),  //
       .led      ( led         )   //

    );

endmodule

三、总结

怎么说呐!也是在学习吧,做什么都慢慢积累吧,走的很慢,但在向前;

征途漫漫,奋勇向前!!!共勉

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值