1、1318.5低音4349.2中音4698.5高音41391.1低音5392中音5784高音51568低音6440中音6880高音61760低音7493.9中音7987.8高音71975.5表2.1 简谱音名与频率的对应关系产生各音符所需的频率可用一分频器实现,由于各音符对应的频率多为非整数,而分频系数又不能为小数,故必须将计算得到的分频数四舍五入取整。若分频器时钟频率过低,则由于分频系数过小,四舍五入取整后的误差较大;若时钟频率过高,虽然误差变小,但分频数将变大。实际的设计应综合考虑两方面的因素,在尽量减小频率误差的前提下取合适的时钟频率。实际上,只要各个音符间的相对频率关系不变,演奏出的乐曲
2、听起来都不会走调。音符的持续时间须根据乐曲的速度及每个音符的节拍数来确定。因此,要控制音符的音长,就必须知道乐曲的速度和每个音符所对应的节拍数,本例所演奏的乐曲的最短的音符为四分音符,如果将全音符的持续时间设为1s的话,那么一拍所应该持续的时间为0.25秒,则只需要提供一个4HZ的时钟频率即可产生四分音符的时长。本例设计的音乐电子琴选取40MHZ的系统时钟频率。在数控分频器模块,首先对时钟频率进行40分频,得到1MHZ的输入频率,然后再次分频得到各音符的频率。由于数控分频器输出的波形是脉宽极窄的脉冲波,为了更好的驱动蜂鸣器发声,在到达蜂鸣器之前需要均衡占空比,从而生成各音符对应频率的对称方波输
3、出。这个过程实际上进行了一次二分频,频率变为原来的二分之一即0.5MHZ。因此,分频系数的计算可以按照下面的方法进行。以中音1为例,对应的频率值为5233Hz,它的分频系数应该为:至于其他音符,同样可由上式求出对应的分频系数,这样利用程序可以很轻松地得到相应的乐声。分频系数1911478170242515173791431359127631911362841014253956851 中音3 659.3 758 中音4 698.5 716 中音5 784 638 中音6 880 568 中音7 987.8 506表2.2 各音名对应的分频系数至于音长的控制,在自动演奏模块,每个乐曲的音符是按地址
4、存放的,播放乐曲时按4HZ的时钟频率依次读取简谱,每个音符持续时间为0.25秒。如果乐谱中某个音符为三拍音长,那又该如何控制呢?其实只要在3个连续地址存放该音符,这时就会发三个0.25秒的音长,即持续了三拍的时间,通过这样一个简单的操作就可以控制音长了。三、实验步骤1、设置端口1)输入端口CLK:40MHZ系统时钟输入端口。2)输出端口device:乐曲的声音输出端口,输出的是对应各音符频率的方波信号。2、设置模块1)自动演奏模块自动演奏模块可以自动播放电子琴内置乐曲,按节拍读取内置乐谱。将键盘输入的音符信号输出。因此,本模块是向Tone模块提供音符信息。首先,对40MHz系统时钟进行10M的
5、分频,得到4Hz的信号,这样一秒中就可以按照四拍进行。然后依照此频率进行地址累计。2)音频发生器模块根据自动演奏模块的信号输出,不同的信号被翻译为不同的频率。3)蜂鸣器驱动模块根据音频发生器发出音频的不同,蜂鸣器得到的驱动也不同。首先,对系统时钟进行40分频,再对1mhz的脉冲再次分频,得到所需要的音符频率,然后再进行2分频。四、实验代码library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;entity tone is port( index:
6、in std_logic_vector(15 downto 0); -音符输入信号 tone0: out integer range 0 to 2047 -音符的分频系数 );end tone;architecture behavioral of tone isbegin search :process(index) -此进程完成音符到音符的分频系数译码,音符的显示,高低音阶 begin case index is when 0000000000000001 = tone0=0; end case; end process;end behavioral;entity speaker is cl
7、k1: in std_logic; -系统时钟12mhz tone1: in integer range 0 to 2047; -音符分频系数 spks: out std_logic -驱动扬声器的音频信号end speaker;architecture behavioral of speaker issignal preclk, fullspks:std_logic; p1:process(clk1)-此进程对系统时钟进行16分频 variable count: integer range 0 to 16; if clk1event and clk1=1 then count:=count+
8、1; if count=8 then preclk=; elsif count=16 then0 count: end if; end if; end process p1; p2:process(preclk,tone1)-对0.75mhz的脉冲再次分频,得到所需要的音符频率 variable count11:integer range 0 to 2047; if preclkevent and preclk= then if count11tone1 then count11:=count11+1; fullspks else end process p2; p3:process(full
9、spks)-此进程对fullspks进行2分频 variable count2: std_logic: if fullspksevent and fullspks= count2:=not count2; if count2= spks end if; end process p3;entity laohu is clk:-系统时钟;键盘输入/自动演奏 tone_key_0: buffer std_logic_vector(15 downto 0)-音符信号输出end laohu;architecture behavioral of laohu issignal count0:integer
10、range 0 to 31;-changesignal clk2:process(clk) -对12mhz系统时钟进行3m的分频,得到4hz的信号clk2integer range 0 to 3000000; if clkevent and clk= count: if count=1500000 then clk2 elsif count=3000000 thenprocess(clk2)-此进程完成自动演奏部分乐曲的地址累加 if clk2event and clk2= if count0=29 then count0 tone_key_000000010_00000000 -2 when
11、 2 =00000100_00000000 -3 when 3 = when 4 = when 5 = when 6 = when 7 = when 8 = when 9 =00001000_00000000 -4 when 10 =00010000_00000000 -5 when 11 = when 12 = when 13 = when 14 = when 15 =00100000_00000000 -6 when 16 = when 17 = when 18 = when 19 = when 20 = when 21 = when 22 = when 23 = when 24 = wh
12、en 25 = when 26 = when 27 =00000000_00100000 -di6 when 28 = null; end case;entity beep0 isin std_logic; device:out std_logicend beep0;architecture behavioral of beep0 iscomponent laohu is out std_logic_vector(15 downto 0)-音符信号输出end component;component tone is-音符输入信号 out integer range 0 to 2047-音符的分频
13、系数component speaker is-系统时钟12mhz out std_logic-驱动扬声器的音频信号signal mid:std_logic_vector(15 downto 0);signal tones:integer; u0:laohu port map(clk,mid); u1:tone port map(mid,tones); u2:speaker port map(clk,tones,device);五、实验结果及其分析频率折算中,由于频率计数3不能是小数,采用了四舍五入的方法,所以得到的频率并不是十分精确的,但是不会影响结果。乐曲按照每秒钟四拍进行,循环地从事先编好的代码中翻译出频率来,所以能听到完整的乐曲。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1