蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。

图1 :蜂鸣器实物图

蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。

压电式蜂鸣器 压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。有的压电式蜂鸣器外壳上还装有发光二极管。多谐振荡器由晶体管或集成电路构成。当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。

电磁式蜂鸣器电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。

按照内部有无震荡源可以分为有源蜂鸣器和无源蜂鸣器。有源蜂鸣器内部带震荡源,所以只要一通电就会发出声音;而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用一定频率的方波去驱动它。

首先设计分频器,设计一个1KHz的方波,驱动蜂鸣器,观测蜂鸣器是否会有声音产生。

本小节研究如何利用蜂鸣器演唱一首曲子《世上只有妈妈好》。

下图为《世上只有妈妈好》的简谱。

图2:世上只有妈妈好的简谱

简谱是一种比较简单易学的音乐记谱法。据说简谱是由法国思想家卢梭于1742年发明的。而最早把简谱引进我国的是我国近代音乐教育家沈心工。简谱应该说是一种比较简单易学的音乐记谱法。它的最大好处是仅用7个阿拉伯数字----1234567,就能将万千变化的音乐曲子记录并表示出来.

在简谱中,用以表示音的高低及相互关系的基本符号为七个阿拉伯数字,即1、2、3、4、5、6、7,唱作do、re、mi、fa、sol、la、si,称为唱名。

音符:1234567

唱名:do re mi fa sol la si

汉字:哆来米发梭拉西

显然,单用以上七个音是无法表现众多的音乐形象的。在实际作品中,还有一些更高或更低的音,如在基本音符上方加记一个"·",表示该音升高一个八度,称为高音;加记两个" :",则表示该音升高两个八度,称为倍高音。在基本音符下方加记一个"·",表示该音降低一个八度,称为低音;加记两个" :",则表示该音降低两个八度,称为倍低音。

在一般歌曲中,无论是在基本音符上方或下方加记两个以上的"·"的音符都是很少见的。

在简谱中,1、2、3、4、5、6、7这七个基本音符,不仅表示音的高低,而且还是表示时值长短的基本单位,称为四分音符,其他音符均是在四分音符的基础上,用加记短横线"-"和附点"·"表示。

在基本音符右侧加记一条短横线,表示增长一个四分音符的时值。这类加记在音符右侧、使音符时值增长的短横线,称为增时线。增时线越多,音符的时值越长。

在基本音符下方加记一条短横线,表示缩短原音符时值的一半。这类加记在音符下方、使音符时值缩短的短横线,称为减时线。减时线越多,音符的时值越短。

在简谱中,加记在单纯音符的右侧的、使音符时值增长的小圆点"·",称为附点。加记附点的音符称为附点音符。附点本身并无一定的长短,其长短由前面的单纯音符来决定。附点的意义在于增长原音符时值的一半,常用于四分音符和小于四分音符的各种音符之后。

在《世上只有妈妈好》的简谱中,每两个竖线之间为2秒钟的时长。每两个竖线之间有4个音符时长,但是其中有较多半个音符的长,本设计采用1/4秒为基本单位。

蜂鸣器给予不同的频率是可以发出近似1、2、3、4、5、6、7这七个基本音符。

图3 :各个音符所对应的频率

此模块命名为music_beep,clk为50MHz的时钟,rst_n为低电平有效的复位,beep为蜂鸣器的驱动信号。

图4 :music_beep的模型

在设计时,首先将简谱中的音符存起来;利用计数器产生1/4秒为周期的脉冲,在此脉冲驱动下,将事先存好的音符一个个输出;根据音符的值,计算出分频比;根据分频比,产生对应频率的波形。将此波形输出即可。

图5 :架构图

在进行多模块设计时,可以对每个模块只设计端口,将架构完成后。再分别设计每个模块。

《世上只有妈妈好》的简谱中共有8个四拍,每个四拍我们用8个音符来表示,合计共64个音符。在speed_ctrl中,输出的cnt为6位,正好可以表示64个状态。

在speed_ctrl中,每1/8秒让cnt增加1即可。

module
speed_ctrl (

input  
wire            clk,

input  
wire            rst_n,

output 
reg   [5:0]     cnt

);

parameter T_250ms   =   12_500_000;

reg           [25:0]    count;

wire                    flag_250ms;

always @ (posedge clk, negedge rst_n) begin

