基于STC89C52的简易电子琴课程设计报告.docx
《基于STC89C52的简易电子琴课程设计报告.docx》由会员分享,可在线阅读,更多相关《基于STC89C52的简易电子琴课程设计报告.docx(25页珍藏版)》请在冰豆网上搜索。
基于STC89C52的简易电子琴课程设计报告
课程设计(报告)
题目基于STC89C52单片机的简易电子琴
学院名称
指导教师
职称
班级
学号
学生姓名
2011年6月12日
摘要:
本课程设计简易电子琴的制作基于STC89C52单片机。
利用定时器中断产生不同频率来实现不同音阶,用键盘扫描实现矩阵琴键的识别。
音频处理部分采用LM386进行信号放大,通过蜂鸣器发音。
该简易电子琴可以实现用矩阵琴键弹奏乐曲和播放一段示例音乐的功能。
关键字简易电子琴STC89C52LM386矩阵键盘
Abstract:
TheelectronicorganinthispaperisbasedononeSingalChipMicro-Computer.Witnthetimerinterrupt,itachievesdifferentscalesatdifferentfrequenciesandachievesidentificationofthematrixkeyboardkeysbyscaning.Inaudioprocessingpart,LM386isusedtoamplificatthesignal,andsoundingbybuzzer.Thesimpleelectronicorgancanplaymusicwiththematrixkeyboardandplayasampleofmusic.
Keywords:
simpleelectronicorgan;STC89C52;LM386;matrixkeyboard
引言
电子琴是使用现代科技实现传统器乐功能的典范。
目前各种电子琴产品,已经完全可以满足音乐教学与演奏的需要。
而在玩具市场上,也有各种玩具电子琴、玩具音乐盒等产品,这些产品原理简单,操作方便。
本课程设计制作的简易电子琴便与儿童玩具电子琴相似。
设计方案论证
1、按键模块方案选择
使用简易电子琴弹奏音乐时,需要中音区的8个音阶和低音与高音区的一部分音阶。
独立式按键占用的I/O口太多,而使用4*4矩阵键盘可以仅用一个四根行输出线和四根列输入线,同时可以弹奏低音3至高音5之间的音阶,已完全满足简单的弹奏需要。
2、音频处理模块方案选择
本设计靠蜂鸣器最终发出声音。
由于单片机驱动能力不够,在处理音符信号时,需加功率放大装置。
采用三极管:
驱动电路结构简单,成本低。
使用LM386:
LM386是美国国家半导体公司生产的音频功率放大器,主要应用于低电压消费类产品。
为保证声音效果,本设计使用LM386作放大器件。
硬件部分
1、系统结构图
硬件部分
系统结构图
图1系统结构图
实现功能:
Switch开关按下后播放示例音乐《樱花》;switch开关按起后为弹奏模式,按下不同的按钮开关发出不同的音阶。
控制模块
2.1STC89C52简介
功能特性:
STC89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
AT89S52具有以下标准功能:
8k字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。
另外,AT89S52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。
空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。
掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
8位微控制器8K字节在系统可编程FlashAT89S52。
图2STC89C52引脚图
主要功能特性
与MCS-51单片机产品兼容8K字节在系统可编程Flash存储器
1000次擦写周期全静态操作:
0Hz~33Hz
三级加密程序存储器32个可编程I/O口线
三个16位定时器/计数器八个中断源全双工UART串行通道、低功耗空闲和掉电模式
掉电后中断可唤醒看门狗定时器双数据指针掉电标识符
2.2音频处理模块
2.2.1LM386简介
LM386是美国国家半导体公司生产的音频功率放大器,主要应用于低电压消费类产品。
LM386特性:
静态功耗低,约为4mA,可用于电池供电;工作电压范围宽,4V-12V或5V-18V;外围元件少;电压增益可调,20-200;低失真度。
LM386是一种音频集成功放,具有自身功耗低、电压增益可调整、电源电压范围大、外接元件少和总谐波失真小等优点,广泛应用于录音机和收音机之中。
图3LM386内部电路原理图
LM386内部电路原理图如图1-3所示。
与通用型集成运放相类似,它是一个三级放大电路.第一级为差分放大电路,T1和T3、T2和T4分别构成复合管,作为差分放大电路的放大管;T5和T6组成镜像电流源作为T1和T2的有源负载;T3和T4信号从管的基极输入,从T2管的集电极输出,为双端输入单端输出差分电路。
使用镜像电流源作为差分放大电路有源负载,可使单端输出电路的增益近似等于双端输出电容的增益
第二级为共射放大电路,T7为放大管,恒流源作有源负载,以增大放大倍数。
第三级中的T8和T9管复合成PNP型管,与NPN型管T10构成准互补输出级。
二极管D1和D2为输出级提供合适的偏置电压,可以消除交越失真。
引脚2为反相输入端,引脚3为同相输入端。
电路由单电源供电,故为OTL电路。
输出端(引脚5)应外接输出电容后再接负载。
电阻R7从输出端连接到T2的发射极,形成反馈通路,并与R5和R6构成反馈网络,从而引入了深度电压串联负反馈,使整个电路具有稳定的电压增益。
LM386的封装形式有塑封8引线双列直插式和贴片式。
图4LM386的封装形式
电压增益内部设置固定为20倍。
如果在①脚与⑧脚外接电容器,可增加到200倍,外围元件少效率高。
在音响要求不高的设备中得到广泛运用1、R3和R18是用来分压的。
因为单片机输出电平是TTL电平,电压太高,所以通过两个电阻分压。
2、从VOUT到LS1接电容C17是输出电容,用来隔直流。
如果不加,很易烧坏喇叭3、R19不是单独用的,它与C18组成高频滤波,滤除高频信号。
5、VS是电源,两个并联电容是滤波用的。
图5LM386应用电路图
2.2.3蜂鸣器
2.2.3.1不同蜂鸣器原理
蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
压电式蜂鸣器,用的是压电材料,即当受到外力导致压电材料发生形变时压电材料会产生电荷。
同样,当通电时压电材料会发生形变。
电磁式蜂鸣器,主要是利用通电导体会产生磁场的特性,用一个固定的永久磁铁与通电导体产生磁力推动固定在线圈上的鼓膜。
由于2种蜂鸣器发音原理不同,压电式结构简单耐用但音调单一音色差,适用于报警器等设备。
而电磁式由于音色好,所以多用于语音、音乐等设备。
蜂鸣器的电路图形符号蜂鸣器在电路中用字母“H”或“HA”(旧标准用“FM”、“LB”、“JD”等)表示。
2.2.3.2有源蜂鸣器与无源蜂鸣器
这里的“源”不是指电源。
而是指震荡源。
也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫。
而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。
必须用2K~5K的方波去驱动它。
有源蜂鸣器往往比无源的贵,就是因为里面多个震荡电路。
无源蜂鸣器的优点是:
便宜;声音频率可控,可以做出“多来米发索拉西”的效果;在一些特例中,可以和LED复用一个控制口。
有源蜂鸣器的优点是:
程序控制方便。
软件部分
1音乐产生原理
一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样方波频率信号,因此,只需将一首歌的音阶和频率相对应即可。
2音阶产生方法
若要产生音频脉冲,只要算出某一音频的周期(1/频率),再将此周期除以2,即为半周期的时间。
利用定时器计时半周期时间,每当计时终止后就将P2.4反相,然后重复计时再反相。
就可在P2.4引脚上得到此频率的脉冲。
利用STC89C52的内部定时器使其工作计数器模式(MODE1)下,改变计数值TH0及TL0以产生不同频率的方法产生不同音阶,例如,频率为523Hz,其周期T=1/523=1912μs,因此只要令计数器计时956μs/1μs=956,每计数956次时将I/O反相,就可得到中音DO(523Hz)。
计数脉冲值与频率的关系式(如式2-1所示)是:
N=fi÷2÷fr
式中,N是计数值;fi是机器频率(晶体振荡器为12MHz时,其频率为1MHz);fr是想要产生的频率。
其计数初值T的求法如下:
T=65536-N=65536-fi÷2÷fr
表1音符频率与计数初值的对应关系表
音符
频率(HZ)
简谱码(T值)
音符
频率(HZ)
简谱码(T值)
低1 DO
262
63628
#4FA#
740
64860
#1 DO#
277
63731
中5SO
784
64898
低2 RE
294
63835
#5SO#
831
64934
#2RE#
311
63928
中6LA
880
64968
低3M
330
64021
#6
932
64994
低4FA
349
64103
中7SI
988
65030
#4FA#
370
64185
高1DO
1046
65058
低5SO
392
64260
#1DO#
1109
65085
#5SO#
415
64331
高2RE
1175
65110
低6LA
440
64400
#2RE#
1245
65134
#6
466
64463
高3M
1318
65157
低7SI
494
64524
高4FA
1397
65178
中1DO
523
64580
#4FA#
1480
65198
#1DO#
554
64633
高5SO
1568
65217
中2RE
587
64684
#5SO#
1661
65235
#2RE#
622
64732
高6LA
1760
65252
中3M
659
64777
#6
1865
65268
中4FA
698
64820
高7SI
1967
65283
3音乐的节拍
在弹奏状态下节拍由操作者控制,而在播放示例音乐时需要程序控制其节拍。
音乐的音拍即单位时间,对于不同的曲调可以用单片机的另外一个定时/计数器来完成。
而在此处采用的方法是利用延时函数确定每个音的长短(即节拍),编程时在设置音阶时还要对其设置节拍。
4矩阵键盘识别
琴键处理程序,根据检测到得按键值,查询音律表,给计时器赋值,发出相应频率的声音。
对音调的控制:
根据不同的按键,对定时器T0送入不同的初值,调节T0的溢出时间,这样就可以输出不同音调频率的方波。
不同音调下各个音阶的定时器。
4.1去抖动:
每个按键在按下或松开时,都会产生短时间的抖动。
抖动的持续时间与键的质量相关,一般为5—20mm。
所谓抖动是指在识别被按键是必须避开抖动状态,只有处在稳定接通或稳定断开状态才能保证识别正确无误。
在程序中通过设置空循环来实现。
4.2被按键识别
采用行扫描法,该方法在微机系统中被广泛使用。
由程序对键盘逐行扫描,通过检测到的列输出状态来确定闭合键,为此,需要设置输出口为P3.0——P3.3,输入口为P3.4——P3.7。
4.3键码产生
为了从键的行列坐标编码得到反映键功能的键码,一般在内存区中建立一个键盘编码表,通过查表获得被按键的键码。
图6产生音阶的定时器中断子程序流程图
图7按键识别程序流程图
程序调试与仿真
1使用Keil软件对程序进行调试,并生成hex文件。
弄懂参考程序后,自己编了一段樱花音乐。
经Keil编译连接,程序调试无误。
2使用proteus进行仿真
将Keil生成的dianziqin.hex文件加到单片机上,启动仿真。
可以很好地实现播放与弹奏功能。
需要说明的是,仿真只是在原理方面的验证,因而本仿真中蜂鸣器直接接到P2.4,在实际中还要有音频放大器件。
图8proteus仿真原理图
电路板的制作与调试
图9简易电子琴电路原理图
图10电子琴PCB电路
实际电路调试
第一次上电后蜂鸣器不响。
后来发现当把隔直电容220uF短路后,蜂鸣器响了,虽然能听出音乐和按键音,但一直有一个很大的声响。
经过一番分析,认为由于蜂鸣器发出的声音频率较低,隔直电容显得过大。
又换了几个容量较小的隔直电容,仍不出声,于是放弃隔直电容,而直接用一个10K电阻替代。
再次测试后,发现效果好得多。
可见,加了电阻可起到削弱直流分量的作用,因而噪声小得多,而频率较低的交流也影响不大。
课程设计心得体会
实践出真知。
单片机是应用性很强的一本学科。
仅有课堂的理论学习和次数有限的实验是远远不够的,必须自己动手做出实物来。
本次课程设计便提供了一个很好地机会,理论联系实际,在实际动手过程中巩固知识、积累经验。
应当说本人较好地珍惜了此次机会。
最初选题时,老师给了我们充分发挥积极主动性的空间,让大家结合自身实际情况自定课题。
本人由于爱好音乐,因而对基于单片机的简易电子琴产生了浓厚的兴趣。
因为有兴趣,所以整个课程设计过程中乐此不疲。
尤其是在做软件部分时,在弄懂了参考程序后,又将原先的示例音乐换掉,自己编写了一段《樱花》,结果非常成功。
在此过程中,要全面考虑音阶、节拍,当然,这是本人的特长。
能将自己的特长与所学的专业结合起来,是非常愉悦的。
功夫在诗外。
本课程设计真正实施起来后,需要的知识不仅仅是理论课学习的书本知识,还需要许多软件的应用技能及电路板制作的知识与经验。
以本次课程设计为契机,本人学了许多新东西。
首先,本设计采用C语言,而不是课堂上一直学习的汇编语言。
这是考虑到C语言思路更清晰,更简明,而且也是以后嵌入式学习的基础,因而查找了KeilCx51的教程,最终弄懂了参考程序并作出了有效的改动。
其次,为了检验对程序的理解,需要仿真,因而又自学了Keil和proteus。
当程序编译连接无误时,当仿真电路能够发出按键音和播放音乐时,很有成就感。
本次课程设计也是对protel、电路板制作和调试的巩固和提高。
这期间得到了实验室同学的热心帮助,从中增长了许多电路板制作与调试的经验知识。
当然,本次课程设计也有遗憾和不足之处。
如,为了省去打太多过孔的麻烦,要在电路板正面置焊点。
因而做按键开关的封装时想把引脚距离拉开以便于焊接,但间距过大,以致实际制作过程中按钮开关引脚很难插。
还有最终蜂鸣器仍存在噪音,使得一些特定频率的按键音被掩盖。
总的来说,本次课程设计获益匪浅。
感谢老师,感谢对本人提供过热心帮助的同学们!
参考文献
【1】李广弟朱月秀冷祖祁.单片机基础.北京航空航天大学出版社
【2】马忠梅籍顺心张凯等.单片机的C语言应用程序设计(第四版).北京航空航天大学出版社
附录
附录一:
程序清单
#include
#defineucharunsignedchar
#defineuintunsignedint
uintkey,i,j,time,m,k;
uchartemp;
ucharSTH0,STL0,STH1,STL1;
sbitsw=P2^7;
sbitspeaker=P2^4;
sbitP37=P3^7;
sbitP36=P3^6;
sbitP35=P3^5;
sbitP34=P3^4;
//樱花数据表
codeunsignedcharsszymmh[]={6,2,2,6,2,2,7,2,4,6,2,2,6,2,2,7,2,4,
6,2,2,7,2,2,1,3,2,7,2,2,6,2,2,7,2,1,6,2,1,4,2,4,
3,2,2,1,2,2,3,2,2,4,2,2,3,2,2,3,2,1,1,2,1,7,1,4,0,0,0
};
//音阶频率表高八位
codeunsignedcharFREQH[]={
0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC,//1,2,3,4,5,6,7,8,i
0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
};
//音阶频率表低八位
codeunsignedcharFREQL[]={
0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F,//1,2,3,4,5,6,7,8,i
0xEE,0x44,0x6B,0xB4,0xF4,0x2D,
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
};
unsignedintcodetab[]={64021,64260,64400,64524,64580,64684,64777,
64820,64898,64968,65030,65058,65110,65157,65178,65217};
voidkey_music()
{
P3=0xff;
P34=0;
temp=P3;
temp=temp&0x0f;
if(temp!
=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp&0x0f;
if(temp!
=0x0f)
{
temp=P3;
temp=temp&0x0f;
switch(temp)
{
case0x0e:
key=0;
break;
case0x0d:
key=1;
break;
case0x0b:
key=2;
break;
case0x07:
key=3;
break;
}
speaker=~speaker;
STH1=tab[key]/256;
STL1=tab[key]%256;
TR0=1;
temp=P3;
temp=temp&0x0f;
while(temp!
=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
TR0=0;
}
}
P3=0xff;
P35=0;
temp=P3;
temp=temp&0x0f;
if(temp!
=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp&0x0f;
if(temp!
=0x0f)
{
temp=P3;
temp=temp&0x0f;
switch(temp)
{
case0x0e:
key=4;
break;
case0x0d:
key=5;
break;
case0x0b:
key=6;
break;
case0x07:
key=7;
break;
}
speaker=~speaker;
STH1=tab[key]/256;
STL1=tab[key]%256;
TR0=1;
temp=P3;
temp=temp&0x0f;
while(temp!
=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
TR0=0;
}
}
P3=0xff;
P36=0;
temp=P3;
temp=temp&0x0f;
if(temp!
=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp&0x0f;
if(temp!
=0x0f)
{
temp=P3;
temp=temp&0x0f;
switch(temp)
{
case0x0e:
key=8;
break;
case0x0d:
key=9;
break;
case0x0b:
key=10;
break;
case0x07:
key=11;
break;
}
speaker=~speaker;
STH1=tab[key]/256;
STL1=tab[key]%256;
TR0=1;
temp=P3;
temp=temp&0x0f;
while(temp!
=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
TR0=0;
}
}
P3=0xff;
P37=0;
temp=P3;
temp=temp&0x0f;
if(temp!
=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp&0x0f;
if(temp!
=0x0f)
{
temp=P3;
temp=temp&0x0f;
switc