模拟电子琴发声控制系统课程设计

更新时间:2024-04-21 17:13:02 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

《单片机应用与仿真训练》设计报告

模拟电子琴发声控制系统

摘要

本设计是基于AT89S52单片机的电子琴的电路设计方法而制作。该方法利用单片机定时器来产生固定频率的方波信号以推动喇叭发出旋律。并使用LED显示器来显示音阶输入的相关消息,然后通过按下键盘组中的相对按键使喇叭发出相对音阶单音,并自动存储所输入的单音,之后再一起自动演奏出来,从而实现具有存储功能的电子琴系统。本设计实现的功能是利用蜂鸣器作为发声部件,两个数码管作为显示部件,设置11个按键,实现高音、中音、低音的1、2、3、4、5、6、7的发音,并存储一首歌的内容,可以实现自动播放。它具有7个音阶的键盘,分别为DO、RE、MI、FA、SO、LA、SI。每个音阶都对应着不同的频率,这样,我们就可以利用不同的频率组合构成我们想要的音乐。对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样的方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。用户可以根据乐谱在键盘上进行演奏,音乐发生器会根据用户的弹奏,通过扬声器将音乐播放出来。

介绍了一种基于AT89S52单片机的电子琴的电路设计方法。该方法利用单片机定时器来产生固定频率的方波信号以推动喇叭发出旋律。然后通过按下键盘组中的相对按键使喇叭发出相对音阶单音,并自动存储所输入的单音,之后再一起自动演奏出来,从而实现具有存储功能的电子琴系统。

关键词:单片机、电子琴、音阶、频率

2

目录

摘要 ......................................................................................................... 错误!未定义书签。 1、概述 ................................................................................................... 错误!未定义书签。

1.1电子琴概述 .............................................................................. 错误!未定义书签。 1.2电子琴系统原理 ...................................................................... 错误!未定义书签。 1.3设计任务及要求 ...................................................................... 错误!未定义书签。 2、系统总体方案及硬件设计 ............................................................... 错误!未定义书签。

2.1 系统硬件组成 ......................................................................... 错误!未定义书签。

2.11 AT89S52简介 .................................................................................................. 5 2.12 音乐播放部分 ................................................................................................. 8 2.13电子琴弹奏部分 .............................................................................................. 8 2.2 具体发音原理 ......................................................................................................... 8 2.3 各部分电路图 ....................................................................................................... 10

2.31 晶振 ............................................................................................................... 10 2.32 复位电路 ..................................................................................................... 10 2.33 按键 ............................................................................................................. 11 2.34 发音 ............................................................................................................. 11

3、软件设计 ........................................................................................................................... 12

3.1流程图 ...................................................................................................................... 12 3.2 主程序代码 ............................................................................................................. 13 4、Proteus软件仿真 ............................................................................................................ 13 5、课程设计体会 ................................................................................................................... 13 参考文献 ................................................................................................................................. 14 附录1 源程序代码 ................................................................................................................ 15 附录2 仿真图 ........................................................................................................................ 23

3

1 概述

1.1 电子琴概述

电子琴又称作电子键盘,属于电子乐器(区别于电声乐器),发音音量可以自由调节。音域较宽,和声丰富,甚至可以演奏出一个管弦乐队的效果,表现力极其丰富。它还可模仿多种音色,甚至可以奏出常规乐器所无法发出的声音(如合唱声,风雨声,宇宙声等)。另外,电子琴在独奏时,还可随意配上类似打击乐音响的节拍伴奏,适合于演奏节奏性较强的现代音乐。

AT89S52是一种低功耗、高性能CMOS 8位微控制器,具有8K 在系统可编程Flash 存储器。使用Atmel 公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52在众多嵌入式控制应用系统中得到广泛应用。本文利用AT89C51 单片机的强大功能,通过软件产生不同频率的声音信号,经相应的放大电路后,在扬声器中发出8个音节。可以弹奏出不同的曲子。

1.2 电子琴系统原理

由于一首音乐是许多不同的音阶组成的,而每个音阶对应着不同的频率,这样我们就可以利用不同的频率的组合,即可构成我们所想要的音乐了,当然对于单片机来产生不同的频率非常方便,我们可以利用单片机的定时/计数器T0来产生这样方波频率信号,因此,我们只要把一首歌曲的音阶对应频率关系弄正确即可。只要向若将不同的音节与一定的节拍组合在一起形成一定的曲调,因此只要一单片机I/0口,通过软件,控制其输出不同频率的信号,就可以产生8个基本音节。将音节以一定的节拍进行组合,便可以产生歌曲。乐曲中每一音符对应着确定的频率。如果单片机某个口线输出“高~低”电平的频率和某个音符的频率一样,那么将此口线接上喇叭就可以发出此音。

