实验中使用的是有源蜂鸣器。
(1)蜂鸣器简介
一般的有源蜂鸣器内部自带了震荡源,只要通电就会发声。而无源蜂鸣器由于不含内部震荡源,需要外接震荡信号才能发声。
(2)实验任务
使用按键控制蜂鸣器发声。初始状态为蜂鸣器鸣叫,按下开关后蜂鸣器停止鸣叫,再次按下开关,蜂鸣器重新鸣叫。
(3)硬件设计
可以直接将蜂鸣器接到FPGA引脚,同样STM32也可以,设置为推挽输出即可。
需要说明的是,由于蜂鸣器需要的驱动电流较大,使用默认8mA的驱动电流有可能出现蜂鸣器发声较小的情况,解决方法是将蜂鸣器输出的驱动电流修改成12mA或者是16mA
(4)程序设计
需要在按键按下时改变蜂鸣器的鸣叫状态。但实际上在按键按下的过程中存在按键抖动的干扰,体现在数字电路中就是不断变化的高低电平,为避免在抖动过程中采集到错误的按键状态,我们需要对按键数据进行消除抖动处理。因此本系统应至少包含按键消抖模块和蜂鸣器控制模块,按键控制蜂鸣器系统框图。
查看软件生成的模块端口及信号连接图:
需要注意的是,必须已经执行过综合或编译之后,才能打开模块端口及信号连接图。打开之后,按下键盘的【Ctrl】键,滚动鼠标的滚轮可以对生连接图进行放大和缩小。模块端口及信号连接图可以比较清晰的查看各个模块端口信号的连接,同时双击模块,也可以进一步查看模块的原理图。
顶层模块例化了以下两个模块,按键消抖模块(key_debounce)和蜂鸣器控制模块(beep_control)。顶层模块(top_key_beep)完成了对另外两个模块的例化。按键消抖模块,主要起到延时采样,防止按键抖动的干扰。蜂鸣器控制模块,通过对按键信号的识别,起到控制蜂鸣器鸣叫的作用。
按键消抖模块(key_debounce):对按键信号延时采样,将消抖后的按键信号和按键数据有效信号输出至beep_control模块。蜂鸣器控制模块(beep_control):根据输入的按键信号和按键数据有效信号,来控制蜂鸣器的鸣叫。
在这里我们介绍一下按键消抖的原理。通常我们所使用的开关为机械弹性开关,当我们按下或松开按键时,由于弹片的物理特性,不能立即闭合或断开,往往会在断开或闭合的短时间内产生机械抖动,消除这种抖动的过程即称为按键消抖。
按键消抖可分为硬件消抖和软件消抖。硬件消抖主要使用RS触发器或电容等方法实现消抖,一般在按键较少时使用。软件消抖的原理主要为按键按下或松开后延时5ms—20ms采样,也可以在检测到按键状态稳定后采样,即避开抖动区域后再采样。
首先编写底层驱动代码:
module beep_control(
input sys_clk,
input sys_rst_n,
input key_flag,//key 有效信号
input key_value,//key_value
output reg beep
);
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
beep <= 1'b0;
else if(key_flag && (~key_value))//判断按键是否有效按下
beep <= ~beep;
end
endmodule
按键消抖
module key_debounce (
input sys_clk,
input sys_rst_n,
input key,
output reg key_flag,
output reg key_value
);
reg [31:0] delay_cnt;
reg key_reg;
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
key_reg <= 1'b1;
delay_cnt <= 32'b0;
end
else begin
key_reg <= key;
if(key_reg != key)
delay_cnt <= 32'd0000_000;
else if(key_reg == key)begin
if(delay_cnt < 32'd1000_000)
delay_cnt <= delay_cnt + 1'b1;
else
delay_cnt <= delay_cnt;
end
end
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
key_flag <= 1'b0;
key_value <= 1'b1;
end
else begin
if(delay_cnt == 32'd1000_000)begin
key_flag <= 1'b1;
key_value <= key;
end
else begin
key_flag <= 1'b0;
key_value <= key_value;
end
end
end
endmodule
顶层模块
module key_beep(
input sys_clk,
input sys_rst_n,
input key,
output beep
);
wire key_value;
wire key_flag;
key_debounce u_key_debounce(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key (key),
.key_flag (key_flag),
.key_value (key_value),
);
beep_control u_beep_control(
. sys_clk (sys_clk),
. sys_rst_n (sys_rst_n),
. key_flag (key_flag),
. key_value (key_value),
. beep (beep),
);
endmodule
模块信号连接图
(5)下载验证