一.按键消抖原理
-
由于按键的物理特性,芯片会识别信号出现多次高低电平变化,会出现如下图的未消抖信号。影响我们的整个项目。
-
所以我们在使用按键时需要消抖,以确保按键被按下时只检测到一次低电平,我们期望的效果如下。
1.1按键消抖方式
- 硬件消抖:通过RS触发器或电容滤波实现(了解即可)
- 软件消抖:通过一个延时实现:当检测到按键信号电平改变时,延时20ms,然后再取该时刻信号作为输出。
1.2按键消抖流程图
-
延时计数器流程图
-
根据延时计数器获取状态(是否抖动)的按键信号
二.蜂鸣器原理
- 由上图可知:值为1时蜂鸣器工作。
三.代码
3.1按键消抖模块
/**************************************功能介绍***********************************
Date : 2023年7月26日20:20:20
Author : Alegg xy.
Version : 1.0
Description: 按键消抖模块
*********************************************************************************/
//---------<模块及端口声名>------------------------------------------------------
module key_debounce(
input wire clk ,//时钟50MHz
input wire rst_n,//复位信号,下降沿有效
input wire key ,//按键
output reg flag ,//消抖完成标志,0表示还在抖动,1表示抖动结束
output reg key_out//消抖完的有效电平
);
parameter DELAY = 20'd1000_000;//20ms
reg [19:0] delay_cnt ;//延迟计数器
reg key_r ;//中间按键寄存器,存放当前按键信号,用于和下次按键信号做比较
//延迟计数器模块
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin//按键复位
delay_cnt <= 20'd0;//初始延迟计数器默认为0
key_r <= 1'b1;//初始中间按键寄存器为高电平,按键高电平无效
end
else begin
key_r <= key;//此刻值赋给key_r,然后key_r与下一时刻key对比
if(key_r != key)begin//抖动:key_r != key
delay_cnt <= DELAY;//开始设置延迟计数器初值
end
else begin//没有抖动
if(delay_cnt > 20'd0)begin//如果延迟计数器大于0
delay_cnt <= delay_cnt - 20'd1;//开始倒数计时
end
else begin
delay_cnt <= 20'd0;//如果延迟计数器小于等于0,延迟计数器清0
end
end
end
end
//根据延迟计数器获取状态以及稳定的按键信号
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin//复位信号
flag <= 1'b0;//初始为0:抖动
key_out <= 1'b1;//记录按键稳定信号
end
else if(delay_cnt == 1'd1)begin//计数20ms
flag <= 1'b1;//条件满足,赋值为1,不抖动
key_out <= key;//key_out将稳定信号输出
end
else begin
flag <= 1'b0;//计数器没有计至20ms,仍然抖动
key_out <= key_out;//key_out保持不变
end
end
endmodule
3.2蜂鸣器控制模块
/**************************************功能介绍***********************************
Date : 2023年7月26日20:20:29
Author : Alegg xy.
Version :
Description:
*********************************************************************************/
//---------<模块及端口声名>------------------------------------------------------
module ctrl_beep(
input clk ,
input rst_n ,
input key ,
output reg beep
);
//---------<参数定义>---------------------------------------------------------
//---------<内部信号定义>-----------------------------------------------------
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
beep <= 0;
end
else if(flag && ~key)begin
beep <= ~beep;
end
else begin
beep <= beep;
end
end
endmodule
3.3顶层模块设计
module top_key_beep (
input wire clk ,
input wire rst_n ,
input wire key ,
output wire beep
);
wire flag_link;
wire key_link;
key_debounce u_key_debounce(
.clk (clk),
.rst_n (rst_n),
.key (key),
.flag (flag_link),
.key_out (key_link)
);
ctrl_beep u_ctrl_beep(
.clk (clk),
.rst_n (rst_n),
.flag (flag_link),
.key (key_link),
.beep (beep)
);
endmodule
- 注意要设置顶层文件
四.模块图
五.引脚配置
信号 | 管脚 |
---|---|
clk | E1 |
rst_n | E15 |
key | E16 |
beep | J1 |