1.3 设计任务及要求

本系统分为两个部分,一个是音乐播放,另一个就是电子琴弹奏。通过开 控制播放音乐或者进行电子琴弹奏。本系统利用蜂鸣器作为发声部件,当播放音乐时,弹奏按键无效;当进行弹奏时,设置10个按键,实现高音、中音、低音的1、2、3、4、5、6、7的发音,两个数码管作为显示部件,显示输入的信息。

4

2 系统总体方案及硬件设计

2.1硬件组成

2.11 AT89S52简介

1.概述

AT89S52是一种低功耗、高性能CMOS 8位微控制器,具有8K 在系统可编程Flash 存储器。使用Atmel 公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片

上,

图2-2 AT89S52单片机 拥有灵巧的8 位CPU 和 在系统可编程Flash,使得AT89S52在众多嵌入式控制应用系统中得到广泛应用。

2.主要性能

与MCS-51单片机产品兼容; 8K字节在系统可编程Flash存储器; 1000次擦写周期; 全静态操作:0Hz-33MHz; 三级加密程序存储器; 32个可编程I/O口线; 三个16位定时器/计数器; 六个中断源;

全双工UART串行通道;

5

2.33按键

2.34 发音

11

3 软件设计

3.1流程图

开开开开开开开开开Y开 do re mi fa sol la SI DO开NYNdo re mi fa sol la SI DO TR0开1TR1开0开开T0开开开UP DOWN开开开?Y开开开开开n开开N开开开开开开开开YEsm开1开NEsm开1TR1开1 NYEsm开0TR1开0开开开 high ave low开开开 NY 开开开开freq开开 开开开开开TR0开0 NEsm开开开1Y开开 开开开开

12

3.2 主程序代码

见附录一 源程序代码

4、Proteus软件仿真

见附录2 仿真图

5 课程设计体会

通过此次课程设计,使我更加扎实的掌握了有关单片机方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。

过而能改,善莫大焉。在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。最终的检测调试环节,本身就是在践行“过而能改,善莫大焉”的知行观。这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘,而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!

课程设计诚然是一门专业课,给我很多专业知识以及专业技能上的提升,同时又是一门讲道课,一门辩思课,给了我许多道,给了我很多思,给了我莫大的空间。同时,设计让我感触很深。使我对抽象的理论有了具体的认识。通过这次课程设计,我掌握了PROTUES、WAVE6000等软件,用WAVE6000进行程序的编译,用PROTUES进行软硬件系统的仿真。

回顾起此课程设计,至今我仍感慨颇多,从理论到实践,在这段日子里,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计

13

使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,但可喜的是最终都得到了解决。

参考文献

[1] 余发山,王福忠.单片机原理及应用技术.徐州:中国矿业大学出版社,2008年

[2] 韩志军等.单片机应用系统设计.北京:机械工业出版社,2004.75-83 [3] 王守中.51单片机开发入门与典型实例.北京:人民邮电出版社,2007.139-149

[4] 周润景等. Proteus在MCS-51&ARM7系统中的应用百例.北京:电子工业出版社,2006.132-139

[5] 王为青,邱文勋.51单片机应用开发案例精选.北京:人民邮电出版社,2007.61-65

14

附录1 源程序代码

#include #include #define SYSTEM_OSC #define SOUND_SPACE #define uchar unsigned char #define uint unsigned int #define P_key P1 sbit beep=P3^6; 86, 76, 72, 64, 56, 50 始频率表

unsigned char code SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在频率表中的位置 unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };

unsigned char Sound_Temp_TH0,Sound_Temp_TL0; //音符定时器初值暂存 unsigned char Sound_Temp_TH1,Sound_Temp_TL1; //音长定时器初值暂存

//曲谱存贮格式 unsigned char code MusicName{音高,音长,音高,音长...., 0,0}; 末尾:0,0 表示结束(Important)

