基于单片机的电子琴发声控制系统.docx
《基于单片机的电子琴发声控制系统.docx》由会员分享,可在线阅读,更多相关《基于单片机的电子琴发声控制系统.docx(37页珍藏版)》请在冰豆网上搜索。
基于单片机的电子琴发声控制系统
2011年11月25日
摘要
本设计是基于单片机的模拟电子琴发声控制系统,该控制系统的主要控制部件是AT89S52,晶振频率为11.0592MHz,发声部件为蜂鸣器,显示部件为七段数码管,十个按键作为输入端。
设计内容:
设置8个音符按键发出1(do)、2(re)、3(mi)、4(fa)、5(so)、6(la)、7(xi)、1(do),为一组八度音阶;设置1个按键调节音调高低(低八度音阶为一组,中八度音阶为一组,高八度音阶为一组),通过识别按键的次数来调出一组八度音阶,供人们演奏,在按键按下的同时由数码管输出对应的音阶数值;另外设置一个播放按键,当判断按键按下时,自动播放内存的音乐,可以随时中断音乐。
设计方法:
软件部分由扫描按键发声并显示和音乐自动播放两部分构成,故本设计通过判断一个按键的两种状态而在两个部分之间进行切换,每种状态对应一个指定部分,从而保证两种状态的正常切换。
按键的扫描采用4*2矩阵形式,节省了输出端口。
硬件部分的设计主要包括按键排列、数码管显示和蜂鸣器部分,本设计P1口用作对按键的扫描,P2口用作数码管显示,所以矩阵按键和数码管的排列均就近I/O口焊接,布局合理。
数码管显示部分通过限流电阻接P2口,无译码器,考虑到输出的数值,本部分设计由软件部分实现指定数值输出。
蜂鸣器通过PNP型三极管8550接P3口,8550可以实现音频的放大。
蜂鸣器与数码管就近排列,以达到输出一致的效果。
设计成果:
按照本设计的设计理念,设计成功!
该控制系统能准确实现按键扫描,音符、音阶的调用准确无误,同时能显示音符和音阶数值,但受数码管限制,无法同时显示音符1和高一阶音符1(本设计中以8代替);能实现按键控制音乐的自动播放,当检测到控制按键按下时,即可启动音乐自动播放。
本设计简单实用,方便操作,系统稳定,编程简单,能满足单片机初学者对单片机技术的追求,也能满足音乐初学者学习乐器的的基本需求。
1概述
1.1课题简介
单片微型计算机室大规模集成电路技术发展的产物,属于第四代电子计算机它具有高性能、高速度、体积小、价格低廉、稳定可靠、应用广泛的特点。
它的应用必定导致传统的控制技术从根本上发生变革。
因此,单片机的开发应用已成为高科技和工程领域的一项重大课题。
电子琴是现代电子科技与音乐结合的产物,是一种新型的键盘乐器。
它在现代音乐扮演重要的角色,单片机具有强大的控制功能和灵活的编程实现特性,它已经溶入现代人们的生活中,成为不可替代的一部分。
本课题的主要内容是用AT89S52单片机为核心控制元件,设计一个电子琴。
以单片机作为主控核心,与键盘、扬声器等模块组成核心主控制模块,在主控模块上设有8个按键,2个控制按键和1个复位按键。
一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,构成我们想演奏的那首曲目。
对于单片机来说产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0或T1来产生这样的方波频率信号,因此,我们只要把一首歌曲的音符对应频率关系编写正确,就可以达到我们想要的曲目。
1.2仿真技术与软硬件技术的结合
本设计中用到了软件Proteus,该软件是世界上著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。
是目前世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等。
在编译方面,它也支持IAR、Keil和MPLAB等多种编译,给我们做电路设计提供方便快捷的仿真效果。
在编译的过程中用到了KeiluVision3,KeilC51是51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(uVision)将这些部分组合在一起。
其方便易用的集成环境、强大的软件仿真调试工具令我们事半功倍。
1.3单片机简介
AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。
AT89S52具有以下标准功能:
8k字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。
另外,AT89S52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。
空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。
掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52在众多嵌入式控制应用系统中得到广泛应用。
图1.30图1.31
AT89S52引脚图AT89S52实物图
2系统总体方案及硬件设计
2.1总体方案
图2.1总体方案流程图
本设计在音乐播放与键盘扫描之间切换,蜂鸣器能发出共计22个音符,共分三个八度音阶,数码管可显示0-8,由于数码管限制,此处用8代替高一级音符do。
当系统运行时,默认进入键盘扫描,并不发音,数码管显示默认值1,即键盘默认可调用低八度音符。
当音乐播放键(PLAY)按下时,音乐自动播放,数码管显示0,此间可按下复位键终止音乐。
当播放停止时,跳出程序段,默认回到键盘扫描状态,数码管显示返回值1。
每当音阶转换控制键(SWITCH)按下时,数码管显示的数值加1,设置最大显示值是3,循环显示;此处1代表可调用低八度音符,2代表可调用中八度音符,3代表可调用高八度音符。
当矩阵键盘有键按下时,扫描的键值由数码管输出,显示1-8,代表do、re、mi、fa、so、la、xi、do(高一阶),按键与音符一一对应。
这样有效地利用了4*2矩阵键盘,可以实现22个音符的输出,简洁而高效。
2.2按键矩阵
本设计采用4*2矩阵非编码按键,由4*4矩阵修改而成,这样不但可以节省程序扫描,也可以节省端口的占用率,从而达到简洁高效的效果。
键盘为各自独立按键,只简单地提供按键开关。
有关按键的识别、键码的确定与输入、消除抖动等功能均由软件完成。
键盘矩阵图与仿真图相同,见图4.1。
对按键矩阵的扫描由P1.0—P1.5口共同完成。
2.3数码管显示
本设计的数码管部分使用了共阳极数码管,数码管公共端接高电平,Led输入端通过200欧的限流电阻接P2.0-P2.6,数字的输出由软件完成。
见图2.3。
2.4蜂鸣器模块
本设计的蜂鸣器模块由PNP三极管8550作为音频放大,200欧的限流电阻,声音的输出在P3.6口。
见图2.4。
图2.3数码管显示原理图图2.4蜂鸣器焊接原理图
3软件设计
3.1播放音乐部分
图3.1声音频率及定时初值表
音乐的播放要进行音符的识别和准确调用,音符的自然频率是固定的,我们可以根据自然频率计算出其半周期,由此计算出单片机在12MHz下的定时初值,具体计算如图3.1。
因此可以设置低音do到超高音do的定时初值表程序段如下:
unsignedintcodetab[]=//音符初值表低音1————超高音1
{
63627,63835,64021,64103,//低音1234
64260,64400,64524,64580,//低音567中音1
64684,64777,64820,64898,//中音2345
64968,65030,65058,65110,//中音67高音12
65157,65178,65217,65252,//高音3456
65283,65297//高音7超高音1
};
在音乐的播放中节拍的控制由延时控制来实现:
voiddelay(unsignedchart)//延时函数,控制发音的时间长度
{
unsignedchart1;
unsignedlongt2;
for(t1=0;t1for(t2=0;t2<8000;t2++);
TR1=0;//关闭T1,停止发音
}
节拍的长短由设定的数值来实现,此处设定1代表16分音符,2代表8分音符,3代表4分音符,4代表2分音符,音乐的设置如下:
codeunsignedcharmid[]=//春江花月夜简谱
{
6,2,2,6,2,1,6,2,1,1,3,2,2,3,1,6,2,1,5,2,4,5,2,0,
5,2,2,5,2,1,5,2,1,6,2,2,1,3,1,2,3,1,3,2,4,3,2,0,
3,2,2,2,2,1,3,2,1,5,2,2,3,2,1,5,2,1,6,2,3,1,3,1,2,3,3,
3,3,2,1,3,2,2,3,1,3,3,1,2,3,1,1,3,1,6,2,2,5,2,4,5,2,0,
5,2,1,1,3,1,5,2,1,1,3,1,2,3,4,6,2,1,1,3,1,5,2,1,2,2,1,3,2,4,3,2,0,
3,2,2,6,2,1,1,3,1,5,2,1,6,2,1,5,2,1,3,2,1,2,2,3,
3,2,1,2,2,1,1,2,1,2,2,1,3,2,1,1,2,1,2,2,4,0,0,0,
};
读出的每个音符由三个数字构成,第一个数字代表音符;第二个数字代表音高,默认1代表低八度,2代表中八度,3代表高八度;第三个数代表节拍,此处用1代表16分音符,2代表8分音符,3代表4分音符,4代表2分音符,而0用来表示停顿,以区分连音。
音乐播放函数的定义需要一个定时器中断,而这个中断与键盘扫描部分不能用一个中断,故设中断1,工作方式1:
voidsong()//演奏一个音符函数
{
TH1=timerh;//控制音调
TL1=timerl;
TR1=1;//启动T1,由T1输出方波去发音
delay(time);//控制时间长度
}
音符扫描并播放函数段如下:
while(mid[i]!
=0)//只要有音符,就持续执行
{
k=mid[i]+7*(mid[i+1]-1)-1;//第i个是音符,第i+1个是第几个八度
timerh=tab[k]/256;//从数据表中读出定时器计数值
timerl=tab[k]%256;//计数值低位
time=mid[i+2];//读出时间长度数值
i+=3;//每隔三个数读一个音符
if(mid[i+2]==0)//设置发音时长为0时停顿
{
delay10ms();
}
song();//发出一个音符
}
在音乐播放完毕之后,自动跳出该程序段,进入按键扫描程序段。
3.2扫描按键部分
对按键的扫描,包括输入消抖和键值计算,消抖部分由一个延时函数来完成:
voiddelay10ms(void)//延时10ms函数
{
for(i=50;i>0;i--)
for(j=198;j>0;j--);
/*每个指令12个机器周期,即1us,延时计算50*(198+2)+2=10002us
延时精确计算汇编程序如下:
MOVi,#032H
MOVj,#0C6H
DJNZj
DJNZi
RET
*/
}
键盘矩阵为4*2,P1.4、P1.5为行,P1.0、P1.1、P1.2、P1.3为列,将列置高电平,行置低电平,进行扫描,如有按键按下,按键所在列就会被拉成低电平,此处默认P1.4为第一行,因此P1.4所在行的按键键值依照P1.3、P1.2、P1.1、P1.0的顺序为0、1、2、3,同理P1.5行所在的按键键值依照P1.3、P1.2、P1.1、P1.0依次为4、5、6、7,键值的计算程序段如下例:
P1=0xff;
P1_4=0;//从第1行开始扫描键盘
temp=P1;
temp=temp&0x0f;
if(temp!
=0x0f)//扫描控制
{
delay10ms();
temp=P1;
temp=temp&0x0f;
if(temp!
=0x0f)
{
temp=P1;
temp=temp&0x0f;
switch(temp)//读取按键值
{
case0x07:
//判定P1.3
key=0;
Display(0xf9);//数码管显示1
break;
case0x0b:
//判定P1.2
key=1;
Display(0xa4);//数码管显示2
break;
case0x0d:
//判定P1.1
key=2;
Display(0xb0);//数码管显示3
break;
case0x0e:
//判定P1.0
key=3;
Display(0x99);//数码管显示4
break;
}
temp=P1;
P3_6=~P3_6;//准备发音
STH0=tab[key]/256;//计算音符对应的定时器计数值
STL0=tab[key]%256;//计数值低位
TR0=1;//T0计时器开始工作
temp=temp&0x0f;
while(temp!
=0x0f)//扫描循环
{
temp=P1;
temp=temp&0x0f;
}
TR0=0;//T0计时器关闭
P3_6=1;//关闭扬声器,防止电流噪音
}
}
P1=0xff;//对P1口置高
P1_5=0;//扫描P1.5行
temp=P1;
temp=temp&0x0f;
if(temp!
=0x0f)//扫描控制
{
delay10ms();
temp=P1;
temp=temp&0x0f;
if(temp!
=0x0f)
{
temp=P1;
temp=temp&0x0f;
switch(temp)//读取按键值
{
case0x07:
//判定P1.3
key=4;
Display(0x92);//数码管显示5
break;
case0x0b:
//判定P1.2
key=5;
Display(0x82);//数码管显示6
break;
case0x0d:
//判定P1.1
key=6;
Display(0xf8);//数码管显示7
break;
case0x0e:
//判定P1.0
key=7;
Display(0x80);//数码管显示8,此处8代表高一级音符1
break;
}
temp=P1;
P3_6=~P3_6;//准备发音
STH0=tab[key]/256;//计算音符对应的定时器计数值
STL0=tab[key]%256;//计数值低位
TR0=1;//开T0中断
temp=temp&0x0f;
while(temp!
=0x0f)//循环扫描
{
temp=P1;
temp=temp&0x0f;
}
TR0=0;//关闭中断T0
P3_6=1;//关闭蜂鸣器,防止噪音
}
}
Display(0xf9);//数码管显示1,代表可调用低八度
break;
3.3数码管显示
共阳极数码管的数字显示,并不通过译码器,因此需要在软件里面设置对应的代码,此时的代码并不具有规律性,因此只能对其输出做指定设置,0—9的对应字形码如下表3.3:
(共阴极的数码管所用代码并不一样)
“0”
0xc0
“5”
0x92
“1”
0xf9
“6”
0x82
“2”
0xa4
“7”
0xf8
“3”
0xb0
“8”
0x80
“4”
0x99
“9”
0x90
表3.3数码管输出字型码表
对应调用函数如下:
voidDisplay(unsignedcharm)//定义数码管显示函数
{
P2=m;//显示需要显示的数值
}
在输出时只需设置对应的代码即可。
4Proteus软件仿真
4.1键盘部分设计
独立式按键按照4*2矩阵排列。
图4.1键盘仿真电路图
4.2蜂鸣器部分仿真
此处用了无源蜂鸣
器,在仿真时无需接三极
管进行音频放大,使得仿
真电路图简洁明了。
图4.2蜂鸣器仿真电路图
4.3数码管部分仿真
基于Protues的基本功能,对数码管的仿真无需外接限流电阻即可实现,具体实现如图4.3:
图4.3数码管仿真电路图
4.4整体仿真设计
基于单片机的最小系统,对外围电路的开发做了简单的配置,数码管接P2.0—P2.6口,矩阵键盘接P1.0—P1.5口,模式转换键在P3.0口控制输入,音阶转换键在P3.7口控制输入,蜂鸣器发声接P3.6口,具体见图4.4:
图4.4仿真电路总图
5课程设计体会
5.1设计成果
本次设计的最终结果与仿真完全吻合,能够实现高低音符的自由切换,也能够实现音符的准确调用及音乐的自动播放。
系统启动时,数码管显示默认值1,此时可以调用低八度音符。
当按下SW(SWITCH)键一次的时候,数码管显示2,此时可以调用中八度音符;当按下SW键二次的时候,数码管显示3,此时可以调用高八度音符;如此循环往复。
矩阵键盘对应按键(C、D、E、F、G、A、B、C)按下的时候,数码管显示1、2、3、4、5、6、7、8,发音do、re、mi、fa、so、la、xi、do。
无论数码管显示何值,当按下P(PLAY)键的时候,音乐自动播放,数码管显示0;按下RE(RESET)键的时候,终止播放,数码管恢复显示默认值1。
5.2心得体会
通过本次电子设计训练,我们复习了很多专业知识,也让我们感悟颇多,具体起来有以下几点:
1、团队合作远比一个人的力量大得多,在这次的实训中,我们的分工与合作让我体会到了团队的重要性。
2、实践操作远比理论学习进步快得多,在这短暂的几天里,我对专业知识的理解突飞猛进地更进了一层,尤其是对51单片机、编程、PNP三极管、数码管显示以及蜂鸣器输出有了更详细地了解,考虑以后会踏入工作岗位,本次实训更是一次难得的锻炼机会。
3、知识的灵活运用远比知识的掌握更重要。
在借鉴学习的过程中,发现矩阵的扫描可以逐行设置代码进行扫描,也可以通过循环函数对已知的端口设定扫描过程,程序简洁而实用。
4、努力重要,技巧更重要。
在焊接的过程中,P1,P2,P3口作为I/O口,此时的焊接我们依据按键的功能进行了划分,分组排列,整齐而美观;数码管输出和蜂鸣器输出的排列,均在输出部分,采用就近接口的方式,同时考虑输出的一致性,将二者就近排列,达到了人性化的设计效果;对P1、P2端口的使用,我们又对端口进行了延伸,从而实现了排线连接,达到了美观的效果。
5、学习要认真,做事需细心。
在设计软件仿真时和硬件焊接时,我们曾出过一些微小的错误,例如软件关闭中断之后需要软件关闭蜂鸣器,否则就会出现噪音。
但在仔细检查过之后,作以修改,就能到达消除噪音的目的。
参考文献
书、专著:
[1]张元良,王建军等.单片机开发技术实例.北京:
机械工业出版社,2010.8
[2]徐爱钧.单片机原理与应用基于Protues的虚拟仿真技术.北京:
机械工业出版社,2010
电子文献:
[1]做而论道.基于51单片机的4*4矩阵键盘电子琴.
2010-08-05
[2]做而论道.单片机播放音乐的基本知识
附录1源程序代码
//本程序采用AT89S52晶振频率11.0592MHz
#include//头文件
unsignedchartemp,key,k,i,j,ID;//自定义字符变量
unsignedcharSTH0,STL0;//自定义暂存变量
unsignedchartimerh,timerl,time;//自定义暂存变量
sbitP1_4=P1^4;//定义行P1.4
sbitP1_5=P1^5;//定义行P1.5
sbitP3_0=P3^0;//定义音乐播放键
sbitP3_6=P3^6;//定义扬声器输出口P3.6
sbitP3_7=P3^7;//定义音符切换键
unsignedintcodetab[]=//音符表低音1————超高音1
{
63627,63835,64021,64103,//低音1234
64260,64400,64524,64580,//低音567中音1
64684,64777,64820,64898,//中音2345
64968,65030,65058,65110,//