《单片机控制的数字音乐盒设计(18页).doc》由会员分享,可在线阅读,更多相关《单片机控制的数字音乐盒设计(18页).doc(18页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、-单片机控制的数字音乐盒设计-第 I 页目 录目 录I摘 要I1设计目的及要求12总体设计内容12.1 原理简介12.2 方案设计思想12.3 相关芯片说明22.3.1芯片AT89C5122.3.2 芯片LCD1286432.4 电路各模块说明32.4.1 时钟振荡电路、复位电路32.4.2 蜂鸣电路42.4.3 键盘电路42.4.4 显示电路52.5 系统的设计62.6 软件设计62.7 仿真、安装和调试8总结与致谢9参考文献10附录11附录一:音乐程序11附录二:基于单片机的数字音乐盒总电路图19摘 要本设计是基于单片机的数字音乐盒设计,由单片机AT89C51芯片和LCD显示器为核心,辅以
2、必要的电路,构成的一个单片机电子数字音乐盒。要求利用I/O口产生一定频率的方波,驱动蜂鸣器,发出不同的音调并采用LCD显示信息,从而演奏乐曲(最少三首乐曲,每首不少于30秒),开机时有英文欢迎提示字符,播放时显示歌曲序号(或名称),可通过功能键选择乐曲,暂停,播放。本设计采用4*4键盘,用Protel来画系统硬件图,采用汇编语言进行编程,编程后利用KEIL C51来进行编译,再生成的HEX文件装入芯片中,采用proteus软件来仿真,检验功能得以正常实现。该音乐盒的设计可以通过按键选择不同的曲目,播放和暂停,并通过LCD显示歌曲号及播放时间。关键词:音乐盒;AT89C51;LCD显示器 Pro
3、tel软件;4*4键盘 1设计目的及要求设计目的:运用单片机设计数字音乐盒设计要求:1、利用I/O口产生一定频率的方波,驱动蜂鸣器,发出不同的音调,从而演奏乐曲(最少储存三首乐曲,每首不少于30秒)2、采用LCD显示信息3、开机时有英文欢迎提示字符,播放时显示歌曲序号(或名称)4、可通过功能键选择乐曲,暂停,播放 5、显示乐曲播放时间或剩余时间2总体设计内容 2.1 原理简介当键盘有键按下时,判断键值,启动计数器T0,产生一定频率的脉冲,驱动蜂鸣器,放出乐曲。同时启动定时器T1,显示乐曲播放的时间,并驱动LCD,显示歌曲号。2.2 方案设计思想用AT89S52单片机的I/O口产生一定频率的方波
4、,驱动蜂鸣器,发出不同的音调,从而演奏乐曲。共有4乐曲,每首乐曲都由相应的按键控制,并且有开关键、暂停键、上一曲以及下一曲控制键。其组成框图如2.2所示图2.22.3 相关芯片说明2.3.1芯片AT89C51AT89C51是一种带4K字节闪存可编程可擦除只读存储器(FPEROM)的低电压,高性能CMOS 8位微处理器,俗称单片机。AT89C2051是一种带2K字节闪存可编程可擦除只读存储器的单片机。单片机的可擦除只读存储器可以反复擦除100次。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,
5、ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。外形及引脚排列如图2.3所示 图2.32.3.2 芯片LCD12864带中文字库的128X64是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为12864, 内置8192个16*16点汉字,和128个16*8点ASCII字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示84行1616点阵的汉字.也可完成图形显示2.4 电路
6、各模块说明2.4.1 时钟振荡电路、复位电路时钟电路在单片机系统中起着非常重要的作用,是保证系统正常工作的基础。在一个单片机应用系统中,时钟是保障系统正常工作的基准振荡定时信号,主要由晶振和外围电路组成,晶振频率的大小决定了单片机系统工作的快慢。为达到振荡周期是12MHZ的要求,这里要采用12MHZ的晶振,另外有两个22P的独石电容,两晶振引脚分别连到XTAL1和XTAL2振荡脉冲输入引脚。其电路图如2.4.1所示图2.4.12.4.2 蜂鸣电路利用PNP管(9012)放大驱动。基极接10K欧姆的电阻,发射极接蜂鸣器,集电极接电源。其电路图如图2.4.2所示图2.4.22.4.3 键盘电路 键
7、盘在单片机应用系统中能实现向单片机输入数据,传送命 图3令等功能,是人工干预单片机的主要手段。键盘模块采用4*4按键模式(S1-S16),接在单片机的P0口上。当用手按下一个键时,往往按键在闭合位置和断开位置之间跳几下才稳定到闭合状态的情况;在释放一个键时,也回会出现类似的情况。这就是抖动。抖动的持续时间随键盘材料和操作员而异,不过通常总是不大于10ms。很容易想到,抖动问题不解决就会引起对闭合键的识别。用软件方法可以很容易地解决抖动问题,这就是通过延迟10ms来等待抖动消失,这之后,在读入键盘码。其电路如图2.4.3所示图2.4.32.4.4 显示电路显示电路采用LCD模块,LCD显示模块采
8、用LCD12864。LCD显示模块电路图和驱动模块电路如图2.4.4所示。图2.4.42.5 系统的设计其系统总电路图见附录一2.6 软件设计主模块是系统软件的主框架。结构化程序设计一般有“自上而下”和“自下而上”两种方式,“自上而下”法的核心就是主框架的构建。它的合理与否关系到程序最终的功能的多少和性能的好坏。本程序可以实现课程设计的基本要求,并可以通过按键播放多首歌曲,主程序流程图和显示子程序的流程图如图2.6所示。数字音乐盒主程序流程图显示子程序流程图2.7 仿真、安装和调试仿真部分采用Keil软件,进行编程和仿真,修改编程错误以及连接错误。总结与致谢学了一学期的单片机,对单片机的硬件设
9、计,软件设计掌握的深度不够,但通过此次课程设计,却改变了很多,首先对于硬件电路的工作原理有了进一步的学习,同样就有了进一步的认识;其次软件方面,在程序的设计,程序的调试方面都学到了很多东西,这是第一次编写单片机的大程序,很有成就感。在此次单片机的课程设计中,我不但对单片机的基础知识掌握的更牢固,而且对其硬件和软件方面有了更深一层的认识。在做数字音乐盒的课程设计时,我掌握了AT89C51单片机的内部振荡方式及振荡频率和单片机的复位电路形式。此次设计的软件编程采用的是我们所学的汇编语言,通过对数字音乐盒的编程,我更熟悉了键盘扫描和动态显示的编程以及定时计数器和中断的编程。巩固了对AT89C51的内
10、部结构和接口扩展的知识。本次设计中,我用到了protel99画图软件,keil C51编程软件。以前虽然对protel99有一定的认识,能运用其画图,不缺不熟练,这次设计是我对其的熟练程度提高了不少。参考文献1 许珉.单片机原理及应用M.北京:中国电力出版社,2007.08 2 John Markus.电子电路大全M.北京:计量出版社,19953 阎石.数字电子技术基础M.北京:高等教育出版社,1998.12,第4版4 邓元庆.数字电路与逻辑设计M.北京:电子工业出版社,2001 5 高锋,单片微型计算机原理与接口技术.科学出版社,2003年. 6 三恒星科技.MCS-51单片机原理与应用实例
11、M. 北京:电子工业出版社,2008.017 王为青,程国钢.单片机Keil Cx51应用开发技术M. 北京:人民邮电出版社,2007.02 8 李传军,单片机原理及应用(第一版).河南科学技术出版社,2006年.9 杨志忠.数字电子技术.高等教育出版社(第二版)M.2003年.10 张友德.单片微型机原理应用与实验.上海复旦大学出版社,2000附录附录一:音乐程序#include #define uchar unsigned char#define uint unsigned intsbit BEEP = P14; /蜂鸣器sbit k0=P20;sbit k1=P21;sbit k2=P2
12、2;sbit k3=P23;sbit k4=P24;sbit k5=P25;sbit k6=P26;uint code Tone_Delay_Table = 64021,64103,64260,64400,64524,64580,64684,64777, 64820,64898,64968,65030,65058,65110,65157,65178 ;uchar code Song1_Tone=1, 1, 5, 5, 6, 6, 5,4, 4, 3 ,3, 2, 2, 1,5, 5, 4, 4, 3, 3, 2, 5, 5, 4, 4, 3, 3, 2,1,1, 5, 5, 6, 6 ,5,4
13、 ,4, 3, 3, 2, 2, 1,0xff;uchar code Song1_Time=2,2,2,2,2,3,4,2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,5,2,2,2,2,2,2,5,2,2,2,2,2,2,5,0xff;uchar code Song2_Tone=1,2,3,1,1,2,3,1,3,4,5,3,4,5, 5,6,5,4,3,1, 5,6,5,4,3,1 ,1,5,1,0xff;uchar code Song2_Time=2,2,3,2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
14、,2,2,3,0xff; uchar code Song3_Tone = 1,3,3,3,3,5,4,2,5,3,7,6,5,5,7,4,4,3,6,7,2,1,0xFF; uchar code Song3_Time = 2,1,1,2,1,1,1,2,1,1,3,2,1,1,2,4,1,1,2,1,1,1,0xFF; uchar code Song4_Tone = 8,9,2,3,7,6,2,3,10,11,1,2,3,1,2,3,3,4,5,6,5,3,5,6,5,3,5,3,2,1,1,2,3,0xFF; uchar code Song4_Time = 3,6,7,2,4,5,8,1,2
15、,2,5,5,1,9,1,1,1,1,6,1,1,2,4,1,1,2,1,1,1,1,1,2,2,1,0xFF;uchar Song_Index = 0, Tone_Index = 0; /音乐片段索引,音符索引uchar *Song_Tone_Pointer, *Song_Time_Pointer; /音符指针,延时指针uchar i = 0; uchar j=0,k=0,m=0; /从当前数组中取音符的位置 void DelayMS(uint ms) /延时 uchar t; while(ms-) for (t = 0; t 120; t+); void play0() /按键产生的INT
16、0 ET0=1; TR0 = 0;k0=1; Song_Index = ( Song_Index + 1) % 4; /切换到下一音乐 switch (Song_Index) case 0: Song_Tone_Pointer = Song1_Tone; Song_Time_Pointer = Song1_Time; break; case 1: Song_Tone_Pointer = Song2_Tone; Song_Time_Pointer = Song2_Time; break; case 2: Song_Tone_Pointer = Song3_Tone; Song_Time_Poin
17、ter = Song3_Time; break;case 3: Song_Tone_Pointer = Song4_Tone; Song_Time_Pointer = Song4_Time; break; /从下一段音乐的第0个音符开始 i = 0; while (k0=1&k1=1&k2=1&k3=1&k4=1&k5=1&k6=1) Tone_Index = Song_Tone_Pointeri; if ( Tone_Index = 0xFF ) i = 0; DelayMS(2000); /每段音乐播放结束后停顿一段时间 continue; /继续播放 TR0 = 1; DelayMS(
18、Song_Time_Pointer Tone_Index * 240); TR0 = 0; i+;return; void play1() ET0=1; TR0 = 0;k1=1; Song_Index = ( Song_Index + 3) % 4; /切换到上一段音乐 switch (Song_Index) case 0: Song_Tone_Pointer = Song1_Tone; Song_Time_Pointer = Song1_Time; break; case 1: Song_Tone_Pointer = Song2_Tone; Song_Time_Pointer = Song
19、2_Time; break; case 2: Song_Tone_Pointer = Song3_Tone; Song_Time_Pointer = Song3_Time; break;case 3: Song_Tone_Pointer = Song4_Tone; Song_Time_Pointer = Song4_Time; break; i = 0; /从上一段音乐的第0个音符开始 while (k0=1&k1=1&k2=1&k3=1&k4=1&k5=1&k6=1) Tone_Index = Song_Tone_Pointeri; if ( Tone_Index = 0xFF ) i =
20、0; DelayMS(2000); /每段音乐播放结束后停顿一段时间 continue; /继续播放 TR0 = 1; DelayMS( Song_Time_Pointer Tone_Index * 240); TR0 = 0; i+;return; void play2() m=!m; TR0 = 0;k2=1;if(m=0) j=1; TR0=0;ET0=0;if(m=1) ET0=1; k=1;if(j=1) /播放被暂停的音乐 switch (Song_Index) case 0: Song_Tone_Pointer = Song1_Tone; Song_Time_Pointer =
21、Song1_Time; break; case 1: Song_Tone_Pointer = Song2_Tone; Song_Time_Pointer = Song2_Time; break; case 2: Song_Tone_Pointer = Song3_Tone; Song_Time_Pointer = Song3_Time; break;case 3: Song_Tone_Pointer = Song4_Tone; Song_Time_Pointer = Song4_Time; break; /从本一段音乐的第i个音符开始 while (k0=1&k1=1&k2=1&k3=1&k4
22、=1&k5=1&k6=1) Tone_Index = Song_Tone_Pointeri; if ( Tone_Index = 0xFF ) i = 0; DelayMS(2000); /每段音乐播放结束后停顿一段时间 Song_Index = ( Song_Index + 1) % 4; /播放下一首音乐 switch (Song_Index) case 0: Song_Tone_Pointer = Song1_Tone; Song_Time_Pointer = Song1_Time; break; case 1: Song_Tone_Pointer = Song2_Tone; Song_
23、Time_Pointer = Song2_Time; break; case 2: Song_Tone_Pointer = Song3_Tone; Song_Time_Pointer = Song3_Time; break;case 3: Song_Tone_Pointer = Song4_Tone; Song_Time_Pointer = Song4_Time; break;continue; TR0 = 1; DelayMS( Song_Time_Pointer Tone_Index * 240); TR0 = 0; i+; if (j=0)j=1; Song_Tone_Pointer =
24、 Song1_Tone; /开始播放音乐 Song_Time_Pointer = Song1_Time; i = 0; while (k0=1&k1=1&k2=1&k3=1&k4=1&k5=1&k6=1) Tone_Index = Song_Tone_Pointeri; if ( Tone_Index = 0xFF ) i = 0; DelayMS(2000); /每段音乐播放结束后停顿一段时间 Song_Index = ( Song_Index + 1) % 4; /播放下一段音乐 switch (Song_Index) case 0: Song_Tone_Pointer = Song1_T
25、one; Song_Time_Pointer = Song1_Time; break; case 1: Song_Tone_Pointer = Song2_Tone; Song_Time_Pointer = Song2_Time; break; case 2: Song_Tone_Pointer = Song3_Tone; Song_Time_Pointer = Song3_Time; break;case 3: Song_Tone_Pointer = Song4_Tone; Song_Time_Pointer = Song4_Time; break; continue; TR0 = 1; D
26、elayMS( Song_Time_Pointer Tone_Index * 240); TR0 = 0; i+; return;void play3() ET0=1; TR0 = 0; k3=1;/切换到第一段音乐 Song_Tone_Pointer = Song1_Tone; Song_Time_Pointer = Song1_Time; Song_Index=0; /从第一段音乐的第0个音符开始 i = 0; while (k0=1&k1=1&k2=1&k3=1&k4=1&k5=1&k6=1) Tone_Index = Song_Tone_Pointeri; if ( Tone_Inde
27、x = 0xFF ) i = 0; DelayMS(2000); /每段音乐播放结束后停顿一段时间 continue; /继续播放 TR0 = 1; DelayMS( Song_Time_Pointer Tone_Index * 240); TR0 = 0; i+;return;void play4() ET0=1; TR0 = 0;k4=1;Song_Tone_Pointer = Song2_Tone;/切换到第二段音乐 Song_Time_Pointer = Song2_Time; Song_Index=1 ; i=0; /从第二段音乐的第0个音符开始 while (k0=1&k1=1&k
28、2=1&k3=1&k4=1&k5=1&k6=1) Tone_Index = Song_Tone_Pointeri; if ( Tone_Index = 0xFF ) i = 0; DelayMS(2000); /每段音乐播放结束后停顿一段时间 continue; /继续播放 TR0 = 1; DelayMS( Song_Time_Pointer Tone_Index * 240); TR0 = 0; i+;return;void play5() ET0=1; TR0 = 0;k5=1;Song_Tone_Pointer = Song3_Tone; /切换到第三段音乐 Song_Time_Poi
29、nter = Song3_Time; Song_Index=2; /从第三段音乐的第0个音符开始 i = 0; while (k0=1&k1=1&k2=1&k3=1&k4=1&k5=1&k6=1) Tone_Index = Song_Tone_Pointeri; if ( Tone_Index = 0xFF ) i = 0; DelayMS(2000); /每段音乐播放结束后停顿一段时间 continue; /继续播放 TR0 = 1; DelayMS( Song_Time_Pointer Tone_Index * 240); TR0 = 0; i+;return;void play6() E
30、T0=1; TR0 = 0;k6=1; Song_Tone_Pointer = Song4_Tone;/切换到第四段音乐Song_Time_Pointer = Song4_Time; Song_Index=3; /从第四段音乐的第0个音符开始 i = 0; while (k0=1&k1=1&k2=1&k3=1&k4=1&k5=1&k6=1) Tone_Index = Song_Tone_Pointeri; if ( Tone_Index = 0xFF ) i = 0; DelayMS(2000); /每段音乐播放结束后停顿一段时间 continue; /继续播放 TR0 = 1; DelayM
31、S( Song_Time_Pointer Tone_Index * 240); TR0 = 0; i+;return; void Timer0_Play_Music() interrupt 1 / T0 定时器控制播放 TH0 = Tone_Delay_Table Tone_Index / 256; TL0 = Tone_Delay_Table Tone_Index % 256; BEEP = BEEP; void main() / 主程序 TMOD = 0x01; IE = 0x82; /许可 INTO 和 TO 中断 TR0 = 0; while(1)if(k0=0&k=1) DelayMS(2000); play0();m=1;if(k1=0&k=1) DelayMS(2000); play1();m=1;if(k2=0) DelayMS(2000); play2();if(k3=0&k=1) DelayMS(2000); play3();m=1;if(k4=0&k=1) DelayMS(2000); play4();m=1;if(k5=0&k=1) DelayMS(2000); play5();m=1;if(k6=0&k=1) DelayMS(2000); play6();m=1;附录二:基于单片机的数字音乐盒总电路图