驱动蜂鸣器实验
一、实验要求
完成驱动蜂鸣器实验
二、实验目的
1.
2.
3.
4. 学习Proteus软件的使用方法 学习Keil软件的使用方法 学习端口输出的使用方法 掌握延时程序的设计
三、实验说明
(条理清晰,含程序的一些功能分析计算)
分析系统要实现的功能,怎么设计实现方案,有哪些计算相关数据要计算,需要使用哪些什么特殊功能寄存器等,
四、硬件原理图及程序设计
(一)硬件原理图设计
在PROTEUS中截图过来,并有文字说明
(二)程序流程图设计
(三)程序设源代码
#include <reg51.h>
sbit buzzer=P3^7;
void delay(int);
void pulse_BZ(int,int,int);
main()
{
while(1)
{
pulse_BZ(100,1,1);
delay(1000);
}
}
void delay(int x)
{
int i, j;
for(i=0;i<x;i++)
for(j=0;j<60;j++);
}
void pulse_BZ(int count,int TH,int TL) {
int i;
for(i=0;i<count;i++)
{
buzzer=1;
delay(TH);
buzzer=0;
delay(TL);
}
} 将程序的源代码付上,主要句子和功能要有注释
五.实验总结
1、实验过程中遇到的问题及解决方法
2、体会
第二篇:vhdl实验报告--蜂鸣器
VHDL实验报告
一、实验目的
1、 掌握蜂鸣器的使用;
2、 通过复杂实验,进一步加深对VHDL语言的掌握程度。
二、实验原理
乐曲都是由一连串的音符组成,因此按照乐曲的乐谱依次输出这些音符所对应的频率,就可以在蜂鸣器上连续地发出各个音符的音调。而要准确地演奏出一首乐曲,仅仅让蜂鸣器能够发声是不够的,还必须准确地控制乐曲的节奏,即每个音符的持续时间。由此可见,乐曲中每个音符的发音频率及其持续的时间是乐曲能够连续演奏的两个关键因素。
乐曲的12平均率规定:每2个八度音(如简谱中的中音1与高音1)之间的频率相差1倍。在2个八度音之间,又可分为12个半音。另外,音符A(简谱中的低音6)的频率为440Hz,音符B到C之间、E到F之间为半音,其余为全音。由此可以计算出简谱中从低音l至高音1之间每个音符的频率,如表2.1所示。
表2.1 简谱音名与频率的对应关系
产生各音符所需的频率可用一分频器实现,由于各音符对应的频率多为非整数,而分频系数又不能为小数,故必须将计算得到的分频数四舍五入取整。若分频器时钟频率过低,则由于分频系数过小,四舍五入取整后的误差较大;若时钟频率过高,虽然误差变小,但分频数将变大。实际的设计应综合考虑两方面的因素,在尽量减小频率误差的前提下取合适的时钟频率。实际上,只要各个音符间的相对频率关系不变,演奏出的乐曲听起来都不会走调。
音符的持续时间须根据乐曲的速度及每个音符的节拍数来确定。因此,要控制音符的音长,就必须知道乐曲的速度和每个音符所对应的节拍数,本例所演奏的乐曲的最短的音符为四分音符,如果将全音符的持续时间设为1s的话,那么一拍所应该持续的时间为0.25秒,则只需要提供一个4HZ的时钟频率即可产生四分音符的时长。
本例设计的音乐电子琴选取12MHZ的系统时钟频率。在数控分频器模块,首先对时钟频率进行16分频,得到0.75MHZ的输入频率,然后再次分频得到各音符的频率。由于数控分频器输出的波形是脉宽极窄的脉冲波,为了更好的驱动蜂鸣器发声,在到达蜂鸣器之前需要均衡占空比,从而生成各音符对应频率的对称方波输出。这个过程实际上进行了一次二分频,频率变为原来的二分之一即0.375MHZ。
因此,分频系数的计算可以按照下面的方法进行。以中音1为例,对应的频率值为523.3Hz,它的分频系数应该为:
至于其他音符,同样可由上式求出对应的分频系数,这样利用程序可以很轻松地得到相应的乐声。
表2.2 各音名对应的分频系数
至于音长的控制,在自动演奏模块,每个乐曲的音符是按地址存放的,播放乐曲时按4HZ的时钟频率依次读取简谱,每个音符持续时间为0.25秒。如果乐谱中某个音符为三拍音长,那又该如何控制呢?其实只要在3个连续地址存放该音符,这时就会发三个0.25秒的音长,即持续了三拍的时间,通过这样一个简单的操作就可以控制音长了。
三、实验步骤
1、设置端口
1)输入端口
CLK:12MHZ系统时钟输入端口。
2)输出端口
device:乐曲的声音输出端口,输出的是对应各音符频率的方波信号。
2、设置模块
1)自动演奏模块
自动演奏模块可以自动播放电子琴内置乐曲,按节拍读取内置乐谱。将键盘输入的音符信号输出。因此,本模块是向Tone模块提供音符信息。
首先,对12MHz系统时钟进行3M的分频,得到4Hz的信号,这样一秒中就可以按照四拍进行。然后依照此频率进行地址累计。
2)音频发生器模块
根据自动演奏模块的信号输出,不同的信号被翻译为不同的频率。
3)蜂鸣器驱动模块
根据音频发生器发出音频的不同,蜂鸣器得到的驱动也不同。首先,对系统时钟进行16分频,再对0.75mhz的脉冲再次分频,得到所需要的音符频率,然后再进行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: in std_logic_vector(15 downto 0); --音符输入信号
tone0: out integer range 0 to 2047 --音符的分频系数
);
end tone;
architecture behavioral of tone is
begin
search :process(index) --此进程完成音符到音符的分频系数译码,音符的显示,高低音阶
begin
case index is
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;
when others => tone0<=0;
end case;
end process;
end behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity speaker is
port(
clk1: in std_logic; --系统时钟12mhz
tone1: in integer range 0 to 2047; --音符分频系数
spks: out std_logic --驱动扬声器的音频信号
);
end speaker;
architecture behavioral of speaker is
signal preclk, fullspks:std_logic;
begin
p1:process(clk1)--此进程对系统时钟进行16分频
variable count: integer range 0 to 16;
begin
if clk1'event and clk1='1' then count:=count+1;
if count=8 then
preclk<='1';
elsif count=16 then
preclk<='0';
count:=0;
end if;
end if;
end process p1;
p2:process(preclk,tone1)--对0.75mhz的脉冲再次分频,得到所需要的音符频率
variable count11:integer range 0 to 2047;
begin
if preclk'event and preclk='1' then
if count11<tone1 then
count11:=count11+1;
fullspks<='1';
else
count11:=0;
fullspks<='0';
end if;
end if;
end process p2;
p3:process(fullspks)--此进程对fullspks进行2分频
variable count2: std_logic:='0';
begin
if fullspks'event and fullspks='1' then
count2:=not count2;
if count2='1' then
spks<='1';
else
spks<='0';
end if;
end if;
end process p3;
end behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity laohu is
port(
clk: in std_logic;--系统时钟;键盘输入/自动演奏
tone_key_0: buffer std_logic_vector(15 downto 0)--音符信号输出
);
end laohu;
architecture behavioral of laohu is
signal count0:integer range 0 to 31;--change
signal clk2:std_logic;
begin
p1:process(clk) --对12mhz系统时钟进行3m的分频,得到4hz的信号clk2
variable count:integer range 0 to 3000000;
begin
if clk'event and clk='1' then
count:=count+1;
if count=1500000 then
clk2<='1';
elsif count=3000000 then
clk2<='0';
count:=0;
end if;
end if;
end process p1;
p2:process(clk2)--此进程完成自动演奏部分乐曲的地址累加
begin
if clk2'event and clk2='1' then
if count0=29 then
count0<=0;
else
count0<=count0+1;
end if;
end if;
end process p2;
p3:process(count0,tone_key_0)
begin
case count0 is--此case语句:存储自动演奏部分的乐曲
when 0 => tone_key_0<=b"00000001_00000000"; --1
when 1 => tone_key_0<=b"00000010_00000000"; --2
when 2 => tone_key_0<=b"00000100_00000000"; --3
when 3 => tone_key_0<=b"00000001_00000000"; --1
when 4 => tone_key_0<=b"00000001_00000000"; --1
when 5 => tone_key_0<=b"00000010_00000000"; --2
when 6 => tone_key_0<=b"00000100_00000000"; --3
when 7 => tone_key_0<=b"00000001_00000000"; --1
when 8 => tone_key_0<=b"00000100_00000000"; --3
when 9 => tone_key_0<=b"00001000_00000000"; --4
when 10 => tone_key_0<=b"00010000_00000000"; --5
when 11 => tone_key_0<=b"00000100_00000000"; --3
when 12 => tone_key_0<=b"00001000_00000000"; --4
when 13 => tone_key_0<=b"00010000_00000000"; --5
when 14 => tone_key_0<=b"00010000_00000000"; --5
when 15 => tone_key_0<=b"00100000_00000000"; --6
when 16 => tone_key_0<=b"00010000_00000000"; --5
when 17 => tone_key_0<=b"00001000_00000000"; --4
when 18 => tone_key_0<=b"00000100_00000000"; --3
when 19 => tone_key_0<=b"00000001_00000000"; --1
when 20 => tone_key_0<=b"00010000_00000000"; --5
when 21 => tone_key_0<=b"00100000_00000000"; --6
when 22 => tone_key_0<=b"00010000_00000000"; --5
when 23 => tone_key_0<=b"00001000_00000000"; --4
when 24 => tone_key_0<=b"00000100_00000000"; --3
when 25 => tone_key_0<=b"00000001_00000000"; --1
when 26 => tone_key_0<=b"00000100_00000000"; --3
when 27 => tone_key_0<=b"00000000_00100000"; --di6
when 28 => tone_key_0<=b"00000001_00000000"; --1
when others => null;
end case;
end process p3;
end behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity beep0 is
port(
clk:in std_logic;
device:out std_logic
);
end beep0;
architecture behavioral of beep0 is
component laohu is
port(
clk: in std_logic;--系统时钟;键盘输入/自动演奏
tone_key_0: out std_logic_vector(15 downto 0)--音符信号输出
);
end component;
component tone is
port(
index: in std_logic_vector(15 downto 0);--音符输入信号
tone0: out integer range 0 to 20##--音符的分频系数
);
end component;
component speaker is
port(
clk1: in std_logic;--系统时钟12mhz
tone1: in integer range 0 to 2047; --音符分频系数
spks: out std_logic--驱动扬声器的音频信号
);
end component;
signal mid:std_logic_vector(15 downto 0);
signal tones:integer;
begin
u0:laohu port map(clk,mid);
u1:tone port map(mid,tones);
u2:speaker port map(clk,tones,device);
end behavioral;
五、实验结果及其分析
频率折算中,由于频率计数3不能是小数,采用了四舍五入的方法,所以得到的频率并不是十分精确的,但是不会影响结果。
乐曲按照每秒钟四拍进行,循环地从事先编好的代码中翻译出频率来,所以能听到完整的乐曲。