本文介绍在EBAZ4205平台上用PL的资源驱动无源蜂鸣器
- 实验内容适用于市面上功能正常的EBAZ4205的板子
- 本次实验需要连接本站点的EBAZ4205转接板
- 本次实验默认EBAZ4205主板上已焊接50M有源晶振
- 如主板没有焊接晶振可根据下文的方法为PL端提供时钟EBAZ4205 ZYNQ 通过 PS部分来为PL逻辑提供时钟(没有焊接PL晶振的板子可用此方法)
- 本文在 vivado2018.3版本上演示
工程创建的过程可以参考实验一中的内容,这里不详细描述了。基于EBAZ4205 的FPGA实验一 用ZYNQ的PL资源点亮一个LED (完整图文) (芯片型号选XC7Z010CLG400-1)
1.)电路部分

无源蜂鸣器的驱动部分如上图所示,当三极管导通时,蜂鸣器上流过电流,当三极管关闭,蜂鸣器上电流停止流过。
蜂鸣器的驱动部分连接到EBAZ4205 的D18管脚
2)无源蜂鸣器简单介绍
无源蜂鸣器不像有源蜂鸣器那样只要通上电就会发出声音,无源蜂鸣器内部没有振荡驱动单元,需要以一定的振荡频率去驱动蜂鸣器,让蜂鸣器以特定的频率进行发声, 缺点是驱动方式稍复杂,优点就是可以发出不同音调的声音。
以下为查资料得知的每个乐调对应的频率。

根据每个音调的频率值,可以计算得出PWM发送模块的预重装值,以下为计算得出的音调频率与对应PWM发送模块输出相应频率的预重装值。(对应的是50M时钟下的值)
计算举例 50M频率下 1S的振荡次数是 50_000_000次, 而261.6hz的周期是1秒循环261.6次,那么在50M频率下 261.6hz的一个周期相当于振荡50_000_000/261.6=191_131 即下图中的预重装值

因为驱动蜂鸣器PWM 的占空比是50%,所以高电平低电平各占一半,所以高低电平的预装周期分别为 整个周期的一半,即完整预装值/2, 也可以用右移一位来替代
3) 代码实现
`timescale 1ns / 1ps
module BEEP_MODULE(
input clk,//50m 波形
output reg beep
);
parameter D0=191130;
parameter RE=170241;
parameter MI=151698;
parameter FA=143183;
parameter SO=127550;
parameter LA=113635;
parameter XI=101234;
//PWM 发声模块,用来产生特定的PWM波形
reg [16:0]beep_pwm_count;
reg [16:0]beep_pwm;
always@(posedge clk)
if(beep_pwm_count>=beep_pwm)begin
beep_pwm_count<=17'd0;
beep<=~beep;
end
else beep_pwm_count<=beep_pwm_count+1'b1;
reg [2:0]voice_mode;
parameter T500_MS = 26'd25_000_000 ;
reg [24:0]time_count;//
//初始化寄存器用
initial begin
voice_mode<=3'd0;
time_count<=25'd0;
end
//0.5秒定时器,每0.5秒改变一次声调,通过voice_mode来调整音调
always@(posedge clk)
if(time_count>=T500_MS)begin
time_count<=25'd0;
if(voice_mode>=3'd6)voice_mode<=3'd0;
else voice_mode<=voice_mode+1'b1;
end
else time_count<=time_count+1'b1;
//将当前voice_mode对应的音调值赋给 beep_pwm寄存器
//向右移动一位的作用是,预设值是实际波长的一半
always@(posedge clk)
case(voice_mode)
3'd0:beep_pwm<=D0>>1;
3'd1:beep_pwm<=RE>>1;
3'd2:beep_pwm<=MI>>1;
3'd3:beep_pwm<=FA>>1;
3'd4:beep_pwm<=SO>>1;
3'd5:beep_pwm<=LA>>1;
3'd6:beep_pwm<=XI>>1;
endcase
endmodule
本章节的工程:
- 本文的完整工程下载:04_PL_BEEP
- VIVADO的版本:2018.3
- 工程适用主板: EBAZ4205主板+转接板