unsigned char code Music_Girl[]={

25,3,25,14,26,4,31,103,27,4,26,3,23,14,22,4,21,2,23,3,32,3,32,14,27,4,26,14,23,4,25,12,25,2,25,3,25,14,26,4,31,103,27,4,26,3,25,14,26,4,23,2,16,3,26,3,26,14,25,4,25,14,23,4,22,12,22,2,23,3,23,14,22,4,25,3,25,4,23,4,22,3,23,14,22,4,21,103,22,4,23,103,25,4,27,14,26,4,25,3,26,12,26,2,31,3,31,14,26,4,31,103,31,4,26,13,25,14,23,4,22,2,16,3,26,3,25,14,23,4,23,14,22,4,21,102,31,14,32,4,33,4,33,3,33,4,32,3,33,14,32,4,31,102,26,14,31,4,32,4,32,3,33,4,32,14,27,4,26,15,27,15,26,5,25,12,25,2,26,14,31,4,26,4,31,3,31,4,26,4,25,3,26,14,25,4,23,2,26,103,31,4,33,14,32,4,31,3,32,102,31,14,32,4,33,4,33,3,33,4,32,3,33,14,32,4,31,102,26,14,31,4,32,103,33,4,32,14,27,4,26,15,27,15,26,5,25,12,25,2,26,14,31,4,31,4,26,4,31,3,31,4,26,4,25,3,26,14,25,4,23,2,26,13,33,3,32,14,31,14,26,3,31,12,31,2,26,13,33,3,32,14,31,14,26,3,31,102,31,14,32,4,26,13,33,3,32,14,31,14,36,3,31,12,31,2,0,0

};

//us级延时程序延时y(us) = 9.75*i + 17.44! //毫秒级延时函数!

void delay_us(uint i);

};

//蜂鸣器控制端口P1^0!

