1 设计任务1.1 设计目的和意义本次课程设计是应用单片机原理设计可编程乐曲演奏器的硬件电路,并利用C语言进行程序设计。课程设计的目的就是配合本课程的教学和平时实验,以达到巩固消化课程的内容的目的,进一步加强综合应用能力及单片机应用系统开发和设计能力的训练,启发创新思维,使之具有独立单片机产品和科研的基本技能,是培养综合运用所学知识的过程,是知识转化为能力和能力转化为工程素质的重要阶段。
1.2 设计任务要求可编程乐曲演奏器的设计,具体内容如下:
- 用定时器T0方式1来产生不同频率的方波。
- 由P1.0输出驱动喇叭,演奏最少两段乐曲。
- 有按键切换选择乐曲、开始/暂停。
- 有发光二极管伴随音频脉冲闪烁。
- 数码管显示当前演奏曲目序号。
2 系统硬件电路的设计2.1 总体设计方案2.1.1 总体设计原理通过单片机的定时器产生一定长度的方波,驱动蜂鸣器发声。产生音频脉冲,只需算出某一音频的周期(1/音频),然后取半周期的时间定时。利用定时器计时这个半周期时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期时间再对I/O口反相,就可在I/O脚上得到此频率的脉冲。如中音D0,频率为523HZ,其周期T=1/523=1912微秒,因此只要令计数器定时1912/2=956,在每计数956次时将I/O口反相,就可得到中音D0(523HZ)。
当键盘有键按下时,判断键值,启动计数器T0,产生一定频率的脉冲,由P1口输出驱动蜂鸣器,放出乐曲。通过单片机P0口控制数码管,实现歌曲序号的显示;功能键盘采用按键开关,通过单片机P3口控制,实现歌曲播放顺序的调换和暂停播放功能;彩灯是由普通发光二极管代替,通过单片机P2口控制,实现闪烁效果。
通过按下功能键实现上一首和下一首及开始/暂停播放,同时有数码管显示当前播放歌曲的序号,蜂鸣器播放出音乐,伴有彩灯闪烁。
2.1.2 总体设计框图单片机电源供电后,晶振电路产生单片机所需时钟信号,通过功能键产生外部中断,控制演奏器的上一首和下一首曲目,再由I/O接口输出控制蜂鸣器发声,LED显示,彩灯闪烁。另外,复位电路在于营造一个程序运行的初始状态,在程序出错时,重新启动单片机工作。总体设计框图如图1所示。
图1 总体设计框图
编程设置好定时时间,通过编程器写入AT89C51单片机系统。由AT89C51单片机的定时器每秒钟通过P0.0-P0.7口控制LED数码显示,复位信号由按钮输入,每按下一次,系统恢复原设定状态。电源,晶振部分,复位电路,单片机,LED,功能键,蜂鸣器部分后面均有详细介绍。
2.2 具体电路设计
2.2.1 最小单片机系统
图2 AT89C51系列单片机
单片机最小系统以AT89C51为核心,外加时钟和复位电路,如图2所示。电路结构简单,抗干扰能力强,成本相对较低,非常符合本设计的所有要求.AT89C51单片机系列是在MCS-51系列的基础上发展起来的,是当前8位单片机的典型代表,采用CHMOS工艺,即互补金属氧化物的HMOS工艺, CHMOS是CMOS和HMOS的结合,具有HMOS高速度和高密度的特点,还具有CMOS低功耗的特点.
单片机需要一个时间基准来为各种操作提供秩序,此电路叫时钟电路,采用不同的接线方式可以获得不同时钟电路,有内部时钟电路和外部时钟电路,外部时钟电路会使电路复杂,故采用的是内部时钟电路。时钟电路在单片机的外部通过XTAL1,XTAL2这两个引脚跨接晶体振荡器和微调电容,构成稳定的自激振荡器.本系统采用的为1MHz的晶振,一个机器周期为12us,C1,C2为22pF。
复位电路的基本功能是:系统上电时提供复位信号,直至系统电源稳定后,撤销复位信号。为可靠起见,电源稳定后还要经一定的延时才撤销复位信号,以防电源开关或电源插头分-合过程中引起的抖动而影响复位。
复位电路分为上电自动复位和按键手动复位RST引脚是复位信号的输入端,复位信号是高电平有效.这次采用的是手动复位。复位通过电容C2和电阻R1来实现,按键手动复位是图中复位键来实现的。
2.2.2 发光二极管电路播放歌曲时,单片机通过定时器产生一定长度方波,驱动蜂鸣器发出某个音调,产生音频脉冲,使与之对应的发光二极管亮起。电路如图3所示。
图3 发光二极管电路图
2.2.3 数码管电路播放乐曲时,数码管电路显示当前播放乐曲序号。
乐曲序号显示部分用数码管来显示,LED显示器件是通过发光二极管显示字段的器件。在单片机控制系统中常用的是由7段LED数码管,它的显示块中有8个发光二极管,7个发光二极管组成字符“8”,1个发光二极管构成小数点,因此有人称7段LED数码管为8段显示器。LED数码管的电路图如图4所示。
图4 LED数码管电路图
2.2.4 蜂鸣器电路一般所指的蜂鸣器是以压电陶瓷为主要元件的。压电陶瓷是一类有将压力与电流相互转换能力的特殊陶瓷。这种能力缘于其特殊的晶体结构。当压电陶瓷在一定方向上受到一个压力使其晶体结构发生形变时,它就会在内部产生一个电流,并且电流的变化与压力的变化密切相关。反之亦然。所以利用这一特性,在压电陶瓷上通过一定频率的电流,就会引起压电陶瓷微小形变,这一形变带动空气发生振动,如果频率适当,就可以被人耳所听见,也就是产生了蜂鸣声。
蜂鸣器的作用:蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。
蜂鸣器的分类:蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。
蜂鸣器的电路图形符号:蜂鸣器在电路中用字母“H”或“HA”(旧标准用“FM”、“LB”、“JD”等)表示。
蜂鸣器电路如图5所示。
图5 蜂鸣器电路图
2.2.5 键盘控制电路通过按下功能键实现上一首和下一首及开始/暂停播放。电路如图6所示。
键盘是由一组按压式或触摸式开关构成的阵列,是一种常用的输入设备。键盘可分为编码式键盘和非编码式键盘两种。
非编码键盘常用一些按键排列成行列矩阵,其硬件逻辑与按键编码不存在严格的对应关系,而要由所用的程序来决定。非编码键盘的硬件接口简单,但是要占用较多的CPU时间,通常采用可编程键盘管理芯片来克服这个缺点。本设计使用两种按键,一种是按键式非编码键盘和轻触式非编码开关。
图6 键盘控制电路图
2.3 整体硬件电路
整体硬件电路如图7所示。
图7 整体硬件电路图
2.4 系统所用元器件
表1 本系统所用的元器件
3软件设计3.1 音调、节拍以及编码的确定方法 一般说来,单片机演奏音乐基本都是单音频率,它不包含相应幅度的谐波频率,也就是说不能像电子琴那样能奏出多种音色的声音。因此单片机奏乐只需弄清楚两个概念即可,也就是“音调”和节拍表示一个音符唱多长的时间。
3.1.1 音调的确定
不同音高的乐音是用C、D、E、F、G、A、B来表示,这7个字母就是音乐的音名,它们一般依次唱成DO、RE、MI、FA、SO、LA、SI,即唱成简谱的1、2、3、4、5、6、7,相当于汉字“多来米发梭拉西”的读音,这是唱曲时乐音的发音,所以叫“音调”,即Tone。把C、D、E、F、G、A、B这一组音的距离分成12个等份,每一个等份叫一个“半音”。两个音之间的距离有两个“半音”,就叫“全音”。在钢琴等键盘乐器上,C–D、D–E、F–G、G–A、A–B两音之间隔着一个黑键,他们之间的距离就是全音;E–F、B–C两音之间没有黑键相隔,它们之间的距离就是半音。通常唱成1、2、3、4、5、6、7的音叫自然音,那些在它们的左上角加上﹟号或者b号的叫变化音。﹟叫升记号,表示把音在原来的基础上升高半音,b叫降记音,表示在原来的基础上降低半音。例如高音DO的频率(1046Hz)刚好是中音DO的频率(523Hz)的一倍,中音DO的频率(523Hz)刚好是低音DO频率(266 Hz)的一倍;同样的,高音RE的频率(1175Hz)刚好是中音RE的频率(587Hz)的一倍,中音RE的频率(587Hz)刚好是低音RE频率(294 Hz)的一倍。
要产生音频脉冲,只要算出某一音频的周期(1/频率),然后将此周期除以2,即为半周期的时间。利用定时器计时这半个周期时间,每当计时到后就将输出脉冲的I/O反相,然后重复计时此半周期时间再对I/O反相,就可在I/O脚上得到此频率的脉冲。
利用AT89C51的内部定时器使其工作在计数器模式MODE1下,改变计数值TH0及TL0以产生不同频率的方法。
此外结束符和休止符可以分别用代码00H和FFH来表示,若查表结果为00H,则表示曲子终了;若查表结果为FFH,则产生相应的停顿效果。
例如频率为523Hz,其周期T=1/523=1912us,因此只要令计数器计时956us/1us=956,在每次技术956次时将I/O反相,就可得到中音DO(523Hz)。
计数脉冲值与频率的关系公式如下:
N=Fi

