【FPGA实战篇二】 蜂鸣器实现音乐播放


蜂鸣器实现音乐播放)

一、蜂鸣器

1、蜂鸣器介绍

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。在一般设计中,可利用蜂鸣器检测有些按键是否按下,或者有些功能是否正常等,也可以让蜂鸣器演奏音乐。
蜂鸣器分为:有源蜂鸣器、无源蜂鸣器;
①有源蜂鸣器:
有源蜂鸣器内部有振荡驱动电路,只要加上电源就可以发声,可以用作报警器的发声器件,但是缺点就是它的频率是固定的,因此只有一个单一的音调。
②无源蜂鸣器:
无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用2K~5K的方波去驱动它。

2、设计原理图

蜂鸣器原理图
在这里插入图片描述
本设计使用的是无源蜂鸣器,也可称为声响器,原理电路图如下所示。它没有内部驱动电路,无源蜂鸣器工作的理想信号为方波,如果给直流,蜂鸣器是不响应的,因为磁路恒定,钼片不能震动发音。
在这里插入图片描述
下面我们开始详细介绍蜂鸣器实现音乐播放的详细流程。

二、工程创建

1、新建项目

打开quartus,【File】→【New Project Wizard 】
在这里插入图片描述
编辑项目相关信息
在这里插入图片描述
选中empty project
在这里插入图片描述
后面是添加文件的,这里是新建直接next。
选择芯片:EP4CE6F17C8
在这里插入图片描述
选择你的仿真软件版本(根据你自己安装的版本进行选择)
在这里插入图片描述
配置信息完成,点击Finish;(注意对比信息,如果信息不对,可back重新编辑)
在这里插入图片描述
创建好后,主界面如示
在这里插入图片描述

2、新建verilog文件

点击【File】→【New】→【Verilog HDL File】→【OK】
在这里插入图片描述
出现了一个空白界面,在右边输入你的Verilog 代码
在这里插入图片描述
选择File
在这里插入图片描述
代码编辑完成后,点击保存;
在这里插入图片描述
弹出dialog,保存在你的项目路径下
在这里插入图片描述
单击保存,此后就出现了一个one.v的文档(保存的名字需要和模块例化名一致,以免报错
在这里插入图片描述
创建工程所有文件,最后进行编译
在这里插入图片描述
至此,项目创建以及Verilog代码编写就完成了,下面看具体的实现。

二、代码实现及工程编译

百度查询“两只老虎”音谱
在这里插入图片描述

1、代码实现

按照上述流程,创建对应file,编写Verilog代码;
①pwm_buzzer

module pwm_buzzer(

	input				clk	,
	input				rst_n	,

	output	    	buzzer	//驱动蜂鸣器
);

//参数定义
		
		localparam 	M1 = 95600,
						M2 = 85150,
						M3 = 75850,
						M4 = 71600,
						M5 = 63750,
						M6 = 56800,
						M7 = 50600;
						
		parameter 	TIMES	= 500;
		
//信号定义
	reg				buzzer_r	;
	
	reg	[16:0]	cnt0	;//计数每个音符对应的周期
	reg	[8:0]		cnt1	;//计数每个音符重复多少次
	reg	[5:0]		cnt2	;//一共有多少个音符
	
	reg	[16:0]	pre_set;//预装载值
	reg 	[16:0]	pre_div;//设定占空比

	always@(posedge clk or negedge rst_n)begin 
		if(~rst_n)begin 
			cnt0 <= 0;
		end 
		else begin 
			if(cnt0 == pre_set-1)
				cnt0 <= 0;
			else 
				cnt0 <= cnt0 + 1;
		end 
	end 
	
	always@(posedge clk or negedge rst_n)begin 
		if(~rst_n)begin 
			cnt1 <= 0;
		end 
		else if(cnt0 == pre_set-1)begin 
			if(cnt1 == TIMES-1)
				cnt1 <= 0;
			else 
				cnt1 <= cnt1 + 1;
		end 
	end
	
	always@(posedge clk or negedge rst_n)begin 
		if(~rst_n)begin 
			cnt2 <= 0;
		end 
		else if(cnt1 == TIMES-1 && cnt0 == pre_set-1)begin 
			if(cnt2 == 32-1)
				cnt2 <= 0;
			else 
				cnt2 <= cnt2 + 1;
		end 
	end
	
	//pre_set  查找表 选择每个音频对应的计数周期
	always@(posedge clk or negedge rst_n)begin 
		if(~rst_n)begin 
			pre_set <= 0;
		end 
		else begin 
			case(cnt2)
			0 :pre_set <= M1;
			1 :pre_set <= M2;
			2 :pre_set <= M3;
			3 :pre_set <= M1;
			4 :pre_set <= M1;
			5 :pre_set <= M2;
			6 :pre_set <= M3;
			7 :pre_set <= M1;
			8 :pre_set <= M3;
			9 :pre_set <= M4;
			10:pre_set <= M5;
			11:pre_set <= M3;
			12:pre_set <= M4;
			13:pre_set <= M5;
			14:pre_set <= M5;
			15:pre_set <= M6;
			16:pre_set <= M5;
			17:pre_set <= M4;
			18:pre_set <= M3;
			19:pre_set <= M1;
			20:pre_set <= M5;
			21:pre_set <= M6;
			22:pre_set <= M5;
			23:pre_set <= M4;
			24:pre_set <= M3;
			25:pre_set <= M1;
			26:pre_set <= M2;
			27:pre_set <= M5;
			28:pre_set <= M1;
			29:pre_set <= M2;
			30:pre_set <= M5;
			31:pre_set <= M1;
			default:pre_set <= M1;
			endcase
		end 
	end 
	
	
	always @ (posedge clk or negedge rst_n)begin 
		if(~rst_n)begin 
			pre_div <= 0;
		end 
		else begin 
			pre_div <= pre_set>>1;
		end 
	end 
	
	//assign pre_div = pre_set>>1;//  /2; 设定占空比为50%

	always @ (posedge clk or negedge rst_n)begin 
		if(~rst_n)begin 
			buzzer_r <= 1'b1;
		end 
		else if(cnt0 < pre_div)begin 
			buzzer_r <= 1'b1;
		end 
		else begin 
			buzzer_r <= 1'b0;
		end 
	end 

	assign buzzer = buzzer_r;
	
endmodule	

②pwm_buzzer_tb

`timescale 1ns/1ns

module pwm_buzzer_tb();

	reg			tb_clk	;
	reg			tb_rst_n	;
	
	wire			tb_buzzer;
	
	pwm_buzzer u_pwm(

	.clk		(tb_clk		),
	.rst_n	(tb_rst_n	),
	.buzzer	(tb_buzzer	) //驱动蜂鸣器
);

	parameter CLOCK_PERIOD = 20;
	defparam u_pwm.TIMES = 50;
	
	
	initial tb_clk = 1'b0;
	always #(CLOCK_PERIOD/2) tb_clk = ~tb_clk;
	
	initial begin 
		tb_rst_n = 1'b0;
		#(CLOCK_PERIOD*20); 
		tb_rst_n = 1'b1;
		#(CLOCK_PERIOD*200000000); 
		$stop;
		
	end 
	
	
	
endmodule 

2、编译

点击编译(或者上述标注的快捷键)
在这里插入图片描述
编译信息
在这里插入图片描述
编译进度
在这里插入图片描述
编译结果
在这里插入图片描述

三、电路及仿真

1、电路原理图

【Tools】→【Netlist Viewers】→【RTL Viewer】
在这里插入图片描述
原理图
在这里插入图片描述

2、仿真

配置仿真环境
【tools】→【options】
在这里插入图片描述
按图示操作
在这里插入图片描述
查看仿真
在这里插入图片描述
添加测试文件
【Assignment】→【Settings…】
在这里插入图片描述
按序号操作
在这里插入图片描述
点击出现
在这里插入图片描述
选择测试文件
在这里插入图片描述
选择test文件
在这里插入图片描述
复制名字到上面
在这里插入图片描述
此后,就一直点OK。
查看仿真波形
选中模块,鼠标右键点击添加波形
在这里插入图片描述
点击下标wave,查看
在这里插入图片描述
左边加入(快捷键Ctrl A+Ctrl G)
在这里插入图片描述
波形示意图
在这里插入图片描述
至此仿真部分就结束了。

四、开发板验证

1、驱动下载

在电脑左下角输入“设备管理器”
在这里插入图片描述
找到“人体学输入设备”,继续下面的操作
在这里插入图片描述

2、烧录程序

再次全编译
在这里插入图片描述
编译无误,连接开发板,打开电源进行烧录
在这里插入图片描述
连接开发板
在这里插入图片描述
选择全编译,查看是否出错
在这里插入图片描述
编译无误,点击烧录
在这里插入图片描述
出现如示界面则点击红色方框内容,添加驱动
在这里插入图片描述
选择驱动,点击close
在这里插入图片描述
ps:如果没有驱动,需要自己下载,
查看信息,点击start烧录
在这里插入图片描述
烧录成功
在这里插入图片描述

3、成果展示

成果演示:
在这里插入图片描述
录制了一个视频,可以看一下,但是声音比较小。
蜂鸣器实现音乐播放.

Guess you like

Origin blog.csdn.net/QWERTYzxw/article/details/118755142