vhdl实验报告蜂鸣器.docx
- 文档编号:5063796
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:11
- 大小:37.42KB
vhdl实验报告蜂鸣器.docx
《vhdl实验报告蜂鸣器.docx》由会员分享,可在线阅读,更多相关《vhdl实验报告蜂鸣器.docx(11页珍藏版)》请在冰豆网上搜索。
vhdl实验报告蜂鸣器
VHDL实验报告
一、实验目的
1、掌握蜂鸣器的使用;
2、通过复杂实验,进一步加深对VHDL语言的掌握程度。
二、实验原理
乐曲都是由一连串的音符组成,因此按照乐曲的乐谱依次输出这些音符所对应的频率,就可以在蜂鸣器上连续地发出各个音符的音调。
而要准确地演奏出一首乐曲,仅仅让蜂鸣器能够发声是不够的,还必须准确地控制乐曲的节奏,即每个音符的持续时间。
由此可见,乐曲中每个音符的发音频率及其持续的时间是乐曲能够连续演奏的两个关键因素。
乐曲的12平均率规定:
每2个八度音(如简谱中的中音1与高音1)之间的频率相差1倍。
在2个八度音之间,又可分为12个半音。
另外,音符A(简谱中的低音6)的频率为440Hz,音符B到C之间、E到F之间为半音,其余为全音。
由此可以计算出简谱中从低音l至高音1之间每个音符的频率,如表2.1所示。
音名
频率/Hz
音名
频率/Hz
音名
频率/Hz
低音1
261.6
中音1
523.3
高音1
1045.5
低音2
293.7
中音2
587.3
高音2
1174.7
低音3
329.6
中音3
659.3
高音3
1318.5
低音4
349.2
中音4
698.5
高音4
1391.1
低音5
392
中音5
784
高音5
1568
低音6
440
中音6
880
高音6
1760
低音7
493.9
中音7
987.8
高音7
1975.5
表2.1简谱音名与频率的对应关系
产生各音符所需的频率可用一分频器实现,由于各音符对应的频率多为非整数,而分频系数又不能为小数,故必须将计算得到的分频数四舍五入取整。
若分频器时钟频率过低,则由于分频系数过小,四舍五入取整后的误差较大;若时钟频率过高,虽然误差变小,但分频数将变大。
实际的设计应综合考虑两方面的因素,在尽量减小频率误差的前提下取合适的时钟频率。
实际上,只要各个音符间的相对频率关系不变,演奏出的乐曲听起来都不会走调。
音符的持续时间须根据乐曲的速度及每个音符的节拍数来确定。
因此,要控制音符的音长,就必须知道乐曲的速度和每个音符所对应的节拍数,本例所演奏的乐曲的最短的音符为四分音符,如果将全音符的持续时间设为1s的话,那么一拍所应该持续的时间为0.25秒,则只需要提供一个4HZ的时钟频率即可产生四分音符的时长。
本例设计的音乐电子琴选取40MHZ的系统时钟频率。
在数控分频器模块,首先对时钟频率进行40分频,得到1MHZ的输入频率,然后再次分频得到各音符的频率。
由于数控分频器输出的波形是脉宽极窄的脉冲波,为了更好的驱动蜂鸣器发声,在到达蜂鸣器之前需要均衡占空比,从而生成各音符对应频率的对称方波输出。
这个过程实际上进行了一次二分频,频率变为原来的二分之一即0.5MHZ。
因此,分频系数的计算可以按照下面的方法进行。
以中音1为例,对应的频率值为523.3Hz,它的分频系数应该为:
至于其他音符,同样可由上式求出对应的分频系数,这样利用程序可以很轻松地得到相应的乐声。
音名
频率/Hz
分频系数
音名
频率/Hz
分频系数
低音1
261.6
1911
高音1
1045.5
478
低音2
293.7
1702
高音2
1174.7
425
低音3
329.6
1517
高音3
1318.5
379
低音4
349.2
1431
高音4
1391.1
359
低音5
392
1276
高音5
1568
319
低音6
440
1136
高音6
1760
284
低音7
493.9
1014
高音7
1975.5
253
中音1
523.3
956
中音2
587.3
851
中音3659.3758中音4698.5716
中音5784638中音6880568
中音7987.8506
表2.2各音名对应的分频系数
至于音长的控制,在自动演奏模块,每个乐曲的音符是按地址存放的,播放乐曲时按4HZ的时钟频率依次读取简谱,每个音符持续时间为0.25秒。
如果乐谱中某个音符为三拍音长,那又该如何控制呢?
其实只要在3个连续地址存放该音符,这时就会发三个0.25秒的音长,即持续了三拍的时间,通过这样一个简单的操作就可以控制音长了。
三、实验步骤
1、设置端口
1)输入端口
CLK:
40MHZ系统时钟输入端口。
2)输出端口
device:
乐曲的声音输出端口,输出的是对应各音符频率的方波信号。
2、设置模块
1)自动演奏模块
自动演奏模块可以自动播放电子琴内置乐曲,按节拍读取内置乐谱。
将键盘输入的音符信号输出。
因此,本模块是向Tone模块提供音符信息。
首先,对40MHz系统时钟进行10M的分频,得到4Hz的信号,这样一秒中就可以按照四拍进行。
然后依照此频率进行地址累计。
2)音频发生器模块
根据自动演奏模块的信号输出,不同的信号被翻译为不同的频率。
3)蜂鸣器驱动模块
根据音频发生器发出音频的不同,蜂鸣器得到的驱动也不同。
首先,对系统时钟进行40分频,再对1mhz的脉冲再次分频,得到所需要的音符频率,然后再进行2分频。
四、实验代码
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitytoneis
port(
index:
instd_logic_vector(15downto0);--音符输入信号
tone0:
outintegerrange0to2047--音符的分频系数
);
endtone;
architecturebehavioraloftoneis
begin
search:
process(index)--此进程完成音符到音符的分频系数译码,音符的显示,高低音阶
begin
caseindexis
when"0000000000000001"=>tone0<=1433;
when"0000000000000010"=>tone0<=1277;
when"0000000000000100"=>tone0<=1138;
when"0000000000001000"=>tone0<=1074;
when"0000000000010000"=>tone0<=960;
when"0000000000100000"=>tone0<=853;
when"0000000001000000"=>tone0<=759;
when"0000000010000000"=>tone0<=716;
when"0000000100000000"=>tone0<=358;
when"0000001000000000"=>tone0<=319;
when"0000010000000000"=>tone0<=284;
when"0000100000000000"=>tone0<=268;
when"0001000000000000"=>tone0<=239;
when"0010000000000000"=>tone0<=213;
when"0100000000000000"=>tone0<=190;
when"1000000000000000"=>tone0<=638;
whenothers=>tone0<=0;
endcase;
endprocess;
endbehavioral;
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entityspeakeris
port(
clk1:
instd_logic;--系统时钟12mhz
tone1:
inintegerrange0to2047;--音符分频系数
spks:
outstd_logic--驱动扬声器的音频信号
);
endspeaker;
architecturebehavioralofspeakeris
signalpreclk,fullspks:
std_logic;
begin
p1:
process(clk1)--此进程对系统时钟进行16分频
variablecount:
integerrange0to16;
begin
ifclk1'eventandclk1='1'thencount:
=count+1;
ifcount=8then
preclk<='1';
elsifcount=16then
preclk<='0';
count:
=0;
endif;
endif;
endprocessp1;
p2:
process(preclk,tone1)--对0.75mhz的脉冲再次分频,得到所需要的音符频率
variablecount11:
integerrange0to2047;
begin
ifpreclk'eventandpreclk='1'then
ifcount11 count11: =count11+1; fullspks<='1'; else count11: =0; fullspks<='0'; endif; endif; endprocessp2; p3: process(fullspks)--此进程对fullspks进行2分频 variablecount2: std_logic: ='0'; begin iffullspks'eventandfullspks='1'then count2: =notcount2; ifcount2='1'then spks<='1'; else spks<='0'; endif; endif; endprocessp3; endbehavioral; libraryieee; useieee.std_logic_1164.all; useieee.std_logic_arith.all; useieee.std_logic_unsigned.all; entitylaohuis port( clk: instd_logic;--系统时钟;键盘输入/自动演奏 tone_key_0: bufferstd_logic_vector(15downto0)--音符信号输出 ); endlaohu; architecturebehavioraloflaohuis signalcount0: integerrange0to31;--change signalclk2: std_logic; begin p1: process(clk)--对12mhz系统时钟进行3m的分频,得到4hz的信号clk2 variablecount: integerrange0to3000000; begin ifclk'eventandclk='1'then count: =count+1; ifcount=1500000then clk2<='1'; elsifcount=3000000then clk2<='0'; count: =0; endif; endif; endprocessp1; p2: process(clk2)--此进程完成自动演奏部分乐曲的地址累加 begin ifclk2'eventandclk2='1'then ifcount0=29then count0<=0; else count0<=count0+1; endif; endif; endprocessp2; p3: process(count0,tone_key_0) begin casecount0is--此case语句: 存储自动演奏部分的乐曲 when0=>tone_key_0<=b"00000001_00000000";--1 when1=>tone_key_0<=b"00000010_00000000";--2 when2=>tone_key_0<=b"00000100_00000000";--3 when3=>tone_key_0<=b"00000001_00000000";--1 when4=>tone_key_0<=b"00000001_00000000";--1 when5=>tone_key_0<=b"00000010_00000000";--2 when6=>tone_key_0<=b"00000100_00000000";--3 when7=>tone_key_0<=b"00000001_00000000";--1 when8=>tone_key_0<=b"00000100_00000000";--3 when9=>tone_key_0<=b"00001000_00000000";--4 when10=>tone_key_0<=b"00010000_00000000";--5 when11=>tone_key_0<=b"00000100_00000000";--3 when12=>tone_key_0<=b"00001000_00000000";--4 when13=>tone_key_0<=b"00010000_00000000";--5 when14=>tone_key_0<=b"00010000_00000000";--5 when15=>tone_key_0<=b"00100000_00000000";--6 when16=>tone_key_0<=b"00010000_00000000";--5 when17=>tone_key_0<=b"00001000_00000000";--4 when18=>tone_key_0<=b"00000100_00000000";--3 when19=>tone_key_0<=b"00000001_00000000";--1 when20=>tone_key_0<=b"00010000_00000000";--5 when21=>tone_key_0<=b"00100000_00000000";--6 when22=>tone_key_0<=b"00010000_00000000";--5 when23=>tone_key_0<=b"00001000_00000000";--4 when24=>tone_key_0<=b"00000100_00000000";--3 when25=>tone_key_0<=b"00000001_00000000";--1 when26=>tone_key_0<=b"00000100_00000000";--3 when27=>tone_key_0<=b"00000000_00100000";--di6 when28=>tone_key_0<=b"00000001_00000000";--1 whenothers=>null; endcase; endprocessp3; endbehavioral; libraryieee; useieee.std_logic_1164.all; useieee.std_logic_arith.all; useieee.std_logic_unsigned.all; entitybeep0is port( clk: instd_logic; device: outstd_logic ); endbeep0; architecturebehavioralofbeep0is componentlaohuis port( clk: instd_logic;--系统时钟;键盘输入/自动演奏 tone_key_0: outstd_logic_vector(15downto0)--音符信号输出 ); endcomponent; componenttoneis port( index: instd_logic_vector(15downto0);--音符输入信号 tone0: outintegerrange0to2047--音符的分频系数 ); endcomponent; componentspeakeris port( clk1: instd_logic;--系统时钟12mhz tone1: inintegerrange0to2047;--音符分频系数 spks: outstd_logic--驱动扬声器的音频信号 ); endcomponent; signalmid: std_logic_vector(15downto0); signaltones: integer; begin u0: laohuportmap(clk,mid); u1: toneportmap(mid,tones); u2: speakerportmap(clk,tones,device); endbehavioral; 五、实验结果及其分析 频率折算中,由于频率计数3不能是小数,采用了四舍五入的方法,所以得到的频率并不是十分精确的,但是不会影响结果。 乐曲按照每秒钟四拍进行,循环地从事先编好的代码中翻译出频率来,所以能听到完整的乐曲。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- vhdl 实验 报告 蜂鸣器