Unsigned int code sy[21]={ 194,173,154,145,129,115,102,390,347,309,291,260,231,205,96, unsigned int code FreTab[12]= { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原

12000000

//定义晶振频率12000000HZ

4/5

//定义普通音符演奏的长度分率,//每4分音符间隔

void delay_ms(uint t);

void didi(uint k,uint t1,uint t2);//蜂鸣器进行响t1静t2的k次动作! void keyscan(void); //按键扫描动作! void yindiao(uint i);

//产生不同频率声音的函数! //按键音优化!

15

void music(uchar diao);

void InitialSound(void); //自动播放需要的定时器设置等!

void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed);

void BeepTimer0(void); void main() { }

void delay_us(uint i)

{ while(i--);//us级延时程序延时y(us) = 9.75*i + 17.44! }

void delay_ms(uint t) { uint i,j; }

void didi(uint k,uint t1,uint t2)//蜂鸣器进行响t1静t2的k次动作! {

uint i; { for(i=0;i

void keyscan(void) //按键扫描动作! {

uchar tiaozheng=0; {

InitialSound();

while(1) { }

for(j=0;j

//毫秒级延时函数!

didi(2,100,40); keyscan();

//两声提示!

//音符发生中断

//自动播放函数!

if((P2&0x01)==0x00)

16

didi(2,80,40); InitialSound();

Play(Music_Girl,0,3,200);//Play(乐曲名,调号,升降八度,演奏速度); {

if((P2&0x04)==0) {

tiaozheng=14;

//进入高音区!

if(P_key==0xfd){music(tiaozheng+0);} //1111 1101 if(P_key==0xfb){music(tiaozheng+1);} //1111 1011 if(P_key==0xf7){music(tiaozheng+2);} if(P_key==0xef){music(tiaozheng+3);} if(P_key==0xdf){music(tiaozheng+4);} if(P_key==0xbf){music(tiaozheng+5);} if(P_key==0x7f){music(tiaozheng+6);}

{

//进入低音区!

}

else if((P2&0x02)==0) //1000 0000当前L也按下了! tiaozheng=7;

//0100 0000当前H也按下了!

}

//此处内部括号不能少,否则不能进入下面。

else if((P_key&0xff)!=0xff)

if(P_key==0xfd){music(tiaozheng+0);} if(P_key==0xfb){music(tiaozheng+1);} if(P_key==0xf7){music(tiaozheng+2);} if(P_key==0xef){music(tiaozheng+3);} if(P_key==0xdf){music(tiaozheng+4);} if(P_key==0xbf){music(tiaozheng+5);} if(P_key==0x7f){music(tiaozheng+6);}

{

}

else //是默认的中音!

tiaozheng=0;

if(P_key==0xfd){music(tiaozheng+0); if(P_key==0xfb){music(tiaozheng+1);} if(P_key==0xf7){music(tiaozheng+2);} if(P_key==0xef){music(tiaozheng+3);} if(P_key==0xdf){music(tiaozheng+4);}

17

if(P_key==0xbf){music(tiaozheng+5);} if(P_key==0x7f){music(tiaozheng+6);} }

void yindiao(uint i) { }

void music(uchar diao) { {

case 0: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 1: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 2: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 3: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 4: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 5: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 6: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 7: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 8: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 9: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 10: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 11: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 12: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 13: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 14: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 15: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 16: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 17: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 18: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; uint i=0,jizhun=20; switch(diao)

//按键音优化!

beep=0; beep=1; delay_us(i); delay_us(i);

//产生不同频率声音的函数

}

}

}

18

}

}

case 19: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; case 20: for(i=0;i<(jizhun+(5*diao));i++)yindiao(sy[diao]);break; default: break;

//自动播放需要的定时器设置等!

void InitialSound(void) { beep = 1; 初值

初值

Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256; (10ms的初装值)

// 计算TL1应装入的

Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%6; // 计算TH1应装入的TH1 = Sound_Temp_TH1; TL1 = Sound_Temp_TL1;

TMOD |= 0x11;//定时器0和定时器1都是方式1 16位计数。 ET0 = 1; ET1 = 0; TR0 = 0; TR1 = 0; IT0=0; EX0=1; EA = 1;

}//曲谱存贮格式 unsigned char code MusicName{音高,音长,音高,音长...., 0,0}; 末尾:0,0 表示结束(Important)

void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)

{

unsigned int NewFreTab[12]; unsigned char i,j;

unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;

unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD; for(i=0;i<12;i++) {

//进入高音音域!

// 根据调号及升降八度来生成新的频率表 //新的频率表

j = i + Signature; if(j > 11) {

j = j-12;

NewFreTab[i] = FreTab[j]*2;

19

else

}

NewFreTab[i] = FreTab[j]; if(Octachord == 1) NewFreTab[i]>>=2; else if(Octachord == 3)

}

//需要升八度!

NewFreTab[i]<<=2; //否则不用改! SoundLength = 0;

while(Sound[SoundLength] != 0x00) //计算歌曲长度

{ }

//读出音调!

// 读出第一个音符和它时时值!

// 算出1分音符的长度(几个10ms) LDiv4 =

SoundLength+=2; Point = 0;

Tone = Sound[Point]; LDiv0 = 12000/Speed; LDiv0/4;

Length = Sound[Point+1];

//需要降八度!

// 算出4分音符的长度

LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准

TR0 = 0; TR1 = 1;

while(Point < SoundLength) {

SL=Tone; SH=Tone/100;

//计算出音符 //计算出高低音 //计算出是否升半

SM=Tone/10;

CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率 { }

if (SM==1) CurrentFre >>= 2; if (SM==3) CurrentFre <<= 2;

//低音 //高音

if(SL!=0)

Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算Sound_Temp_TH0 = Temp_T/256; Sound_Temp_TL0 = Temp_T%6; TH0 = Sound_Temp_TH0;

TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿

计数器初值

20

SLen=LengthTab[Length]; //算出是几分音符 XG=Length/10; FD=Length/100; LDiv=LDiv0/SLen; if (FD==1) if(XG!=1)

//算出普通音符的演奏长度

LDiv=LDiv+LDiv/2; if(XG==0) if (SLen<=4) LDiv1=LDiv-LDiv4; else

LDiv1=LDiv*SOUND_SPACE; else

LDiv1=LDiv/2; else LDiv1=LDiv; if(SL==0) LDiv1=0; LDiv2=LDiv-LDiv1; if (SL!=0) { TR0=1; for(i=LDiv1;i>0;i--) { while(TF1==0); TH1 = Sound_Temp_TH1; TL1 = Sound_Temp_TL1; TF1=0; }

if(LDiv2!=0) { TR0=0; beep=1; for(i=LDiv2;i>0;i--) { while(TF1==0); TH1 = Sound_Temp_TH1; TL1 = Sound_Temp_TL1; TF1=0;

} }

//音符间的间隔

}

//发规定长度的音

//算出不发音的长度

//算出顿音的演奏长度

//算出连音音符演奏的长度(多少个10ms) //有浮点,加半个时值!

//算出音符类型(0普通1连音2顿音)

if((P1&0xff)!=0xff) break;

21

Point+=2; Tone=Sound[Point]; Length=Sound[Point+1]; }

void BeepTimer0(void) interrupt 1 //音符发生中断 } beep = 1;

{ beep = !beep;

TH0 = Sound_Temp_TH0; TL0 = Sound_Temp_TL0; }

22

附录2 仿真图

23

本文来源:https://www.bwwdw.com/article/yuxp.html

Top