2

Fr
N:计算值; Fi:内部计时一次为1us,故其频率为1MHz;
其计数值的求法如下:
T=65536-N=65536-Fi2Fr
例如:设K=65536,F=1000000=Fi=1MHz,球低音DO(261Hz)。中音DO(523Hz)。高音的DO(1046Hz)的计算值
T=65536-N=65536-Fi2Fr=65536-10000002Fr=65536-500000/Fr
低音DO的T=65536-500000/262=63627
低音DO的T=65536-500000/523=64580
低音DO的T=65536-500000/1047=65059
C调各音符频率与计数值T的对照表如表2所示。
表2 C调各音符频率与计数值T的对照表
3.1.2 节拍的确定
若要构成音乐,光有音调是不够的,还需要节拍,让音乐具有旋律(固定的律动),而且可以调节各个音的快满度。“节拍”,即Beat,简单说就是打拍子,就像我们听音乐不自主的随之拍手或跺脚。若1拍实0.5s,则1/4 拍为0.125s。至于1拍多少s,并没有严格规定,就像人的心跳一样,大部分人的心跳是每分钟72下,有些人快一点,有些人慢一点,只要听的悦耳就好。音持续时间的长短即时值,一般用拍数表示。休止符表示暂停发音。
一首音乐是由许多不同的音符组成的,而每个音符对应着不同频率,这样就可以利用不同的频率的组合,加以与拍数对应的延时,构成音乐。了解音乐的一些基础知识,我们可知产生不同频率的音频脉冲即能产生音乐。对于单片机来说,产生不同频率的脉冲是非常方便的,利用单片机的定时/计数器来产生这样的方波频率信号。因此,需要弄清楚音乐中的音符和对应的频率,以及单片机定时计数的关系。
表3 节拍与节拍码对照
每个音符使用1个字节,字节的高4位代表音符的高低,低4位代表音符的节拍,表3为节拍码的对照。如果1拍为0.4秒,1/4拍实0.1秒,只要设定延迟时间就可求得节拍的时间。假设1/4拍为1DELAY,则1拍应为4DELAY,以此类推。所以只要求得1/4拍的DELAY时间,其余的节拍就是它的倍数,如表4为1/4和1/8节拍的时间设定。
表4 1/4和1/8节拍的时间设定
3.1.3 编码的确定
do re mi fa so la si分别编码为1~7,重音do编为8,重音re编为9,停顿编为0。播放长度以十六分音符为单位(在本程序中为165ms),一拍即四分音符等于4个十六分音符,编为4,其它的播放时间以此类推。音调作为编码的高4位,而播放时间作为低4位,如此音调和节拍就构成了一个编码。以0xff作为曲谱的结束标志。
举例1:音调do,发音长度为两拍,即二分音符,将其编码为0x18。
举例2:音调re,发音长度为半拍,即八分音符,将其编码为0x22
歌曲播放的设计。先将歌曲的简谱进行编码,储存在一个数据类型为unsigned char 的数组中。程序从数组中取出一个数,然后分离出高4位得到音调,接着找出相应的值赋给定时器0,使之定时操作蜂鸣器,得出相应的音调;接着分离出该数的低4位,得到延时时间,接着调用软件延时。
表5 简谱对应的简谱码、T值、节拍数
3.2 软件设计思路定时器初始化后,加载延时函数、乐曲演奏函数、定时器中断函数,按键控制主函数演奏乐曲。乐曲演奏函数控制七首乐曲演奏,并显示当前曲目序号;按键控制切换选择乐曲并控制开始、暂停,发光二极管闪烁。
3.3 主函数的设计主函数流程图如图8所示。
图8 主函数流程图
主函数程序:
void main()
{
while(key3==1);
led1=0;
led2=1;
InitTimer();
while(1)
{
Musics_Play();
if(key1==0)
{
delay1ms(10);
while(key1==0);
music_value++;
if(music_value>7) music_value=1;
}
if(key2==0)
{
delay1ms(10);
while(key2==0);
music_value--;
if(music_value==0) music_value=7;
}
}
}
3.4定时器初始函数的设计void InitTimer(void)
{
TMOD=0x01; //定时器0置于方式一,X=65536-N=
IT0=1;
ET0=1;
EA=1; //打开总中断
}
3.5延时函数的设计void delay150ms(void) /*延时1/4拍时间即150ms*/
{
unsigned char a,b,c;
for(c=3;c>0;c--)
for(b=80;b>0;b--)
{
if(P3!=0xff) {break;}
for(a=214;a>0;a--);
}
}
3.6乐曲演奏函数的设计乐曲演奏函数流程图如图9所示。
图9 乐曲演奏流程图
void Musics_Play()
{
unsigned int j=0,i=0,k=0;
//------------------------音乐选择
switch(music_value)
{
case 1 :song=song1;
led3=1;
P0=tab[1];
delay(50);
break;
.
.
.
//---------------------------节拍音调读取
while(*(song+j)!=0xFF&&cycle_flag)
{
beat=*(song+j)&0x0F; //取出节拍
sound=*(song+j)>>4; //取出音
TH0=tones[2*sound];
TL0=tones[2*sound+1];
TR0=1;
if ((tones[2*sound]==0xFF)&&(tones[2*sound+1]==0xFF)) TR0=0;
for(i=beat;i>0;i--){delay150ms();}
TR0=0;
if(sound>=8) sound=7;
led1=!led1;
led2=!led2;
j++;
k++;
if(k==7) k=0;
}
}
3.7定时器0中断函数的设计void Timer0Interrupt(void) interrupt 1
{
TH0=tones[2*sound];
TL0=tones[2*sound+1];
speaker = !speaker;
}
4系统仿真与调试
4.1 系统软件程序的调试图10 软件程序运行调试图
如图10所示,0 Error(s),0 Warning(s)。运行结果无错,正常运行。
4.2 系统硬件电路的仿真与调试图11 系统硬件电路调试图
如图11所示,最小单片机系统运行正常;驱动蜂鸣器运行正常;数码管显示正常;发光二极管正常闪烁;按键控制正常。
图12 产生方波调试图
如图12所示,单片机正常产生不同频率的方波。
5总结
5.1 本系统的优缺点优点:本系统实现了:
用定时器T0方式1来产生不同频率的方波、由P1.0输出驱动喇叭,演奏最少两段乐曲、有按键切换选择乐曲、开始/暂停、有发光二极管伴随音频脉冲闪烁、数码管显示当前演奏曲目序号等功能。
缺点:
不能显示乐曲名称,功能较少。
5.2 心得体会
单片机的设计至今为止已经进入了令人鼓舞的阶段,在进行了两周时间的摸索与实验,使我不仅仅是掌握单片机入门软件与硬件的常用设计与功能,同时也了解对于一项设计研究的制作过程所需要的详细步骤和具体的实现方法的。
当然在这次宝贵的课程设计活动中,经验才是对于我们最大的收获,而且还增强了自身对未知问题以及对知识的深化认识的能力,用受益匪浅这个词语来概括这次难忘的活动我觉得再合适不过了。但是,光是完成了作品还是不可以自我满足的,在从一开始的时候就怀着将作品制作得更加人性化,更加令人满意,更加地使功能完美又方便地被应用领域这个最终目的下,随着对单片机这门学科的认识加深,到达了拓展的程度,我想这个目的将在不远的时期内被实现。
总之,这次设计从软件编写、调试到软硬件联机调试,我倾注了大量的时间和心血。真是曾经为程序的编写而冥思查找过,曾经为无法找出错误而郁闷苦恼过,也曾经为某一功能不能实现而犹豫彷徨过,但最终我成功了。
我不仅品味到了结果的喜悦,更明白了过程的弥足珍贵。
6参考文献[1] 李建忠.单片机原理及应用[M],西安电子科技大学出版社,2008.2.
[2] 黄智伟.全国大学生电子设计竞赛系统设计[M],北京:北京航空航天大学出版社,2006.6.
[3] 黄智伟.凌阳单片机课程设计指导[M],北京:北京航空航天大学出版社,2006.11.
[4] 李广弟,朱月秀,王秀山.单片机基础[M],北京:北京航空航天大学出版社,2001.7.
[5] 赵曙光,郭万有,杨颂华.可编程逻辑器件原理开发与应用[M],西安:西安电子科技大学, 2000.
[6] 候伯亨.VHDL硬件描述语言与数字逻辑电路设计[M], 西安:西安电子科技大学出版社, 1999.
[7] 康华光. 模拟电子技术基础(第四版)[M], 武汉:华中理工大学出版社,1999.
[8] 谭浩强.C语言程序设计(第二版)[M],北京:清华大学出版社,1991.
[9] 陈小忠,黄宁. 单片机接口技术实用子程序[M],北京:北京人民邮电出版社, 2005.
[10] 欧伟明,周春临,瞿遂春.电子信息系统设计[M],西安电子科技大学出版社,2005.9.
[11] 贾立新,王涌.电子系统设计与实践[M],北京:清华大学出版社,2007.
[12] 罗亚非.凌阳16位单片机应用基础[M],北京:北京航空航天大学出版社,2003.
[13] 雷思孝.凌阳单片机原理及实用技术[M],西安电子科技大学,2004.
附录1
单片机源程序如下:
代码:
- #include<reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
-
- uchar sound,//音
-
- beat,//节拍
-
- music_value=1;//音乐值(播放第几首音乐)
-
- uchar code * data song;
-
- sbit speaker=P1^0;///蜂鸣器
- sbit key1=P3^0;
- sbit key2=P3^1;
- sbit key3=P3^4;
- sbit key4=P3^5;
- sbit led1=P2^0;
- sbit led2=P2^1;
- sbit led3=P2^2;
- uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
-
-
- bit cycle_flag=1;//循环标志位 1允许循环
- // 休止符 低6 低7 中1 中2 中3 中4 中5 中6 中7 高1 低3 低5 低4 高3
- uchar code tones[30]={0xFF,0xFF,0xFB,0x90,0xFC,0x0C,0xFC,0x44,0xFC,0xAC,0xFD,0x09,0xFD,0x34,0xFD,0x82,0xFD,0xC8,0xFE,0x06,0xFE,0x22,0xFA,0X15,0XFB,0x04,0xFA,0x67,0xFE,0x85};
-
- uchar code song1[37]={0xC4,0x12,0x32,0x44,0x42,0x52, //<<祈祷>>
- 0x52,0x44,0x32,0x32,0x12,0x14,
- 0x12,0x12,0x32,0x42,0x54,0x44,
- 0x4F,
- 0xC4,0x12,0x32,0x44,0x42,0x72,
- 0x58,0x42,0x32,0x34,
- 0x14,0x12,0x32,0x34,0x32,0x12,
- 0x1F,
- 0xFF};
- uchar code song2[46]={0x12,0x52,0x52,0x52,0x56,0x42, //<<兰花草>>
- 0x32,0x42,0x32,0x22,0x18,
- 0x82,0x82,0x82,0x82,0x86,0x72,
- 0xB2,0x72,0x72,0x62,0x58,
- 0x52,0x82,0x82,0x72,0x56,0x42,
- 0x32,0x42,0x32,0x22,0x16,0xB2,
- 0xB2,0x32,0x32,0x22,0x16,0x52,
- 0x42,0x32,0x22,0xC2,0x88,
- 0xFF};
- uchar code song3[131]={0x52,0x42, //<<两只蝴蝶>>
- 0x58,0x02,0x42,0x52,0x42,
- 0x38,0x04,0x12,0x32,
- 0x44,0x42,0x52,0x42,0x32,0x12,0x12,
- 0xC8,0x04,0x52,0x42,
- 0x58,0x02,0x42,0x52,0x42,
- 0x38,0x04,0x12,0x32,
- 0x44,0x42,0x52,0x42,0x32,0x12,0x32,
- 0x48,0x04,0x52,0x42,
- 0x58,0x02,0x42,0x52,0x42,
- 0x38,0x04,0x12,0x32,
- 0x44,0x42,0x52,0x42,0x32,0x12,0x11,0x31,
- 0xC8,0x04,0x52,0x72,
- 0x78,0x02,0x72,0x82,0x72,
- 0x58,0x04,0x42,0x42,
- 0x44,0x42,0x52,0x42,0x32,0x12,0x12,
- 0x32,0x32,0x3C,
- 0x09,0x72,0x72,0x82,
- 0xA2,0x92,0x92,0x82,0x52,0x42,0x42,0x42,
- 0x58,0x02,0x52,0x52,0x72,
- 0x84,0x84,0x02,0x12,0x52,0x42,
- 0x48,0x04,0x52,0x72,
- 0x72,0x52,0x74,0x02,0xA4,0x92,
- 0x82,0x92,0x54,0x02,0x82,0x82,0x92,
- 0x82,0x72,0x52,0x42,0x02,0xC4,0x12,
- 0x3C,
- 0xFF};
- uchar code song4[37]={0xC4,0x12,0x32,0x44,0x42,0x52, //<<祈祷>>
- 0x52,0x44,0x32,0x32,0x12,0x14,
- 0x12,0x12,0x32,0x42,0x54,0x44,
- 0x4F,
- 0xC4,0x12,0x32,0x44,0x42,0x72,
- 0x58,0x42,0x32,0x34,
- 0x14,0x12,0x32,0x34,0x32,0x12,
- 0x1F,
- 0xFF};
- uchar code song5[144]={0x52,0x62, //<<阳光总在风雨后>>
- 0x74,0x74,0x74,0x34,
- 0x42,0x34,0x52,0x56,0x42,
- 0x34,0x34,0x14,0x32,0x12,
- 0x12,0xC2,0xC4,0x04,0x52,0x62,
- 0x74,0x74,0x74,0x34,
- 0x42,0x34,0x52,0x56,0x42,
- 0x34,0x32,0x12,0x12,0x34,0x42,
- 0x4C,0x52,0x42,
- 0x34,0x32,0x42,0x32,0x12,0x12,0xC2,
- 0xC2,0x54,0x52,0x54,0x52,0x52,
- 0x42,0x32,0x32,0x12,0x32,0x42,0x32,0x52,
- 0x5C,0x52,0x42,
- 0x34,0x32,0x42,0x32,0x12,0x12,0xC2,
- 0xC2,0x54,0x52,0x54,0x02,0x52,
- 0x52,0x42,0x32,0x12,0x32,0x84,0x72,
- 0x7F,
- 0x0F,
- 0x74,0x72,0x52,0x54,0x74,
- 0x82,0x52,0x52,0x72,0x78,
- 0x34,0x32,0x32,0x42,0x54,0x72,
- 0x7F,
- 0x86,0x82,0x72,0x52,0x54,
- 0x72,0x84,0x32,0x36,0x52,
- 0x42,0x52,0x42,0x32,0x34,0x12,0x32,
- 0x32,0x42,0x4C,
- 0x86,0x82,0x72,0x52,0x54,
- 0x72,0x84,0x52,0x56,0x52,
- 0x42,0x52,0x72,0x82,0x52,0x34,0x12,
- 0x12,0x32,0x3C,
- 0xFF};
- uchar code song6[77]={0xC2,0xC2,0x34,0x42,0x42, //<<一生有你>>
- 0x52,0x41,0x51,0x5C,
- 0x04,0xC2,0xC2,0x34,0x42,0x42,
- 0x52,0x31,0x41,0x4C,
- 0x04,0xC2,0xC2,0x34,0x42,0x42,
- 0x52,0x41,0x51,0x58,0x32,0x52,
- 0x4C,0x42,0x32,
- 0x34,0x32,0x42,0x48,
- 0x04,0xC2,0xC2,0x34,0x42,0x42,
- 0x72,0x41,0x51,0x5C,
- 0x04,0xC2,0xC2,0x32,0x32,0x42,0x42,
- 0x52,0x42,0x4C,
- 0x04,0xC2,0xC2,0x34,0x42,0x42,
- 0x52,0x41,0x51,0x58,0x32,0x52,
- 0x4C,0x42,0x32,
- 0x32,0x42,0x4C,
- 0xFF};
- uchar code song7[]={0XC2,0XB2, //<<喜欢你>>
- 0X36,0X52,0X42,0X32,0X11,0XC1,0XB2,
- 0XC6,0X12,0XC4,0X12,0XC2,
- 0X76,0XA2,0X82,0X72,0X51,0X41,0X32,
- 0X4C,0X42,0X32,
- 0X74,0X82,0X74,0X82,0X72,
- 0X52,0X41,0X38,0X32,0X42,
- 0X16,0XC2,0X72,0X52,0X42,0X42,
- 0X3C,0XC2,0XB2,
- 0X36,0X52,0X42,0X32,0X11,0XC1,0XB2,
- 0XC6,0X12,0XC4,0X12,0XC2,
- 0X76,0XA2,0X82,0X72,0X51,0X41,0X32,
- 0X4C,0X42,0X32,
- 0X76,0X82,0X74,0X82,0X72,
- 0X53,0X41,0X38,0X32,0X42,
- 0X16,0XC2,0X72,0X52,0X41,0X51,0X12,
- 0XCC,0XC2,0XB2,
- 0X16,0XC2,0X72,0X52,0X42,0X42,
- 0X3C,0X32,0X32,
- 0X26,0X22,0X24,0X42,0X32,
- 0x22,0x12,0x18,0x02,0x52,
- 0X46,0X12,0X44,0X72,0X82,
- 0X5C,0X52,0X52,
- 0X46,0X42,0X74,0X42,0X32,
- 0X36,0X42,0X58,
- 0X82,0X72,0X62,0X52,0X46,0X32,
- 0X3C,0X12,0XB2,
- 0X36,0X52,0X42,0X32,0X11,0XC1,0XB2,
- 0XC6,0X12,0XC4,0X12,0XC2,
- 0X76,0XA2,0X82,0X72,0X51,0X41,0X32,
- 0X48,0X02,0X42,0X52,0X62,
- 0X76,0X82,0X74,0X82,0X72,
- 0X56,0X41,0X38,0X32,0X22,
- 0X16,0XC2,0X72,0X52,0X42,0X42,
- 0X3C,0X04,0X04,0X04,0X04,
- 0xFF};
-
-
-
- void delay150ms(void) /*延时1/4拍时间即150ms*/
- {
- unsigned char a,b,c;
-
- for(c=3;c>0;c--)
- for(b=80;b>0;b--)
- {
- if(P3!=0xff) {break;}
- for(a=214;a>0;a--);
- }
-
- }
-
- /**************************************
-
- *名称: InitTimer(void)
-
- *功能:定时器初始化函数
-
- ***************************************/
- void InitTimer(void)
- {
- TMOD=0x01; //定时器0置于方式一
-
- IT0=1;
-
- ET0=1;
-
- EA=1; //打开总中断
-
- }
- /**************************************
-
- *名称:Music_Play()
-
- *功能:乐曲演奏函数
-
- ***************************************/
- void delay(uint i)
- {
- uchar j;
- for(i;i>0;i--)
- for(j=115;j>0;j--);
- }
-
- void Musics_Play()
- {
- unsigned int j=0,i=0,k=0;
- //------------------------音乐选择
- switch(music_value)
- {
- case 1 :song=song1;
- led3=1;
- P0=tab[1];
- delay(50);
- break;
- case 2 :song=song2;
- led3=1;
- P0=tab[2];
- delay(50);
- break;
- case 3 :song=song3;
- led3=1;
- P0=tab[3];
- delay(50);
- break;
- case 4 :song=song4;
- led3=1;
- P0=tab[4];
- delay(50);
- break;
- case 5 :song=song5;
- led3=1;
- P0=tab[5];
- delay(50);
- break;
- case 6 :song=song6;
- led3=1;
- P0=tab[6];
- delay(50);
- break;
- case 7 :song=song7;
- led3=1;
- P0=tab[7];
- delay(50);
- break;
- }
- //---------------------------节拍音调读取
-
- while(*(song+j)!=0xFF&&cycle_flag)
- {
- beat=*(song+j)&0x0F; //取出节拍
- sound=*(song+j)>>4; //取出音
- TH0=tones[2*sound];
- TL0=tones[2*sound+1];
- TR0=1;
- if ((tones[2*sound]==0xFF)&&(tones[2*sound+1]==0xFF)) TR0=0;
- for(i=beat;i>0;i--){delay150ms();}
- TR0=0;
- if(sound>=8) sound=7;
- led1=!led1;
- led2=!led2;
- j++;
- k++;
- if(k==7) k=0;
- }
- }
- void delay1ms(int t) //1ms延时函数
- {
- int i,j;
- for (i=0;i<t;i++)
- for(j=0;j<120;j++);
- }
- void main()
- {
- while(key3==1);
- led1=0;
- led2=1;
- InitTimer();
- while(1)
- {
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
所有资料51hei提供下载: