赞
踩
目录
蜂鸣器按照构造方式的不同,可分为压电式蜂鸣器和电磁式蜂鸣器两种类型,由于两种蜂鸣器发音原理不同,压电式结构简单耐用但音调单一音色差,适用于报警器等设备。而电磁式由于音色好,所以多用于语音、音乐等设备。
蜂鸣器按照驱动电路的不同可以分为有源蜂鸣器与无源蜂鸣器。有源蜂鸣器内部带震荡源,所以只要通电就会鸣叫;而无源蜂鸣器内部不带震荡源,因此如果用直流信号无法令其鸣叫,这就需要用 2K-5K 的方波(声音频率)去驱动。ACZ702 开发板上使用了一枚 3.3V 直流电压驱动的电磁式无源蜂鸣器。其原理图如下图所示:
- module pwm_gen(
- input clk,
- input reset_n,
- input pwm_gen_en,//使能信号
- input [31:0]counter_arr,//预重装值,用来设定频率
- input [31:0]counter_crr,//比较值,用来调节占空比
- output reg pwm_out//输出pwm波
- );
-
- reg [31:0]pwm_gen_cnt;
-
- always@(posedge clk or negedge reset_n)
- if(!reset_n)
- pwm_gen_cnt <= counter_arr;
- else if(pwm_gen_en)begin
- if(pwm_gen_cnt <= 1)
- pwm_gen_cnt <= counter_arr; //计数减到 1,加载预重装寄存器值
- else
- pwm_gen_cnt <= pwm_gen_cnt - 1; //计数器自减 1
- end
- else //未使能时,计数器值等于预重装寄存器值
- pwm_gen_cnt <= counter_arr;
-
- always@(posedge clk or negedge reset_n)
- if(!reset_n)
- pwm_out <= 0;//复位时,PWM 输出低电平
- else if(pwm_gen_cnt <= counter_crr) //计数值小于比较值,PWM 输出高电平
- pwm_out <= 1;
- else
- pwm_out <= 0; //计数值大于比较值,PWM 输出低电平
- endmodule
- `timescale 1ns / 1ps
- module pwm_gen_tb();
-
- reg clk;
- reg reset_n;
- reg pwm_gen_en;
- reg [31:0]counter_arr;
- reg [31:0]counter_crr;
- wire pwm_out;
-
- pwm_gen pwm_gen_inst(
- .clk (clk) ,
- .reset_n (reset_n) ,
- .pwm_gen_en (pwm_gen_en) ,//使能信号
- .counter_arr (counter_arr) ,//预重装值,用来设定频率
- .counter_crr (counter_crr) ,//比较值,用来调节占空比
- .pwm_out (pwm_out) //输出pwm波
- );
-
- initial clk =1;
- always #10 clk = ~clk;
-
- initial begin
- reset_n = 0;
- pwm_gen_en = 0;
- counter_arr =0;
- counter_crr = 0;
- #201;
- reset_n = 1;
- #201;
- counter_arr = 1000; //设置输出信号频率为 50KHz
- counter_crr = 400; //设置输出 PWM 波占空比为 40%
- #100;
- pwm_gen_en = 1; //启动计数以产生 PWM 输出
- #100050;
- counter_crr = 700; //设置输出 PWM 波占空比为 70%
- #100050;
- pwm_gen_en = 0; //停止计数以关闭 PWM 输出
-
- counter_arr = 500; //设置输出信号频率为 100KHz
- counter_crr = 250; //设置输出 PWM 波占空比为 50%
- #100;
- pwm_gen_en = 1; //启动计数以产生 PWM 输出
- #50050;
- counter_crr = 100; //设置输出 PWM 波占空比为 20%
- #50050;
- pwm_gen_en = 0; //停止计数以关闭 PWM 输出
- #200;
- $stop;
- end
- endmodule
- module pwm_gen_test(
- input clk,
- input reset_n,
- output beep
- );
-
- reg [27:0]delay_500ms; //500ms延时计数器
- reg [2:0] bit_cnt;//位计数器
- reg [31:0]counter_arr; //预重装值寄存器
- wire [31:0]counter_ccr; //输出比较值
-
- parameter MCNT_500ms = 2500_0000;
- //7个音调的预重装值,也叫频率周期
- localparam D1 = 170068, //D 调音 1
- D2 = 151515, //D 调音 2
- D3 = 142857, //D 调音 3
- D4 = 127227, //D 调音 4
- D5 = 113379, //D 调音 5
- D6 = 101010, //D 调音 6
- D7 = 89928 ; //D 调音 7
-
- //输出比较值为预重装值一半
- assign counter_ccr = counter_arr >> 1;//右移一位,数值变为一半
- pwm_gen pwm_gen_inst(
- .clk (clk) ,
- .reset_n (reset_n) ,
- .pwm_gen_en (1) ,//使能信号
- .counter_arr (counter_arr) ,//预重装值,用来设定频率
- .counter_crr (counter_ccr) ,//比较值,用来调节占空比
- .pwm_out (beep) //输出pwm波
- );
- //500ms持续计数逻辑
- always@(posedge clk or negedge reset_n)
- if(!reset_n)
- delay_500ms <= 0;
- else if(delay_500ms == MCNT_500ms - 1)
- delay_500ms <= 0;
- else
- delay_500ms <= delay_500ms + 1;
- //每 500ms 切换一次音调
- always@(posedge clk or negedge reset_n)
- if(!reset_n)
- bit_cnt <= 0;
- else if(delay_500ms == MCNT_500ms - 1)
- bit_cnt <= bit_cnt + 1;
- else
- bit_cnt <= bit_cnt;
-
- //根据音调编号给预重装值给相应的值
- always@(posedge clk or negedge reset_n)
- if(!reset_n)
- counter_arr <= 1;
- else begin
- case(bit_cnt)
- 0:counter_arr <= 1 ;
- 1:counter_arr <= D1;
- 2:counter_arr <= D2;
- 3:counter_arr <= D3;
- 4:counter_arr <= D4;
- 5:counter_arr <= D5;
- 6:counter_arr <= D6;
- 7:counter_arr <= D7;
- endcase
- end
- endmodule
3.7 管脚约束文件列表
- set_property IOSTANDARD LVCMOS33 [get_ports beep]
- set_property IOSTANDARD LVCMOS33 [get_ports clk]
- set_property IOSTANDARD LVCMOS33 [get_ports reset_n]
- set_property PACKAGE_PIN G15 [get_ports beep]
- set_property PACKAGE_PIN U18 [get_ports clk]
- set_property PACKAGE_PIN F20 [get_ports reset_n]
以上代码即可实现蜂鸣器即开始循环播放“哆来咪发梭拉西”7 个音。
- module get_pitch(
- input clk,
- input reset_n,
- output reg [8:0]pitch_num //获取音符 rom 的地址编号
- );
-
- reg [23:0]cnt_125ms; //125ms 延时计数器,每个节拍的时间
-
- parameter MCNT_125ms_MAX = 6250000;
- //125ms持续计数逻辑
- always@(posedge clk or negedge reset_n)
- if(!reset_n)
- cnt_125ms <= 0;
- else if(cnt_125ms == MCNT_125ms_MAX - 1)
- cnt_125ms <= 0;
- else
- cnt_125ms <= cnt_125ms + 1;
-
- //每125ms切换一次音调的位控制逻辑 (每125ms获取一次音符 rom 的地址编号(递增))
- always@(posedge clk or negedge reset_n)
- if(!reset_n)
- pitch_num <= 0;
- else if(cnt_125ms == MCNT_125ms_MAX - 1)
- pitch_num <= pitch_num + 1;
- else
- pitch_num <= pitch_num ;
- endmodule
- module music_gen(
- input clk,
- input reset_n,
- output beep
- );
-
- reg [31:0]counter_arr ;//预重装值寄存器
- wire [31:0]counter_crr; //输出比较值
-
- wire [8:0]pitch_num; //音乐的音调编号,0-->最大值 循环递增
- wire [4:0]pitch; //音乐的音调
-
- localparam DL1 = 340136, //D 调低音 1
- DL2 = 303030, //D 调低音 2
- DL3 = 285714, //D 调低音 3
- DL4 = 255102, //D 调低音 4
- DL5 = 226244, //D 调低音 5
- DL6 = 201613, //D 调低音 6
- DL7 = 179856, //D 调低音 7
- D1 = 170068, //D 调音 1
- D2 = 151515, //D 调音 2
- D3 = 142857, //D 调音 3
- D4 = 127227, //D 调音 4
- D5 = 113379, //D 调音 5
- D6 = 101010, //D 调音 6
- D7 = 89928 , //D 调音 7
- DH1 = 84889, //D 调高音 1
- DH2 = 75643, //D 调高音 2
- DH3 = 71429, //D 调高音 3
- DH4 = 63613, //D 调高音 4
- DH5 = 56689, //D 调高音 5
- DH6 = 50505, //D 调高音 6
- DH7 = 44964; //D 调高音 7
-
- //根据 rom 存储输出不同的音调输出不同的预置数
- always@(posedge clk or negedge reset_n)
- if(!reset_n)
- counter_arr <= 1;
- else begin
- case(pitch)
- 5'b01_001:counter_arr = DL1; //D 调低音 1
- 5'b01_010:counter_arr = DL2; //D 调低音 2
- 5'b01_011:counter_arr = DL3; //D 调低音 3
- 5'b01_100:counter_arr = DL4; //D 调低音 4
- 5'b01_101:counter_arr = DL5; //D 调低音 5
- 5'b01_110:counter_arr = DL6; //D 调低音 6
- 5'b01_111:counter_arr = DL7; //D 调低音 7
-
- 5'b10_001:counter_arr = D1; //D 调音 1
- 5'b10_010:counter_arr = D2; //D 调音 2
- 5'b10_011:counter_arr = D3; //D 调音 3
- 5'b10_100:counter_arr = D4; //D 调音 4
- 5'b10_101:counter_arr = D5; //D 调音 5
- 5'b10_110:counter_arr = D6; //D 调音 6
- 5'b10_111:counter_arr = D7; //D 调音 7
-
- 5'b11_001:counter_arr = DH1; //D 调高音 1
- 5'b11_010:counter_arr = DH2; //D 调高音 2
- 5'b11_011:counter_arr = DH3; //D 调高音 3
- 5'b11_100:counter_arr = DH4; //D 调高音 4
- 5'b11_101:counter_arr = DH5; //D 调高音 5
- 5'b11_110:counter_arr = DH6; //D 调高音 6
- 5'b11_111:counter_arr = DH7; //D 调高音 7
- default: counter_arr = 32'd1;//休止符
- endcase
- end
-
-
- //rom例化
- blk_mem_gen_0 your_instance_name (
- .clka(clk), // input wire clka
- .addra(pitch_num), // input wire [8 : 0] addra
- .douta(pitch) // output wire [4 : 0] douta
- );
-
- get_pitch get_pitch(
- .clk(clk),
- .reset_n(reset_n),
- .pitch_num(pitch_num)
- );
-
- pwm_gen pwm_gen(
- .clk (clk),
- .reset_n (reset_n),
- .pwm_gen_en(1),//使能信号
- .counter_arr(counter_arr),//预重装值,用来设定频率
- .counter_crr(counter_crr),//比较值,用来调节占空比
- .pwm_out(beep)//输出pwm波
- );
- //设置输出比较值为预重装值一半
- assign counter_crr = counter_arr >> 1;
-
- endmodule
- `timescale 1ns / 1ps
- module music_gen_tb();
-
- reg clk;//系统时钟输入,50M
- reg reset_n; //复位信号输入,低有效
- wire beep;//pwm 输出信号
-
- music_gen music_gen(
- .clk(clk),
- .reset_n(reset_n),
- .beep(beep)
- );
-
- defparam music_gen.get_pitch.MCNT_125ms_MAX = 24'd6250;//缩短仿真时间
- initial clk = 1;
- always #10 clk = ~clk;
- initial
- begin
- reset_n = 0;
- #201;
- reset_n = 1;
- wait(music_gen.pitch_num == 512);//一轮播放结束
- #200;
- $stop;
-
- end
- endmodule
- set_property IOSTANDARD LVCMOS33 [get_ports clk]
- set_property IOSTANDARD LVCMOS33 [get_ports reset_n]
- set_property IOSTANDARD LVCMOS33 [get_ports beep]
- set_property PACKAGE_PIN G15 [get_ports beep]
- set_property PACKAGE_PIN F20 [get_ports reset_n]
- set_property PACKAGE_PIN U18 [get_ports clk]
至此“天空之城”音乐发生器设计完毕。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。