1、 基于PROTEUS完成硬件电路的设计,基于AT89S51单片机完成控制显示程序的设计。 2、 独立完成设计工作,重点要求创新,用不同的方式实现基于单片机的电子琴的设计工作。 3、 完成自己的PPT制作工作,独立答辩。 4、 提交设计报告。
二、题目分析本次设计是利用单片机产生不同频率来达到音阶的控制,实现类似电子琴的功能。通过控制单片机频率的变化获得我们要求的音阶,实现高、中、低共21个音符的发音。 本设计在音阶播放的基础上,设立以下创新点: 1、 设立为双重模式,分别为弹奏模式和播放模式,通过按键进行切换,并通过LED显示当前模式。 2、 增加可视化LED显示功能,显示当前声音为何种高中低音符。 3、 可以随意的改写播放模式中的曲目,弹奏想要表达的音乐。 4、 能自动播放程序中编排的多首音乐,通过按键切换音乐内容。 5、 系统运行稳定,硬件电路简单,软件功能完善。 本设计应用单片机控制技术,采用AT89C51单片机为核心,根据本学期所学的单片机知识结合设计了一套单片机控制的电子琴系统。 电子琴是现代电子科技与音乐结合的产物,是一种新型的键盘乐器,它在现代音乐扮演着重要的角色。
三、总体方案单片机音乐播放器控制系统结构简单,环节较少,因此,单片机音乐播放器除了播放音乐有按键外,其余的硬件组成大体相同。在实际电路中,对于单片机音乐播放器声音的读出除了蜂鸣器以外,还要配置合适的放大器播放出响亮的声音。 本次课程设计总体采用软件控制硬件的方式,用Keil软件编写相应C语言程序用于驱动和控制芯片的工作,同时应用Proteus仿真软件搭建仿真电路完成整体电路仿真。
四、 系统硬件设计 4.1总体设计框图电路总体以AT89C51单片机为核心,由电源电路进行驱动,键盘电路进行控制,当按下键盘控制,单片机根据当前状态控制蜂鸣器发出声音,按下复位键后恢复初始状态。
图 1 总体设计框图 4.2总体电路图 2 总体电路图 4.3 局部电路 4.3.1 晶振电路
晶振电路主要用于产生12M 的晶振,给单片机提供工作信号脉冲。如图所示,将两个电容C1、C2串联在AT89C51的18和19端口即XTAL1和XTAL2两个端口,再并联一个晶振器(如图中Y1),最后整体接地,构成晶振电路。
图 3 晶振电路 4.3.2复位电路将如图所示电路接入AT89C51的9号端口RST端口,用于总电路的复位。
图 4 复位电路 4.3.3按键电路
用独立式键盘的7个按键分别对应相应的音符,当按下某一个按键时,产生一个相应音符,操作者按一定的节奏、规律进行输入时,信号经过单片机处理,然后经音频放大后经扬声器输出音频信号,产生乐曲。
图 5 音符按键电路选择控制功能采用四个按键控制,分别为“功能切换”、“高音”、“中音”、“低音”。其中K1按键接入P3.2,K2按键接入P3.3,K3按键接入P3.4,K4按键接入P3.5。
图 6控制按键电路 4.3.4播放电路本次采用无源蜂鸣器SPEAKER来音乐的读出,只需要将蜂鸣器一端接入P2.2另一端接地即可。
图 7 播放电路 4.3.5当前模式电路通过控制LED灯的亮灭,观察当前处于何种状态。
图 8 当前模式电路 4.3.6数码管显示电路 图 9 数码管显示电路 图 10数码管显示配套的位移缓存器74HC595是一个8位串行输入、平行输出的位移缓存器。平行输出是在12脚STCP的上升沿时,8位位移缓存器的数据存人到8位平行输出缓存器。当13脚串行数据输人端OE的控制信号为低使能时,平行输出端的输出值等于平行输出缓存器所存储的值。具有锁存功能。 OE置低电平,MR置高电平,在正常使用时STCP为低电平, OE为低电平。从DS每输入一位数据,串行输入时钟SHCP上升沿有效一次,直到八位数据输入完毕,输出时钟STCP上升沿有效一次,此时,输入的数据就被送到了输出端,数码管将接收数据显示出来。 LED 灯的显示原理:通过同名管脚上所加电平的高低来控制发光二极管是否点亮而显示不同的字形,全亮显示为8,采用共阴极连接驱动代码,代码表如下表1所示。
表1:驱动代码表 五、 各部分定性说明以及定量计算 5.1单片机发声概述一般来说,单片机不像其他专业乐器那样能奏出多种音色的声音,即不包含相应幅度的谐振频率。单片机演奏的音乐基本都是单音频率。因此单片机演奏音乐比较简单,只需能清楚“音调”和“节拍”两个概念即可。音调表示一个音符唱多高的频率。节拍表示一个音符唱多长的时间。知道了一个音符的频率后,便可以让单片机发出相应频率的振荡信号,从而产生相应的音符声音。 通过单片机的定时器进行定时中断,在中断服务程序中将单片机上完结单片机IO口来回置高电平或者是低电平的,从而让扬声器发出声音。通过节拍计算出每个音符所需要的时间,采用循环延时的方法来实现控制一个音符唱多长的时间,从而构成一首完整的音乐。 音调主要由声音的频率决定。对一定强度的纯音,音调随频率的升降而升降;对一定顿率的纯音、低频纯音的音调随响度增加而下降,高频纯音的音调却随响度增加而上升。 音调的高低还与发声体的结构有关,因为发声体的结构影响了声音的顿率。大体上,2000 赫兹以下的低频纯音的音调随响度的增加而下降,3000赫兹以上高频纯音的音调随响度的增加而上升。 在音乐中音符1与音符2,音符2与音符3……等等之间正好相差一个倍频程,在音乐学中称它相差一个八度音。在一个八度内,有12个半音。由于人耳的听觉效果,这12个音阶的分度基本上是以对数的关系来划分的。只要知道12个音符的音高,也就是其基本频率,就可以根据音符之间的倍频关系得到其他音符的基本音调频率。 以标准高音A的频率F=440HZ,其对应的周期为: T=1/F=1/440=2272us 因此需要在单片机IO端口输出周期为T=2272us的方波脉冲,也就是 t=T/2=2272/2=1136us 也就是说,单片机上定时器的中断出发时间为1136us。如果单片机采用定时器为工作方式1,它以振荡器的十二分频信号为计数脉冲。设外接晶振的振荡器频率为f,则定时器的预置初始值有以下公式来确定: Temp=65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC); TH=Temp/256; TL=Temp%256;
5.2音乐的产生一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器TO来产生这样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系设置正确即可。 若要产生音频脉冲,只要算出某一音频的周期,再将此周期除以2,即为半周期的时间。利用定时器计时半周期时间,每当计时终止后就将P1.0反相,然后重复计时再反相。就可在P1.0引脚上得到此频率的脉冲。 利用AT89C51的内部定时器使其工作计数器模式(MODE1)下,改变计数值TH0及 TL0以产生不同频率的方法产生不同音阶。 计数脉冲值与频率的关系式是: N = fi÷2÷fr 式中,N是计数值;fi是机器频率(晶体振荡器为12MHz时,其频率为1MHz);fr是想要要产生的频率。 其计数初值T的求法如下: T = 65536-N = 65536-fi÷2÷fr 例如:设K=65536,f=1MHz,求低音DO(261Hz)、中音DO (523Hz)、高音DO (1046Hz)的计数值。 T = 65536—N = 65536—fi÷2÷fr = 65536—1000000÷2÷fr = 65536—500000/fr 低音DO的T=65536—500000/262=63627; 中音DO的T=65536—500000/523=64580; 高音DO的T=65536-500000/1046=65059; 单片机12MHZ晶振,高中低音符与计数TO相关的计数值如表1所示
表2:音符频率表程序中的全局变量FREQH 和 FREQL就是音符频率表,分别为数据的高8位和低8位,如下: //音阶频率表 高八位
uchar code table2[]={ 0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,//中音的高8位0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC, //低音的高8位0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,//高音的高8位 };//音阶频率表 低八位
uchar code table3[]={0x8E,0xED,0x44,0x6B,0xB4,0xF4,0x2D, //中音的低8位0x21,0xDB,0x87,0xD7,0x68,0xE8,0x5B, //低音的低8位0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16, //高音的低8位};table2[]和 table3[]中分别为数据的高8位和低8位,分别用来初始化THO、TLO。 音乐的音拍,一个节拍为单位(C调)(如表2所示)
六、 系统软件设计 5.1软件部分解析为了实现本次课程设计的功能,可以选择用C语言或者汇编语言来编写相应程序,但是由于汇编语言能实现功能较少,且编写复杂,而本次课程设计涉及的软件部分又较为繁琐,故采用相对来说更加便捷、清晰的C语言来编写。 本次设计大体功能共分为弹奏模式和播放模式。弹奏模式可以实现高、中、低共21个音符的发音,播放模式可以自动播放预先写入程序的音乐曲目。 本次软件部分可大致分为以下部分: 1 主函数 2 数据定义 3 初始化子函数 4 延时子函数 5 数码管显示子函数 6 高低音选择子函数 7 播放音乐子函数 8 演奏模式子函数
5.2 程序流程框图设计 图 11 程序流程框图 5.3主要模块代码分析 5.3.1 主函数 //主函数void main(){init();while(1){if(flag==0)display_music();elsedisplay_play();}} 5.3.2 延时子函数 //延时子函数void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=340;y>0;y--);} 5.3.3 初始化子函数 //初始化子函数void init(){beep=0;D1=1;D2=0;EA=1;//开总中断TCON=0x01;//外部中断0设置为边沿触发EX0=1;//开外部中断0ET0=1;ET1=1;TMOD=0x11;//定时器0,1工作在定时状态,均为方式1} 5.3.4 数码管显示子函数//数码管显示子函数
void display1(){in(table1[aa]); //再传段码out();W1=0;;delay(1); //延迟时间2ms以内W1=1;in(table1[cc+1]); //再传段码out();W2=0;delay(1); //延迟时间2ms以内W2=1; } 5.4.5 高低音选择子函数 //高低音选择子函数void yinjie(){if(k10==0){delay(5);if(k10==0){ aa=10;bb=0;//返回10为seg[10]显示C}}if(k9==0){delay(5);if(k9==0){aa=11;bb=1;//返回11为seg[11]显示L}}if(k11==0){delay(5);if(k11==0){aa=12;bb=2;//返回12为seg[12]显示H}}if(aa==0){aa=13;}} 5.5.6 播放音乐子函数 //播放音乐子函数void display_music(){TH0=table2[table4[i]-1];TL0=table3[table4[i]-1];while(flag==0){if(i