
题 目:基于单片机的简易音乐播放器设计
学 院:物理与电气工程学院
专 业:电子信息科学与技术
年 级:08电信(一)班
姓 名: 王凯 陈少杰 王龙 龚祥龙
****** ***
完成日期: 2011-9-10
摘 要
在电子技术日月更新、不断换代,计算机程序设计语言应用广泛,特别是单片机技术日趋发达的情况下,为了培养并增强设计自主性和动手能力强的人才,了解单片机强大的设计功能,我们进行了此次设计。为了实现一首音乐的播放,选择了用单片机来实现音乐的播放,因为它有很多优点,如:外部结构简单、实现起来比较方便等。对于单片机产生音乐,关键是控制频率的输出。我们知道,不同的声音对应不同的频率,产生有规律的频率输出就可以得到相应规律的声音。音乐中,有7个基本音符:do﹑re﹑mi﹑fa﹑so﹑la﹑si,七个不同的音符对应着不同的频率。只要我们对照音符输出相对应的频率,就可以产生美妙的音乐了。在此次设计中主要采用单片机ATC52和一个SOUNDER(喇叭)来实现音乐的播放,在单片机ATC52的18号和19号引脚(外接晶振端子,分别是片内反相放大器输入端、片内反相放大器输出端)上外接振荡电路,以此来提供时钟频率(时钟频率为12MHz);而P3口中的P1.2端口作为音频输出口;并同时利用P3口中P3.2、P3.3、P3.1端口来控制音乐选择上一曲、下一曲及音乐播放的开始或暂停;与此同时我们还在P0口端接一个八段数码管来显示当前所放歌曲的曲数。
第1章 绪论
现在各种各样的音乐播放器呈现在我们面前,外观越来越精美,功能越来越多,体积越来越小,重量也越来越小、价格越来越便宜。同时,随着当代手机行业的快速发展,许多手机厂商为了能够吸引广大的客户受到消费者的青睐,致此他们开始研究在手机上实现音乐和视频的播放,因此现在的手机都能够轻松的播放音乐了。这样人们就更很容易携带,随时随地都可以听,以便来缓解人们的疲劳、压抑、愉快人们的心情等,甚至有时还可以借着音乐来抒发自己的感情,传达我们对朋友的祝福。因此,在不知不觉中它成为了人们生活的一样必需品,无论到哪里、无论什么时候都可以听到我们想听的音乐。
本设计共分为六章,第1章是绪论,第2章是音乐基础知识,第3章是系统方案设计,第4章是硬件电路,第5章软件设计,第6章是系统调试。
第2章 音乐基础知识
2.1 音乐基础
音作为一种物理现象,是由于物体振动而产生的,振动产生的声波作用于人耳,听觉系统将神经冲动传达给大脑,进而产生听觉。人耳能听到的声音频率大约在11—20000Hz,而音乐使用的音一般在27—4100Hz。
乐音体系中各音级的名称叫做音名,被广泛采用的是C D E F G A B (do re mi fa so la si则多用于歌唱,称为唱名)。乐音体系中音高关系的最小计量单位叫做半音,两个半音构成一个全音。乐音中有几十个高低不同的音,但是最基本只有这七个音,其他高、低音名都是在这个基础上变化出来的。
乐谱表上用来表示正在进行的音的长短的符号,叫做音符。不同的音符代表不同的长度。音符有以下几种:全音符、二分音符、四分音符、八分音符、十六分音符、三十二分音符、六十四分音符。此外,还有附点音符,它就是指带附点的音符,所谓附点就是记在音符右边的小圆点,表示增加前面音符时值的一半。音持续的长短即时值,一般用拍数表示,休止符表示暂停发音。
一首音乐就是由许多不同的音符组成的,而每一个音符对应着不同的频率,这样就可以利用不同的频率的组合,加以拍数对应的延时来构成不同的音乐。
2.2 音频脉冲和音乐节拍的实现
2.2.1 音频脉冲的产生
音乐的产生需要不同频率的音频脉冲,对于单片机而言,可以利用它的定时/计数器产生这样的方波频率信号。在本设计中,单片机工作在12MHz时钟频率下,其时钟周期为1us,因此可以利用ATC52的内部定时/计数器T0,使其工作模式为1,根据对应音符的不同频率求出计数器的初值T(即是TH0和TL0的值),则TH0=T/256,TL0=T%256。
C调各音符频率与计数值T的对照如下表2-1所示。
表2-1 C调各音符频率与计数值T的对照表
| 音符 | 频率(Hz) | 简谱码(T) | 音符 | 频率(Hz) | 简谱码(T) |
| 低1D0 | 262 | 63628 | #4FA# | 740 | 860 |
| #1D0# | 277 | 63731 | 中5SO | 748 | 8 |
| 低2RE | 294 | 63835 | #5S0# | 831 | 934 |
| #2RE# | 311 | 63928 | 中6LA | 880 | 968 |
| 低3M | 330 | 021 | #6LA# | 932 | 994 |
| 低4FA | 349 | 103 | 中7S1 | 988 | 65030 |
| #4FA# | 370 | 185 | 高1DO | 1046 | 65058 |
| 低5SO | 392 | 260 | #DO# | 1109 | 65085 |
| #5S0# | 415 | 331 | 高2RE | 1175 | 65110 |
| 低6LA | 440 | 400 | #2RE# | 1245 | 65134 |
| #6LA# | 466 | 463 | 高3M | 1318 | 65157 |
| 低7S1 | 494 | 524 | 高4FA | 1397 | 65178 |
| 中1DO | 523 | 580 | #4FA# | 1480 | 65198 |
| #1D0# | 554 | 633 | 高5SO | 1568 | 65217 |
| 中2RE | 578 | 684 | #5SO# | 1661 | 65235 |
| #2RE# | 622 | 723 | 高6LA | 1760 | 65252 |
| 中3M | 659 | 777 | #6LA# | 1865 | 65268 |
| 中4FA | 698 | 820 | 高7SI | 1967 | 65283 |
节拍是指音乐持续的长短,是除音符之外音乐的另一关键组成部分,在单片机系统中可以通过延时来实现。
如果1/4拍的延时设为0.2s,则1拍的时间为0.8s,依次类推,可以求出其余节拍的值,节拍的延时时间与音乐的曲调值有相对应的关系,下面为不同曲调下的1/4和1/8节拍的时间设定,如下表2-2所示。
表2-2 不同曲调下1/4和1/8节拍的延时表
| 曲调值(1/8节拍) | delay(ms) | 曲调值(1/4节拍) | delay(ms) |
| 调4/4 | 62 | 调4/4 | 125 |
| 调3/4 | 94 | 调3/4 | 187 |
| 调2/4 | 125 | 调2/4 | 250 |
3.1设计任务
设计一音乐发生器:
(1)用单片机作为开发工具,至少能储存3首乐曲;
(2)能按键选择乐曲序号,每按一次加1键乐曲序号加1,每按一次减1键乐曲序号减1;并有暂停/开始键控制;
(3)用LED数码管显示正在播放的乐曲序号;
(4)能进行仿真音乐发生器。
3.2 设计目的
(1)培养学生怎样将综合的理论知识与实际相结合起来的能力
(2)培养学生分析问题、解决问题的能力
(3)锻炼学生、自学的能力及其动手能力
3.3 设计过程
在毕业设计题目选择后,我积极的查阅相关资料。经过分析、思考及其指导老师的悉心的指导,我最终设计出了一种方案——用ATC52单片机、一个共阴极的八段数码管及扬声器来实现音乐的播放。确定好设计方案后,将整个设计分成了三个步骤:一是,了解的硬件电路图;二是,程序的设计;三是,硬件电路仿真与程序的编译、连接及运行。
3.4 设计思想
在此次设计中,我查阅了很多相关资料并经过分析、思考得到了以下一种方案。它们分别是:用ATC52单片机、一个共阴极的八段数码管及扬声器实现音乐发生器,用INT0和INT1来实现上下曲的切换。
方案设计:主要运用ATC52单片机和一个蜂鸣器两个器件组成。在ATC51单片机外部端子上接晶振电路,单片机的工作时钟为12MHz,将P1口的P1.2引脚作为音频输出口直接送给喇叭,再通过程序设计的来计算出将要播放的歌曲的长度,然后在计算出从该首歌中所取出来的音符的长度,在将该音符通过一系列的控制后实现了该音符的播放,在利用延时来实现该音符播放的长度,在该音符播放完后接着取下一个音符,就这样反复的取出下一个音符,从而实现了乐曲的播放。该方案具体的、详细的电路图设计如图所示。
第4章 硬件电路
4.1 电路组成及工作原理
4.1.1 电路组成
对于整个设计的电路由单片机、显示电路、驱动发声电路及歌曲播放控制电路等部分组成,其组成框图如图4-1所示,其中单片机ATC52主要是将各个模块连接起来并控制各个模块;时钟电路则是用来产生时钟频率,一般是12MHz;复位电路则是能够将当前状态变为初始状态;歌曲的曲数显示电路主要是显示当前所播放的歌曲的曲目数;驱动发声电路则是来播放音乐的;歌曲播放控制电路则是来控制歌曲的播放/暂停和选择歌曲;而整个电路组成框图则是用来显示播放歌曲的曲目数同是控制歌曲的选择及音乐的播放。
图4-1 电路组成框图
4.2 工作原理
利用单片机ATC52直接来产生音频脉冲来驱动喇叭来完成音乐的播放 。利用了该单片机的内部定时器/计数器T0来定进行定时,并同时利用了该单片机的P2口的P1.2来作为音频脉冲的输出端,P3.2(INT0)用来切换到上一曲,P3.3(INT1)用来切换到下一曲,P3.1用来暂停/开始。
4.3 发声驱动电路
主要是采用单片机的P1口上的P1.2来驱蜂鸣声器来产生音乐。P1口上的因为用到一个扬声器所以就可以不能区分它的正负极性了,它的电路框图如图所示。
4.4 显示电路
显示部分主要是由一个共阴极的八段数码管和上拉电阻共同来组成的。它们接在ATC52单片机P0口上。这样数码管就可以正常显示所播放的歌曲的曲目数了,具体的显示器电路图如图所示。
4.5 控制电路
这部分电路主要是用来控制歌曲的播放/暂停及选择。采用了三个按钮来进行控制来实现歌曲播放的上一曲、下一曲及开始/暂停的功能。
第5章 软件设计
5.1程序设计
详细的程序设计见附录1
5.2 程序流程图
第6章 系统调试
6.1 常用调试工具
6.1.1 Proteu仿真软件介绍
Proteu仿真软件用来画硬件电路原理图,在其中我们可以同时调用各样的单片机,但是其中存放的是普通的单片机可能不存在我们所要的芯片,因此我们也可以用Auto CAD或protel 99来画此硬件电路图,而我在此次设计中采用了Proteu这个软件。在画图过程中一定要注意的是,元器件之间的连接线不可以是非线一定要导线,因此完成电路图后再调试这个硬件电路是否能实现它的功能。
6.1.2 Keil编译环境介绍
Keil编译软件用来编程,可以用汇编语言也可以用C语言来进行编程实现某些功能。当打开keil后,首先新建一个项目保存在相应位置,后再新建一个文本,将你已经编好的程序复制到这个文本中或是在这个文本进行编写程序,之后一再将其保存为一个以.Asm或是.c作为后缀名的文本,再在我们建立的组中将程序文件添加到工程中,再经过编译,然后生成.Hex文件再编译,若提示没有出现错误errors(不含警告warnings)则说明调试成功,反之则应该对程序进行检查分析,直到调试成功为止。
结论及设计缺陷
结论:过这次比较完整的单片机音乐发生器的设计,我摆脱了单纯的理论知识学习状态,和实际设计的结合锻炼了我的综合运用所学的专业基础知识,同时也提高我查阅文献资料、设计规范以及电脑画图等其他专业能力水平,而且通过对整体的掌控,对局部的取舍,以及对细节的斟酌处理,都使我的能力得到了锻炼,经验得到了丰富,并且意志品质力。其次,就是在此次毕业设计中关系到了音乐的一些基础知识,音乐是由不同的音符组成,不同的音符对应着不同的频率产生,产生有规律的频率乐音。了解音乐的产生,音乐体系中中音高关系的最小计量单位及音符的定义,同时也知道了音符又分为了以下几种:全音符、二分音符、四分音符、八符分音符、十六分音符、三十二分音符、六十四分符。
设计缺陷:由于本设计的程序的发音设计,在执行暂停开始时不能通过TR0=0,只能通过ET0=0;所以在执行暂停开始不能切换上下曲。
附 录
附录1 程序清单
#include sbit key_next = P3^2; //上一曲按钮 sbit key_last = P3^3; //下一曲按钮 sbit player = P3^1; //定义暂停/播放 sbit speaker = P1^2; //定义音乐输出端口,需要连接到对应的喇叭 unsigned char timer0high,timer0low,time;// unsigned char m,n,x,y; signed char k; unsigned char i; //用来判断暂停开始的变量 code unsigned char music[3][500]={ { 5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 3,1,1, 2,1,1, 2,1,4, 5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,1, 3,1,4, 5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 3,1,1, 2,1,1, 2,1,4, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 1,1,1, 2,1,1, 1,1,1, 1,1,8, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 1,1,1, 2,1,1, 2,1,6, 3,1,1, 2,1,2, 1,1,1, 1,1,1, 5,0,1, 6,0,1, 5,0,1, 5,0,6, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 1,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,2, 1,1,1, 2,1,2, 3,1,1, 3,1,4,5,0,1, 3,1,1, 5,1,2, 6,1,1, 3,1,1, 0,0,0}, //一辈子孤单数据表 { 6,2,3, 5,2,1, 3,2,2, 5,2,2, 1,3,2, 6,2,1, 5,2,1, 6,2,4, 3,2,2, 5,2,1, 6,2,1, 5,2,2, 3,2,2, 1,2,1, 6,1,1, 5,2,1, 3,2,1, 2,2,4, 2,2,3, 3,2,1, 5,2,2, 5,2,1, 6,2,1, 3,2,2, 2,2,2, 1,2,4, 5,2,3, 3,2,1, 2,2,1, 1,2,1, 6,1,1, 1,2,1, 5,1,6, 0,0,0 }, //世上只有妈妈好数据表 { 5,1,2, 3,1,3, 5,1,1, 1,2,3, 6,1,2, 1,2,2, 5,1,4, 5,1,2, 1,1,1, 2,1,1, 3,1,2, 2,1,1, 1,1,1, 2,1,4, 5,1,2, 3,1,1, 5,1,1, 1,2,2, 7,1,1, 6,1,2, 1,2,2, 5,1,4, 5,1,2, 2,1,1, 3,1,1, 4,1,2, 7,0,1, 1,1,4, 6,1,2, 1,2,2, 1,2,4, 7,1,2, 6,1,1, 7,1,1, 1,2,4, 6,1,1, 7,1,1, 1,2,1, 6,1,1, 6,1,1, 5,1,1, 3,1,1, 1,1,1, 2,1,8, 5,1,2, 3,1,1, 5,1,1, 1,2,2, 7,1,1, 6,1,2, 1,2,2, 5,1,4, 5,1,2, 2,1,1, 3,1,1, 4,1,2,7,0,2,1,1,4,0,0,0} //送别数据表 }; // 音阶频率表 高八位 code unsigned char FREQH[]={ 0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8, //低音1234567 0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //中音1,2,3,4,5,6,7,8,i 0xFC,0xFD,0xFD,0xFD,0xFD,0xFE, //高音234567 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF, //高音1234567 } ; // 音阶频率表 低八位 code unsigned char FREQL[]={ 0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6, //低音1234567 0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //中音1,2,3,4,5,6,7,8,i 0xEE,0x44, 0x6B,0xB4,0xF4,0x2D, //高音234567 0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16, //超高音1234567 }; unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 共阴显示段码值01234567 void delay(unsigned char t); void SONG(unsigned char n); void start(); //函数声明 /******************************************************************/ /* 主函数 */ /******************************************************************/ void main() { TMOD=1; //置T0定时工作方式1 EA=1; //CPU开中断 ET0=1; //T0开中断 EX0=1; //INT0开中断 IT0=1; //边沿触发 EX1=1; //INT1开中断 IT1=1; //边沿触发 PX1=1; //优先级设定,INT1优先级在T0前 while(1) { switch(n) //n表示第几首歌曲 { case 0:SONG(0);break; case 1:SONG(1);break; case 2:SONG(2);break; } if(k==-1) //k等于-1表示一首歌曲结束,从下首歌第一个音符开始;若为暂停则不清0 {m=0;} } } /******************************************************************/ /* 延时函数 */ /******************************************************************/ void delay(unsigned char t) { unsigned char t1; unsigned long t2; for(t1=0;t1 for(t2=0;t2<8000;t2++) {;} } } /******************************************************************/ /* 定时器中断函数 */ /******************************************************************/ void t0int() interrupt 1 { TR0=0; //停止计数 speaker=!speaker; //每中断一次,对P1.2取反一次,从而控制蜂鸣器的发音 TH0=timer0high; TL0=timer0low; //赋初值 TR0=1; //开始计数 } /******************************************************************/ /* 音乐处理函数 */ /******************************************************************/ void song() //发出音符的函数 { TH0=timer0high; TL0=timer0low; TR0=1; //开始计数 delay(time); //延时time TR0=0; //停止计数 } void SONG(unsigned char n) { P0=led[n+1]; //数码管显示 while(key_next&&key_last&&player) //判断是否有外部中断或暂停,若都为1则执行函数 { k=music[n][m]+7*music[n][m+1]-1; timer0high=FREQH[k]; timer0low=FREQL[k]; //计算发出音调所需要的时间的初始值 time=music[n][m+2]; //音调延时的时间 m+=3; //三个数字为一音符 if(k==-1) //以0,0,0,结束,结束是k等于-1 break; song(); //调用发音的程序 } if(~player) //判断是否暂停键按下 { while(~player); //离开时跳出死循环 start(); } //调用暂停开始函数 } /******************************************************************/ /* 上下曲处理函数 */ /******************************************************************/ void int_0()interrupt 0 //上一曲函数 { m=0; if(n==0) n=2; else n=n-1; } void int_1() interrupt 2 //下一曲函数 { m=0; if(n==2) n=0; else n=n+1; } /******************************************************************/ /* 暂停开始处理函数 */ /******************************************************************/ void start() { i=i+1; //设置判断的标志位,若为1执行暂停,为0执行开始 if(i%2==1) { x=n; y=m; //保护现场,停止发音 ET0=0; //关闭中断T0 } if(i%2==0) { ET0=1; //打开中断T0 n=x; m=y; //恢复现场 } } 附录2 单片机音乐发生器电路原理图