if (rst_n == 1'b0)

count <= 26'd0;

else

if (count < T_250ms - 1'b1)

count <= count + 1'b1;

else

count <= 26'd0;

end

assign flag_250ms = (count == T_250ms -
1'b1) ? 1'b1 : 1'b0;

always @ (posedge clk, negedge rst_n) begin

if (rst_n == 1'b0)

cnt <= 6'd0;

else

if (flag_250ms == 1'b1)

cnt <= cnt + 1'b1;

else

cnt <= cnt;

end

endmodule

图6:speed_ctrl的设计代码

在music_mem中存储音符,存储方式为低音用1到7表示,中音用8到14表示,高音用15到21表示,music为5bit位宽。

module
music_mem (

input  
wire            clk,

input  
wire            rst_n,

input  
wire    [5:0]   cnt,

output 
reg     [4:0]   music

);

// 1  2 
3  4  5 
6  7

// 8  9  10
11 12 13 14

// 15 16 17 18
19 20 21

always @ (posedge clk, negedge rst_n) begin

if (rst_n == 1'b0)

music <= 5'd0;

else

case (cnt)

6'd0    :  
music <= 5'd13;

6'd1    :  
music <= 5'd13;

6'd2    :  
music <= 5'd13;

6'd3    :  
music <= 5'd12;

6'd4    :  
music <= 5'd10;

6'd5    :  
music <= 5'd10;

6'd6    :  
music <= 5'd12;

6'd7    :  
music <= 5'd12;

6'd8    :  
music <= 5'd15;

6'd9    :  
music <= 5'd15;

6'd10   :  
music <= 5'd13;

6'd11   :  
music <= 5'd12;

6'd12   :  
music <= 5'd13;

6'd13   :  
music <= 5'd13;

6'd14   :  
music <= 5'd13;

6'd15   :  
music <= 5'd13;

6'd16   :  
music <= 5'd10;

6'd17   :  
music <= 5'd10;

6'd18   :  
music <= 5'd12;

6'd19   :  
music <= 5'd13;

6'd20   :  
music <= 5'd12;

6'd21   :  
music <= 5'd12;

6'd22   :  
music <= 5'd10;

6'd23   :  
music <= 5'd10;

6'd24   :  
music <= 5'd8;

6'd25   :  
music <= 5'd6;

6'd26   :  
music <= 5'd12;

6'd27   :  
music <= 5'd10;

6'd28   :  
music <= 5'd9;

6'd29   :  
music <= 5'd9;

6'd30   :  
music <= 5'd9;

6'd31   :  
music <= 5'd9;

6'd32   :  
music <= 5'd9;

6'd33   :  
music <= 5'd9;

6'd34   :  
music <= 5'd9;

6'd35   :  
music <= 5'd10;

6'd36   :  
music <= 5'd12;

6'd37   :  
music <= 5'd12;

6'd38   :  
music <= 5'd13;

6'd39   :  
music <= 5'd13;

6'd40   :  
music <= 5'd10;

6'd41   :  
music <= 5'd10;

6'd42   :  
music <= 5'd10;

6'd43   :  
music <= 5'd9;

6'd44   :  
music <= 5'd8;

6'd45   :  
music <= 5'd8;

6'd46   :  
music <= 5'd8;

6'd47  
:   music <= 5'd8;

6'd48   :  
music <= 5'd12;

6'd49   :  
music <= 5'd12;

6'd50   :  
music <= 5'd12;

6'd51   :  
music <= 5'd10;

6'd52   :  
music <= 5'd9;

6'd53   :  
music <= 5'd8;

6'd54   :  
music <= 5'd6;

6'd55   :  
music <= 5'd8;

6'd56   :  
music <= 5'd5;

6'd57   :  
music <= 5'd5;

6'd58   :  
music <= 5'd5;

6'd59   :  
music <= 5'd5;

6'd60   :  
music <= 5'd5;

6'd61  
:   music <= 5'd5;

6'd62   :  
music <= 5'd5;

6'd63   :  
music <= 5'd5;

default  :  
music <= 5'd0;

endcase

end

endmodule

图7 :music_mem的设计代码

根据频率和音符的关系,将音符对应的频率值取出来,根据频率值算出分频比。驱动时钟为50MHz,所以分频比为50M除以频率。

module
cal_divnum (

input  
wire              clk,

input  
wire              rst_n,

input  
wire    [4:0]     music,

output 
reg     [31:0]    divnum

);

reg             [31:0]    freq;

always @ * begin

case (music)

5'd1   
: freq =    32'd262;

5'd2   
: freq =    32'd294;

5'd3   
: freq =    32'd330;

5'd4   
: freq =    32'd349;

5'd5   
: freq =    32'd392;

5'd6   
: freq =    32'd440;

5'd7   
: freq =    32'd494;

5'd8   
: freq =    32'd523;

5'd9   
: freq =    32'd587;

5'd10  
: freq =    32'd659;

5'd11  
: freq =    32'd699;

5'd12  
: freq =    32'd784;

5'd13  
: freq =    32'd880;

5'd14  
: freq =    32'd988;

5'd15  
: freq =    32'd1050;

5'd16  
: freq =    32'd1175;

5'd17  
: freq =    32'd1319;

5'd18  
: freq =    32'd1397;

5'd19  
: freq =    32'd1568;

5'd20  
: freq =    32'd1760;

5'd21  
: freq =    32'd1976;

default : freq =    32'd1;

endcase

end

always @ (posedge clk, negedge rst_n) begin

if (rst_n == 1'b0)

divnum <= 32'd50_000_000;

else

divnum <= 50_000_000/freq;

end

endmodule

图8 :cal_divmum的设计代码

知道分频数后,利用任意分频的方式,产生对的波形即可。

module
wave_gen (

input  
wire            clk,

input  
wire            rst_n,

input  
wire  [31:0]    divnum,

output 
reg             beep

);

reg           [31:0]    cnt;

always @ (posedge clk, negedge rst_n) begin

if (rst_n == 1'b0)

cnt <= 32'd0;

else

if (cnt < divnum - 1'b1)

cnt <= cnt + 1'b1;

else

cnt <= 32'd0;

end

always @ (posedge clk, negedge rst_n) begin

if (rst_n == 1'b0)

beep <= 1'b0;

else

if (cnt < divnum[31:1])

beep <= 1'b0;

else

beep <= 1'b1;

end

endmodule

图9 :wave_gen的设计代码

设计好上述四个模块后,将它们之前设计架构的连接方式,连接起来。

module
music_beep (

input  
wire              clk,

input  
wire              rst_n,

output 
wire              beep

);

wire          [5:0]       cnt;

wire          [4:0]       music;

wire          [31:0]      divnum;

speed_ctrl speed_ctrl_inst(

.clk                  (clk),

.rst_n                (rst_n),

.cnt                  (cnt)

);

music_mem music_mem_inst(

.clk                  (clk),

.rst_n                (rst_n),

.cnt                  (cnt),

.music                (music)

);

cal_divnum cal_divnum_inst(

.clk                  (clk),

.rst_n                (rst_n),

.music                (music),

.divnum               (divnum)

);

wave_gen wave_gen_inst(

.clk                  (clk),

.rst_n                (rst_n),

.divnum               (divnum),

.beep                 (beep)

);

endmodule

图10 :music_beep的设计代码

RTL视图如下,和所设计架构相同。

图11 :RTL视图

在testbench中,将speed_ctrl_inst模块中的T_250ms改成10。

defparam可以重新定义参数。

`timescale
1ns/1ps

module
music_beep_tb;

reg           clk;

reg           rst_n;

wire          beep;

defparam music_beep_inst.speed_ctrl_inst.T_250ms
= 10;

music_beep music_beep_inst(

.clk        (clk),

.rst_n      (rst_n),

.beep       (beep)

);

initial clk = 1'b0;

always # 10 clk = ~clk;

initial begin

rst_n = 1'b0;

# 200

@ (posedge clk);

# 2;

rst_n = 1'b1;

# 20000;

$stop;

end

endmodule

图12 :testbench代码

由于输出的频率都较低,所以仿真时间都很长。

将参数改小,也只是加快切换输出音符的频率。由于wave_gen模块和分频模块相同,故而不在验证。只看RTL视图中,分频数是不是正确即可。

图13 :RTL视图

在RTL视图中,也看到cnt每10个周期增长1,然后对应输出音符。音符得出频率,根据频率得出分频数。经过验证,数据都是正确的。

分配管脚,全编译形成下载文件,下板后就可以听到《世上只有妈妈好》的歌曲了。

通过更改speed_crtl中的控制音符前进的速度,可以控制播放的速度。如果将速度控制到1/2秒的话,那么听到的歌曲将会变慢。如果将速度控制到1/8秒的话,那么听到的歌曲将会变快。

设计者:郝旭帅         QQ:746833924     QQ交流群: 173560979

基于FPGA的音乐蜂鸣器设计的更多相关文章

  1. 基于FPGA的HDMI显示设计(三)

    上一篇:基于FPGA的VGA显示设计(二) 10月10日 ~ 20日期间实习,令我万万没想到的是实习题目是 “便携式高清电视显示屏测试系统原型设计” 也就是 “基于FPGA的视频显示”. 实习要求用 ...

  2. 基于FPGA的VGA显示设计(二)

    上一篇:基于FPGA的VGA显示设计(一)     参照 CrazyBingo 的 基于FPGA的VGA可移植模块终极设计代码  的工程代码风格,模块化处理了上一篇的代码,并增加了一点其它图形. 顶层 ...

  3. 基于FPGA的异步FIFO设计

    今天要介绍的异步FIFO,可以有不同的读写时钟,即不同的时钟域.由于异步FIFO没有外部地址端口,因此内部采用读写指针并顺序读写,即先写进FIFO的数据先读取(简称先进先出).这里的读写指针是异步的, ...

  4. 基于FPGA的VGA显示设计(一)

    前言 FPGA主要运用于芯片验证.通信.图像处理.显示VGA接口的显示器是最基本的要求了. 原理 首先需要了解 : (1)VGA接口协议:VGA端子_维基百科 .VGA视频传输标准_百度 引脚1 RE ...

  5. 优化基于FPGA的深度卷积神经网络的加速器设计

    英文论文链接:http://cadlab.cs.ucla.edu/~cong/slides/fpga2015_chen.pdf 翻译:卜居 转载请注明出处:http://blog.csdn.net/k ...

  6. 基于FPGA的图像去噪

    目录 结构图 其中FPGA 控制模块为核心,通过它实现视频图像数据的获取.缓存.处理和控制各模块间通讯[1].由CCD 相机对目标成像,高速图像数据由camera link 实时传输[2],经信号转换 ...

  7. 基于FPGA的DDS设计(一)

    最近在学习基于FPGA的DDS设计,借此机会把学习过程记录下来,当作自己的学习笔记也希望能够帮助到学习DDS的小伙伴. DDS(Direct Digital Synthesizer)直接数字合成器,这 ...

  8. 基于FPGA的XPT2046触摸控制器设计

    基于FPGA的XPT2046触摸控制器设计 小梅哥编写,未经许可,文章内容和所涉及代码不得用于其他商业销售的板卡 本实例所涉及代码均可通过向 xiaomeige_fpga@foxmail.com  发 ...

  9. 基于FPGA的VGA可移植模块终极设计【转】

    本文转载自:http://www.cnblogs.com/lueguo/p/3373643.html 略过天涯   基于FPGA的VGA可移植模块终极设计 一.VGA的诱惑 首先,VGA的驱动,这事, ...

  10. 基于FPGA的SPI FLASH控制器设计

    1.SPI FLASH的基本特征 本文实现用FPGA来设计SPI FLASH,FLASH型号为W25Q128BV.支持3种通信方式,SPI.Dual SPI和Quad SPI.FLASH的存储单元无法 ...

随机推荐

  1. 鸿蒙HarmonyOS实战-ArkTS语言(状态管理)

    前言 状态管理是指在应用程序中维护和更新应用程序状态的过程.在一个程序中,可能有很多不同的组件和模块,它们需要共享和相互作用的状态.如果没有一个明确的方式来管理这些状态,就会导致代码混乱.不易维护和难 ...

  2. .NET分布式Orleans - 2 - Grain的通信原理与定义

    Grain 是 Orleans 框架中的基本单元,代表了应用程序中的一个实体或者一个计算单元. 每个Silo都是一个独立的进程,Silo负责加载.管理和执行Grain实例,并处理来自客户端的请求以及与 ...

  3. -bash: jps:未找到命令 CentOS7

    yum install java-1.8.0-openjdk-devel.x86_64

  4. Python---time对象的使用获取时间

    https://www.jb51.net/article/49326.htm 1.time.time() 它返回当前时间的时间戳(1970纪元后经过的浮点秒数). 如果调用这个函数,如:  print ...

  5. Windows和Linux系统下的Conda环境迁移

    Motivation ​ 大家在学习Python的过程中,可能经常会遇到下面两种情况: 同一份代码,别人配置conda环境可以跑通,但你配置了N天,还不知道哪一步出现了差错,仍然跑不通代码,conda ...

  6. 学习 Tensorflow 的困境与解药

    我构建的预测模型 在过去的一段时间里我抓去了小宇宙内上万条播客节目的首日播放量的数据,并利用这些数据构建了一个用于预测播客节目播放量的模型.包含以下六个输入参数: 节目发布于一周中的哪一天 节目发布于 ...

  7. CH392作服务器TCP Server应用配置使用

    CH392工作在TCP Server模式时,参考手册说明需要打开监听Socket端口,也要设置数据连接Socket端口,注意数据连接Socket的源端口和监听Socket的源端口一致. 配置TCP S ...

  8. 使用Python的turtle模块绘制美丽的樱花树

    引言 Python的turtle模块是一个直观的图形化编程工具,让用户通过控制海龟在屏幕上的移动来绘制各种形状和图案.turtle模块的独特之处在于其简洁易懂的操作方式以及与用户的互动性.用户可以轻松 ...

  9. 【直播回顾】OpenHarmony知识赋能六期第三课—OpenHarmony智能家居项目之控制面板功能实现

    7月14日晚上19点,知识赋能第六期第三节直播 <OpenHarmony智能家居项目之控制面板功能实现> ,在OpenHarmony开发者成长计划社群内成功举行. 本次直播是"O ...

  10. Git 教程:解密 .gitignore 文件、合并分支、解决冲突、及 Git 帮助

    Git 帮助 如果你忘记了命令或命令的选项,你可以使用 Git 帮助. 在命令行中,有几种不同的使用帮助命令的方式: git command -help - 查看特定命令的所有可用选项 git hel ...