fpga开发——蜂鸣器

蜂鸣器的原理

有源蜂鸣器和无源蜂鸣器

         无源蜂鸣器利用电磁感应现象,为音圈接入交变电流后形成的电磁铁与永磁铁相吸或相斥而推动振膜发声,接入直流电只能持续推动振膜而无法产生声音,只能在接通或断开时产生声音。无源蜂鸣器的工作原理与扬声器相同。在使用方波信号源驱动的应反向并联一个二极管,防止突然断电时产生的高压反向电动势击穿其他元件以及使用寿命缩短。

        有源蜂鸣器插上电就能用,内部有固定频率,无法更改。

        在我的开发板上使用的是无源蜂鸣器,只有产生方波才能发出声音,产生不同频率的方波就产生不同音调的波形。

发出特定音调的声音

        开发板外部时钟50Mhz,若要产生262hz(do)音调,则计数器应该计数到50000000/262 = 190840个数,若要产生占空比为0.5的方波,则计数器可以计数到190840/2 = 95420 信号翻转,就产生了占空比0.5 的方波,可以驱动蜂鸣器发出连续的do音调。

代码如下:

module beep
#(parameter cnt_max = 17'd95419)
(input wire clk,
input wire rst,
output reg  beep);

//发出连续音调的声音
reg [16:0] cnt ;

always@(posedge clk or negedge rst)
begin
	if(rst == 1'd0)
		cnt<=17'd0;
	else if(cnt == cnt_max)
		cnt<=17'd0;
	else 
		cnt<= cnt+17'd1;
end

always@(posedge clk or negedge rst )
begin
	if(rst == 1'd0)
		beep <=1'd0;
	else if(cnt == cnt_max)
		beep<=~beep;
	else
		beep <= beep;
end

endmodule

发出间断的声音

         上述的代码是产生一个方波,通过这个方波才能驱动计数器发出声音,若要让蜂鸣器0.5s发出声音,0.5s不发出声音,就要设置一个计数器,计数到24999999,当计数到24999999时产生一个标志信号,通过标志信号产生一个选择信号,当选择信号为低电平的时候不发出声音,当选择信号为高电平的时候发出声音,选择信号的周期为1s,0.5s高电平,0.5s为低电平。高电平时按照上述方法产生音调tone方波。

代码如下:

module beep
#(parameter cnt_max = 17'd95419,
	parameter cnt_50ms = 25'd24999999)
(input wire clk,
input wire rst,
output reg  beep);

//发出有间隔的声音
reg [16:0] cnt_tone ; 
reg [24:0] cnt_space;
reg 	   space_flag;
reg        beep_sel;

always@(posedge clk or negedge rst)
begin
	if(rst ==1'd0)
		cnt_space <= 25'd0;
	else if (cnt_space == (cnt_50ms -1))
		cnt_space <= 25'd0;
	else 
		cnt_space<=cnt_space+25'd1;
end

always@(posedge clk or negedge rst)
begin
	if(rst ==1'd0)
		space_flag <= 1'd0;
	else if (cnt_space == (cnt_50ms - 1))
		space_flag <=1'd1;
	else 
		space_flag<=1'd0;
end

always@(posedge clk or negedge rst)
begin
	if(rst ==1'd0)
		beep_sel <= 1'd0;
	else if( space_flag == 1'd1)
		beep_sel<= ~beep_sel;
	else
		beep_sel <=beep_sel;
end


always@(posedge clk or negedge rst)
begin
	if(rst == 1'd0)
		cnt_tone<=17'd0;
	else if(cnt_tone == cnt_max)
		cnt_tone<=17'd0;
	else 
		cnt_tone<= cnt_tone+17'd1;
end

always@(posedge clk or negedge rst )
begin
	if(rst == 1'd0)
		beep <=1'd0;
	else if(beep_sel==1'b1)
		if(cnt_tone == cnt_max)
			beep<=~beep;
		else
			beep <= beep;
	else 
		beep<=1'd0;
end

endmodule

测试文件如下,为了便于观察波形,将最大值设小:

`timescale 1ns/1ns
`include"beep_test.v"

module top();

reg clk;
reg rst;

initial
begin
	clk <= 1'b0;
	rst<=1'b0;
	#25
	rst <=1'b1;
end

always #10 clk =~clk;

beep 
#(.cnt_max(17'd24),
  .cnt_50ms(25'd99))
b1
(clk,rst,beep);

endmodule

仿真波形如下:

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年12月7日
下一篇 2023年12月7日

相关推荐