变频救护车
#include<reg52.h>//包含访问sfr库函数 #define uchar unsigned char //定义一下方便使用 #define uint unsigned int #define ulong unsigned long sbit BEEP=P1^0; sbit K1=P3^2; //变频声救护车报警信号输出试验 main() { uint n; ulong ul; while(1) //程序循环 { //输出约 1 秒种一个频率的声音 for(ul=0;ul<3000;ul++) { for(n=0;n<80;n++); //延时 BEEP=~BEEP; //取反输出到喇叭的信号 } //输出约 1 秒种另一个频率的声音 for(ul=0;ul<2500;ul++) { for(n=0;n<100;n++); //延时 BEEP=~BEEP; //取反输出到喇叭的信号 } } }
音阶声音自动输出试验
#include<reg52.h>//包含访问sfr库函数 #define uchar unsigned char //定义一下方便使用 #define uint unsigned int #define ulong unsigned long sbit BEEP=P1^0; uchar th0_f; //在中断中装载的 T0 的值高 8 位 uchar tl0_f; //在中断中装载的 T0 的值低 8 位 //T0 的值,及输出频率对照表 uchar code freq[36*2]={ 0xA9,0xEF,//00220HZ ,1 //0 0x93,0xF0,//00233HZ ,1# 0x73,0xF1,//00247HZ ,2 0x49,0xF2,//00262HZ ,2# 0x07,0xF3,//00277HZ ,3 0xC8,0xF3,//00294HZ ,4 0x73,0xF4,//00311HZ ,4# 0x1E,0xF5,//00330HZ ,5 0xB6,0xF5,//00349HZ ,5# 0x4C,0xF6,//00370HZ ,6 0xD7,0xF6,//00392HZ ,6# 0x5A,0xF7,//00415HZ ,7 0xD8,0xF7,//00440HZ 1 //12 0x4D,0xF8,//00466HZ 1# //13 0xBD,0xF8,//00494HZ 2 //14 0x24,0xF9,//00523HZ 2# //15 0x87,0xF9,//00554HZ 3 //16 0xE4,0xF9,//00587HZ 4 //17 0x3D,0xFA,//00622HZ 4# //18 0x90,0xFA,//00659HZ 5 //19 0xDE,0xFA,//00698HZ 5# //20 0x29,0xFB,//00740HZ 6 //21 0x6F,0xFB,//00784HZ 6# //22 0xB1,0xFB,//00831HZ 7 //23 0xEF,0xFB,//00880HZ `1 0x2A,0xFC,//00932HZ `1# 0x62,0xFC,//00988HZ `2 0x95,0xFC,//01046HZ `2# 0xC7,0xFC,//01109HZ `3 0xF6,0xFC,//01175HZ `4 0x22,0xFD,//01244HZ `4# 0x4B,0xFD,//01318HZ `5 0x73,0xFD,//01397HZ `5# 0x98,0xFD,//01480HZ `6 0xBB,0xFD,//01568HZ `6# 0xDC,0xFD,//01661HZ `7 //35 }; //定时中断 0,用于产生唱歌频率 timer0() interrupt 1 { TL0=tl0_f;TH0=th0_f; //调入预定时值 BEEP=~BEEP; //取反音乐输出 IO } //音阶声音自动输出试验 void main(void) // 主程序 { ulong n; uchar i; uchar code jie8[8]={12,14,16,17,19,21,23,24};//1234567`1 八个音符在频率表中的位置 TMOD = 0x01; //使用定时器 0 的 16 位工作模式 TR0 = 1; ET0 = 1; EA = 1; while(1) { for(i=0;i<8;i++) //循环播放 8 个音符 { tl0_f=freq[jie8[i]*2]; //置一个音符的值 th0_f=freq[jie8[i]*2+1]; for(n=0;n<50000;n++); //延时 1 秒左右 } } }
按键控制音阶声音输出(电子琴)
#include<reg52.h>//包含访问sfr库函数 #define uchar unsigned char //定义一下方便使用 #define uint unsigned int #define ulong unsigned long sbit BEEP=P1^0; //喇叭输出脚 sbit K1= P3^2; sbit K2= P3^3; sbit K3= P3^4; sbit K4= P3^5; uchar th0_f; //在中断中装载的 T0 的值高 8 位 uchar tl0_f; //在中断中装载的 T0 的值低 8 位 //T0 的值,及输出频率对照表 uchar code freq[36*2]={ 0xA9,0xEF,//00220HZ ,1 //0 0x93,0xF0,//00233HZ ,1# 0x73,0xF1,//00247HZ ,2 0x49,0xF2,//00262HZ ,2# 0x07,0xF3,//00277HZ ,3 0xC8,0xF3,//00294HZ ,4 0x73,0xF4,//00311HZ ,4# 0x1E,0xF5,//00330HZ ,5 0xB6,0xF5,//00349HZ ,5# 0x4C,0xF6,//00370HZ ,6 0xD7,0xF6,//00392HZ ,6# 0x5A,0xF7,//00415HZ ,7 0xD8,0xF7,//00440HZ 1 //12 0x4D,0xF8,//00466HZ 1# //13 0xBD,0xF8,//00494HZ 2 //14 0x24,0xF9,//00523HZ 2# //15 0x87,0xF9,//00554HZ 3 //16 0xE4,0xF9,//00587HZ 4 //17 0x3D,0xFA,//00622HZ 4# //18 0x90,0xFA,//00659HZ 5 //19 0xDE,0xFA,//00698HZ 5# //20 0x29,0xFB,//00740HZ 6 //21 0x6F,0xFB,//00784HZ 6# //22 0xB1,0xFB,//00831HZ 7 //23 0xEF,0xFB,//00880HZ `1 0x2A,0xFC,//00932HZ `1# 0x62,0xFC,//00988HZ `2 0x95,0xFC,//01046HZ `2# 0xC7,0xFC,//01109HZ `3 0xF6,0xFC,//01175HZ `4 0x22,0xFD,//01244HZ `4# 0x4B,0xFD,//01318HZ `5 0x73,0xFD,//01397HZ `5# 0x98,0xFD,//01480HZ `6 0xBB,0xFD,//01568HZ `6# 0xDC,0xFD,//01661HZ `7 //35 }; //定时中断 0,用于产生唱歌频率 timer0() interrupt 1 { TL0=tl0_f;TH0=th0_f; //调入预定时值 BEEP=~BEEP; //取反音乐输出 IO } //按键控制音阶声音输出(电子琴) void main(void) // 主程序 { ulong n; uchar code jie8[8]={12,14,16,17,19,21,23,24};//1234567`1 八个音符在频率表中的位置 TMOD = 0x01; //使用定时器 0 的 16 位工作模式 TR0 = 0; ET0 = 1; EA = 1; while(1) { if(!K1) { tl0_f=freq[jie8[0]*2]; //置一个音符的值 th0_f=freq[jie8[0]*2+1]; TR0 = 1; for(n=0;n<10000;n++); //延时 } if(!K2) { tl0_f=freq[jie8[1]*2]; //置一个音符的值 th0_f=freq[jie8[1]*2+1]; TR0 = 1; for(n=0;n<10000;n++); //延时 } if(!K3) { tl0_f=freq[jie8[2]*2]; //置一个音符的值 th0_f=freq[jie8[2]*2+1]; TR0 = 1; for(n=0;n<10000;n++); //延时 } if(!K4) { tl0_f=freq[jie8[3]*2]; //置一个音符的值 th0_f=freq[jie8[3]*2+1]; TR0 = 1; for(n=0;n<10000;n++); //延时 } TR0 = 0; } }
乐谱方式输入的音乐播放,仙剑奇侠传
乐谱解释函数,是逐个字符解释的。
遇到拍子分隔符和空格跳过,判断是否高低音,读音符,调整为高低音音符,读音符后的升半个音符的“#”,读延长音“-”“.”,读缩短一半音长的“_”,字符串结束符“0x00”。请仔细领会这个函数。
奏乐函数就比较简单,基本上就是从数组中取出音符和时长,送入定时器预置数,再延时即可。在每个音符播放前后,用 TR0 控制是否输出音乐,每个音符之间也有短暂静音,以使音乐更为清晰。
在本程序中,播放音乐函数中,我们使用了 xdata 的空间的 RAM,这是因为乐谱的数据需要比较多的内存,data 和 idata 空间已经放不下了的原因。
如果你把这个程序烧写到一片没有 XRAM 的芯片中,比如 at89c52 之类,就会出现无法运行的现象。在使用没有 XRAM 的 51 芯片时,如果使用了 XRAM,则要在总线上外加一个内存芯片,比如 62256
之类。
完全看懂了程序之后,请编译运行,观察结果。按全速,可以听到美妙的仙剑音乐从蜂鸣器中传出,真是太奇妙了
#include<reg52.h>//包含访问sfr库函数 #define uchar unsigned char //定义一下方便使用 #define uint unsigned int #define ulong unsigned long sbit BEEP=P1^0; //喇叭输出脚 sbit K1= P3^2; sbit K2= P3^3; sbit K3= P3^4; sbit K4= P3^5; uchar th0_f; //在中断中装载的 T0 的值高 8 位 uchar tl0_f; //在中断中装载的 T0 的值低 8 位 //T0 的值,及输出频率对照表 uchar code freq[36*2]={ 0xA9,0xEF,//00220HZ ,1 //0 0x93,0xF0,//00233HZ ,1# 0x73,0xF1,//00247HZ ,2 0x49,0xF2,//00262HZ ,2# 0x07,0xF3,//00277HZ ,3 0xC8,0xF3,//00294HZ ,4 0x73,0xF4,//00311HZ ,4# 0x1E,0xF5,//00330HZ ,5 0xB6,0xF5,//00349HZ ,5# 0x4C,0xF6,//00370HZ ,6 0xD7,0xF6,//00392HZ ,6# 0x5A,0xF7,//00415HZ ,7 0xD8,0xF7,//00440HZ 1 //12 0x4D,0xF8,//00466HZ 1# //13 0xBD,0xF8,//00494HZ 2 //14 0x24,0xF9,//00523HZ 2# //15 0x87,0xF9,//00554HZ 3 //16 0xE4,0xF9,//00587HZ 4 //17 0x3D,0xFA,//00622HZ 4# //18 0x90,0xFA,//00659HZ 5 //19 0xDE,0xFA,//00698HZ 5# //20 0x29,0xFB,//00740HZ 6 //21 0x6F,0xFB,//00784HZ 6# //22 0xB1,0xFB,//00831HZ 7 //23 0xEF,0xFB,//00880HZ `1 0x2A,0xFC,//00932HZ `1# 0x62,0xFC,//00988HZ `2 0x95,0xFC,//01046HZ `2# 0xC7,0xFC,//01109HZ `3 0xF6,0xFC,//01175HZ `4 0x22,0xFD,//01244HZ `4# 0x4B,0xFD,//01318HZ `5 0x73,0xFD,//01397HZ `5# 0x98,0xFD,//01480HZ `6 0xBB,0xFD,//01568HZ `6# 0xDC,0xFD,//01661HZ `7 //35 }; //定时中断 0,用于产生唱歌频率 timer0() interrupt 1 { TL0=tl0_f;TH0=th0_f; //调入预定时值 BEEP=~BEEP; //取反音乐输出 IO } //****************************** //音乐符号串解释函数 //入口:要解释的音乐符号串,输出的音调串,输出的时长串 changedata(uchar *song,uchar *diao,uchar *jie) { uchar i,i1,j; char gaodi; //高低+/-12 音阶 uchar banyin;//有没有半个升音阶 uchar yinchang;//音长 uchar code jie7[8]={0,12,14,16,17,19,21,23}; //C 调的 7 个值 *diao=*song; for(i=0,i1=0;;) { gaodi=0; //高低=0 banyin=0;//半音=0 yinchang=4;//音长 1 拍 if((*(song+i)=='|') || (*(song+i)==' ')) i++; //拍子间隔和一个空格过滤 switch(*(song+i)) { case ',': gaodi=-12;i++;//低音 break; case '`': gaodi=12;i++; //高音 break; } if(*(song+i)==0) //遇到 0 结束 { *(diao+i1)=0; //加入结束标志 0 *(jie+i1)=0; return; } j=*(song+i)-0x30; i++; //取出基准音 j=jie7[j]+gaodi; //加上高低音 yinc: switch(*(song+i)) { case '#': //有半音 j 加一个音阶 i++;j++; goto yinc; case '-': //有一个音节加长 yinchang+=4; i++; goto yinc; case '_': //有一个音节缩短 yinchang/=2; i++; goto yinc; case '.': //有一个加半拍 yinchang=yinchang+yinchang/2; i++; goto yinc; } *(diao+i1)=j; //记录音符 *(jie+i1)=yinchang; //记录音长 i1++; } } //****************************************** //奏乐函数 //入口:要演奏的音乐符号串 void play(uchar *songdata) { uchar i,c,j=0; uint n; uchar xdata diaodata[112]; //音调缓冲 uchar xdata jiedata[112]; //音长缓冲 changedata(songdata,diaodata,jiedata); //解释音乐符号串 TR0=1; for(i=0;diaodata[i]!=0;i++) //逐个符号演奏 { tl0_f=freq[diaodata[i]*2]; //取出对应的定时值送给 T0 th0_f=freq[diaodata[i]*2+1]; for(c=0;c<jiedata[i];c++) //按照音长延时 for(n=0;n<32000;n++); TR0=0; for(n=0;n<500;n++); //音符间延时 TR0=1; } TR0=0; } //仙剑 uchar code xianjian[]={ "|3_3_3_2_3-|2_3_2_2_,6,6_,7_|12_1_,7,6_,5_|,6---|" "3_3_3_2_3.6_|5_6_5_5_22_3_|45_4_32_1_|3.--3_|" "67_6_55_3_|5--3_5_|26_5_32_3_|3---|" "26_6_6-|16_6_66_7_|`17_6_76_7_|3.--3_|" "67_6_55_3_|5--3_5_|67_6_76_7_|3---|" "26_6_6-|16_6_66_7_|`17_6_7.5_|6---|" }; //乐谱方式输入的音乐播放,仙剑奇侠传 void main(void) // 主程序 { TMOD = 0x01; //使用定时器 0 的 16 位工作模式 TR0 = 0; ET0 = 1; EA = 1; while(1) { play(xianjian); } }
四个按键控制
#include<reg52.h>//包含访问sfr库函数 #define uchar unsigned char //定义一下方便使用 #define uint unsigned int #define ulong unsigned long sbit BEEP=P1^0; //喇叭输出脚 sbit P10=P1^1;//灯 sbit K1= P3^2; sbit K2= P3^3; sbit K3= P3^4; sbit K4= P3^5; uchar th0_f; //在中断中装载的 T0 的值高 8 位 uchar tl0_f; //在中断中装载的 T0 的值低 8 位 //T0 的值,及输出频率对照表 uchar code freq[36*2]={ 0xA9,0xEF,//00220HZ ,1 //0 0x93,0xF0,//00233HZ ,1# 0x73,0xF1,//00247HZ ,2 0x49,0xF2,//00262HZ ,2# 0x07,0xF3,//00277HZ ,3 0xC8,0xF3,//00294HZ ,4 0x73,0xF4,//00311HZ ,4# 0x1E,0xF5,//00330HZ ,5 0xB6,0xF5,//00349HZ ,5# 0x4C,0xF6,//00370HZ ,6 0xD7,0xF6,//00392HZ ,6# 0x5A,0xF7,//00415HZ ,7 0xD8,0xF7,//00440HZ 1 //12 0x4D,0xF8,//00466HZ 1# //13 0xBD,0xF8,//00494HZ 2 //14 0x24,0xF9,//00523HZ 2# //15 0x87,0xF9,//00554HZ 3 //16 0xE4,0xF9,//00587HZ 4 //17 0x3D,0xFA,//00622HZ 4# //18 0x90,0xFA,//00659HZ 5 //19 0xDE,0xFA,//00698HZ 5# //20 0x29,0xFB,//00740HZ 6 //21 0x6F,0xFB,//00784HZ 6# //22 0xB1,0xFB,//00831HZ 7 //23 0xEF,0xFB,//00880HZ `1 0x2A,0xFC,//00932HZ `1# 0x62,0xFC,//00988HZ `2 0x95,0xFC,//01046HZ `2# 0xC7,0xFC,//01109HZ `3 0xF6,0xFC,//01175HZ `4 0x22,0xFD,//01244HZ `4# 0x4B,0xFD,//01318HZ `5 0x73,0xFD,//01397HZ `5# 0x98,0xFD,//01480HZ `6 0xBB,0xFD,//01568HZ `6# 0xDC,0xFD,//01661HZ `7 //35 }; //定时中断 0,用于产生唱歌频率 timer0() interrupt 1 { TL0=tl0_f;TH0=th0_f; //调入预定时值 BEEP=~BEEP; //取反音乐输出 IO } //****************************** //音乐符号串解释函数 //入口:要解释的音乐符号串,输出的音调串,输出的时长串 changedata(uchar *song,uchar *diao,uchar *jie) { uchar i,i1,j; char gaodi; //高低+/-12 音阶 uchar banyin;//有没有半个升音阶 uchar yinchang;//音长 uchar code jie7[8]={0,12,14,16,17,19,21,23}; //C 调的 7 个值 *diao=*song; for(i=0,i1=0;;) { gaodi=0; //高低=0 banyin=0;//半音=0 yinchang=4;//音长 1 拍 if((*(song+i)=='|') || (*(song+i)==' ')) i++; //拍子间隔和一个空格过滤 switch(*(song+i)) { case ',': gaodi=-12;i++;//低音 break; case '`': gaodi=12;i++; //高音 break; } if(*(song+i)==0) //遇到 0 结束 { *(diao+i1)=0; //加入结束标志 0 *(jie+i1)=0; return; } j=*(song+i)-0x30; i++; //取出基准音 j=jie7[j]+gaodi; //加上高低音 yinc: switch(*(song+i)) { case '#': //有半音 j 加一个音阶 i++;j++; goto yinc; case '-': //有一个音节加长 yinchang+=4; i++; goto yinc; case '_': //有一个音节缩短 yinchang/=2; i++; goto yinc; case '.': //有一个加半拍 yinchang=yinchang+yinchang/2; i++; goto yinc; } *(diao+i1)=j; //记录音符 *(jie+i1)=yinchang; //记录音长 i1++; } } //****************************************** //奏乐函数 //入口:要演奏的音乐符号串 void play(uchar *songdata) { uchar i,c,j=0; uint n; uchar xdata diaodata[112]; //音调缓冲 uchar xdata jiedata[112]; //音长缓冲 changedata(songdata,diaodata,jiedata); //解释音乐符号串 TR0=1; for(i=0;diaodata[i]!=0;i++) //逐个符号演奏 { tl0_f=freq[diaodata[i]*2]; //取出对应的定时值送给 T0 th0_f=freq[diaodata[i]*2+1]; for(c=0;c<jiedata[i];c++) //按照音长延时 { for(n=0;n<32000;n++); if((!K1)||(!K2)||(!K3)||(!K4))//发现按键,立即退出播放 { TR0=0; return; } } TR0=0; for(n=0;n<500;n++); //音符间延时 TR0=1; } TR0=0; } //仙剑 uchar code xianjian[]={ "|3_3_3_2_3-|2_3_2_2_,6,6_,7_|12_1_,7,6_,5_|,6---|" "3_3_3_2_3.6_|5_6_5_5_22_3_|45_4_32_1_|3.--3_|" "67_6_55_3_|5--3_5_|26_5_32_3_|3---|" "26_6_6-|16_6_66_7_|`17_6_76_7_|3.--3_|" "67_6_55_3_|5--3_5_|67_6_76_7_|3---|" "26_6_6-|16_6_66_7_|`17_6_7.5_|6---|" }; uchar code song3[]={ "5-5_3_2_1_|3---|6-6_4_2_1_" ",7--,5_|1.3_5.1_|,7.3_5 5_|" "6.7_`1.6_|6_5_5-3_2_|1.1_13_2_|" "1.1_12_3_|2.1_,62_3_|2-- ,5_|" "1.3_5.1_|,7.3_55_|6.7_`1.6_|" "6_5_5-3_2_|1.1_13_2_|1.1_12_3_" "2.,6_,71_2_|1--" }; //世上只有妈妈好 uchar code mamahao[]={ "6.5_35|`16_5_6-|35_6_53_2_|1_,6_5_3_2-|" "2.3_55_6_|321-|5.3_2_1_,6_1_|,5--" }; void main(void) // 主程序 { TMOD = 0x01; //使用定时器 0 的 16 位工作模式 TR0 = 0; ET0 = 1; //定时器 0 中断 EA = 1; //打开总中断 while(1) { if(!K1) { while(!K1); play(xianjian); //播放音乐 } if(!K2) { while(!K2); play(song3); //播放音乐 } if(!K3) { while(!K3); play(mamahao); //播放音乐 } } }
一个按键切换播放
#include<reg52.h>//包含访问sfr库函数 #define uchar unsigned char //定义一下方便使用 #define uint unsigned int #define ulong unsigned long sbit BEEP=P1^0; //喇叭输出脚 sbit P10=P1^1;//灯 sbit K1= P3^2; sbit K2= P3^3; sbit K3= P3^4; sbit K4= P3^5; uchar th0_f; //在中断中装载的 T0 的值高 8 位 uchar tl0_f; //在中断中装载的 T0 的值低 8 位 //T0 的值,及输出频率对照表 uchar code freq[36*2]={ 0xA9,0xEF,//00220HZ ,1 //0 0x93,0xF0,//00233HZ ,1# 0x73,0xF1,//00247HZ ,2 0x49,0xF2,//00262HZ ,2# 0x07,0xF3,//00277HZ ,3 0xC8,0xF3,//00294HZ ,4 0x73,0xF4,//00311HZ ,4# 0x1E,0xF5,//00330HZ ,5 0xB6,0xF5,//00349HZ ,5# 0x4C,0xF6,//00370HZ ,6 0xD7,0xF6,//00392HZ ,6# 0x5A,0xF7,//00415HZ ,7 0xD8,0xF7,//00440HZ 1 //12 0x4D,0xF8,//00466HZ 1# //13 0xBD,0xF8,//00494HZ 2 //14 0x24,0xF9,//00523HZ 2# //15 0x87,0xF9,//00554HZ 3 //16 0xE4,0xF9,//00587HZ 4 //17 0x3D,0xFA,//00622HZ 4# //18 0x90,0xFA,//00659HZ 5 //19 0xDE,0xFA,//00698HZ 5# //20 0x29,0xFB,//00740HZ 6 //21 0x6F,0xFB,//00784HZ 6# //22 0xB1,0xFB,//00831HZ 7 //23 0xEF,0xFB,//00880HZ `1 0x2A,0xFC,//00932HZ `1# 0x62,0xFC,//00988HZ `2 0x95,0xFC,//01046HZ `2# 0xC7,0xFC,//01109HZ `3 0xF6,0xFC,//01175HZ `4 0x22,0xFD,//01244HZ `4# 0x4B,0xFD,//01318HZ `5 0x73,0xFD,//01397HZ `5# 0x98,0xFD,//01480HZ `6 0xBB,0xFD,//01568HZ `6# 0xDC,0xFD,//01661HZ `7 //35 }; //定时中断 0,用于产生唱歌频率 timer0() interrupt 1 { TL0=tl0_f;TH0=th0_f; //调入预定时值 BEEP=~BEEP; //取反音乐输出 IO } //****************************** //音乐符号串解释函数 //入口:要解释的音乐符号串,输出的音调串,输出的时长串 changedata(uchar *song,uchar *diao,uchar *jie) { uchar i,i1,j; char gaodi; //高低+/-12 音阶 uchar banyin;//有没有半个升音阶 uchar yinchang;//音长 uchar code jie7[8]={0,12,14,16,17,19,21,23}; //C 调的 7 个值 *diao=*song; for(i=0,i1=0;;) { gaodi=0; //高低=0 banyin=0;//半音=0 yinchang=4;//音长 1 拍 if((*(song+i)=='|') || (*(song+i)==' ')) i++; //拍子间隔和一个空格过滤 switch(*(song+i)) { case ',': gaodi=-12;i++;//低音 break; case '`': gaodi=12;i++; //高音 break; } if(*(song+i)==0) //遇到 0 结束 { *(diao+i1)=0; //加入结束标志 0 *(jie+i1)=0; return; } j=*(song+i)-0x30; i++; //取出基准音 j=jie7[j]+gaodi; //加上高低音 yinc: switch(*(song+i)) { case '#': //有半音 j 加一个音阶 i++;j++; goto yinc; case '-': //有一个音节加长 yinchang+=4; i++; goto yinc; case '_': //有一个音节缩短 yinchang/=2; i++; goto yinc; case '.': //有一个加半拍 yinchang=yinchang+yinchang/2; i++; goto yinc; } *(diao+i1)=j; //记录音符 *(jie+i1)=yinchang; //记录音长 i1++; } } //****************************************** //奏乐函数 //入口:要演奏的音乐符号串 void play(uchar *songdata) { uchar i,c,j=0; uint n; uchar xdata diaodata[112]; //音调缓冲 uchar xdata jiedata[112]; //音长缓冲 changedata(songdata,diaodata,jiedata); //解释音乐符号串 TR0=1; for(i=0;diaodata[i]!=0;i++) //逐个符号演奏 { tl0_f=freq[diaodata[i]*2]; //取出对应的定时值送给 T0 th0_f=freq[diaodata[i]*2+1]; for(c=0;c<jiedata[i];c++) //按照音长延时 { for(n=0;n<32000;n++); if((!K1)||(!K2)||(!K3)||(!K4))//发现按键,立即退出播放 { TR0=0; return; } } TR0=0; for(n=0;n<500;n++); //音符间延时 TR0=1; } TR0=0; } //仙剑 uchar code xianjian[]={ "|3_3_3_2_3-|2_3_2_2_,6,6_,7_|12_1_,7,6_,5_|,6---|" "3_3_3_2_3.6_|5_6_5_5_22_3_|45_4_32_1_|3.--3_|" "67_6_55_3_|5--3_5_|26_5_32_3_|3---|" "26_6_6-|16_6_66_7_|`17_6_76_7_|3.--3_|" "67_6_55_3_|5--3_5_|67_6_76_7_|3---|" "26_6_6-|16_6_66_7_|`17_6_7.5_|6---|" }; uchar code song3[]={ "5-5_3_2_1_|3---|6-6_4_2_1_" ",7--,5_|1.3_5.1_|,7.3_5 5_|" "6.7_`1.6_|6_5_5-3_2_|1.1_13_2_|" "1.1_12_3_|2.1_,62_3_|2-- ,5_|" "1.3_5.1_|,7.3_55_|6.7_`1.6_|" "6_5_5-3_2_|1.1_13_2_|1.1_12_3_" "2.,6_,71_2_|1--" }; //世上只有妈妈好 uchar code mamahao[]={ "6.5_35|`16_5_6-|35_6_53_2_|1_,6_5_3_2-|" "2.3_55_6_|321-|5.3_2_1_,6_1_|,5--" }; //我是一只菠萝 uchar code boluo[]={ "1-|2_4_3_2_55|5_6_3_4_22|2_4_3_2_1_`1_7_6_|5_4_2_3_11|" "2_4_3_2_55|5_6_3_4_22|2_4_3_2_1_5_2_3_|1---|" }; //小星星 uchar code xingxing[]={ "1155|665-|4433|221-|" "5544|332-|5544|332-|" "1155|665-|4433|221-|" }; //老鼠爱大米 uchar code dami[]={ "321-|3.2_1-|3231|3_6.5-|3_5_665|65-3_2_|122_3_2|12--|" }; void main(void) // 主程序 { uchar i; TMOD = 0x01; //使用定时器 0 的 16 位工作模式 TR0 = 0; ET0 = 1; //定时器 0 中断 EA = 1; //打开总中断 while(1) { if(!K1) { while(!K1); switch(i) { case 0: play(xianjian); //播放音乐 break; case 1: play(song3); //播放音乐 break; case 2: play(mamahao); //播放音乐 break; case 3: play(boluo); //播放音乐 break; case 4: play(xingxing); //播放音乐 break; case 5: play(dami); //播放音乐 break; } i++;if(i==6)i=0; } } }
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器 sbit sound=P1^0; //将sound位定义为P3.7 unsigned int C; //储存定时器的定时常数 //以下是C调低音的音频宏定义 #define l_dao 262 //将“l_dao”宏定义为低音“1”的频率262Hz #define l_re 286 //将“l_re”宏定义为低音“2”的频率286Hz #define l_mi 311 //将“l_mi”宏定义为低音“3”的频率311Hz #define l_fa 349 //将“l_fa”宏定义为低音“4”的频率349Hz #define l_sao 392 //将“l_sao”宏定义为低音“5”的频率392Hz #define l_la 440 //将“l_a”宏定义为低音“6”的频率440Hz #define l_xi 494 //将“l_xi”宏定义为低音“7”的频率494Hz //以下是C调中音的音频宏定义 #define dao 523 //将“dao”宏定义为中音“1”的频率523Hz #define re 587 //将“re”宏定义为中音“2”的频率587Hz #define mi 659 //将“mi”宏定义为中音“3”的频率659Hz #define fa 698 //将“fa”宏定义为中音“4”的频率698Hz #define sao 784 //将“sao”宏定义为中音“5”的频率784Hz #define la 880 //将“la”宏定义为中音“6”的频率880Hz #define xi 987 //将“xi”宏定义为中音“7”的频率523H //以下是C调高音的音频宏定义 #define h_dao 1046 //将“h_dao”宏定义为高音“1”的频率1046Hz #define h_re 1174 //将“h_re”宏定义为高音“2”的频率1174Hz #define h_mi 1318 //将“h_mi”宏定义为高音“3”的频率1318Hz #define h_fa 1396 //将“h_fa”宏定义为高音“4”的频率1396Hz #define h_sao 1567 //将“h_sao”宏定义为高音“5”的频率1567Hz #define h_la 1760 //将“h_la”宏定义为高音“6”的频率1760Hz #define h_xi 1975 //将“h_xi”宏定义为高音“7”的频率1975Hz //函数功能:1个延时单位,延时200ms void delay() { unsigned char i,j; for(i=0;i<250;i++) for(j=0;j<250;j++); } //函数功能:主函数 void main(void) { unsigned char i,j; //以下是《渴望》片头曲的一段简谱 unsigned int code f[]={re,mi,re,dao,l_la,dao,l_la, //每行对应一小节音符 l_sao,l_mi,l_sao,l_la,dao, l_la,dao,sao,la,mi,sao, re, mi,re,mi,sao,mi, l_sao,l_mi,l_sao,l_la,dao, l_la,l_la,dao,l_la,l_sao,l_re,l_mi, l_sao, re,re,sao,la,sao, fa,mi,sao,mi, la,sao,mi,re,mi,l_la,dao, re, mi,re,mi,sao,mi, l_sao,l_mi,l_sao,l_la,dao, l_la,dao,re,l_la,dao,re,mi, re, l_la,dao,re,l_la,dao,re,mi, re, 0xff}; //以0xff作为音符的结束标志 //以下是简谱中每个音符的节拍 //"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位 unsigned char code JP[ ]={4,1,1,4,1,1,2, 2,2,2,2,8, 4,2,3,1,2,2, 10, 4,2,2,4,4, 2,2,2,2,4, 2,2,2,2,2,2,2, 10, 4,4,4,2,2, 4,2,4,4, 4,2,2,2,2,2,2, 10, 4,2,2,4,4, 2,2,2,2,6, 4,2,2,4,1,1,4, 10, 4,2,2,4,1,1,4, 10 }; EA=1; //开总中断 ET0=1; //定时器T0中断允许 TMOD=0x00; // 使用定时器T0的模式1(13位计数器) while(1) //无限循环 { i=0; //从第1个音符f[0]开始播放 while(f[i]!=0xff) //只要没有读到结束标志就继续播放 { C=460830/f[i]; TH0=(8192-C)/32; //可证明这是13位计数器TH0高8位的赋初值方法 TL0=(8192-C)%32; //可证明这是13位计数器TL0低5位的赋初值方法 TR0=1; //启动定时器T0 for(j=0;j<JP[i];j++) //控制节拍数 delay(); //延时1个节拍单位 TR0=0; //关闭定时器T0 i++; //播放下一个音符 } } } //函数功能:定时器T0的中断服务子程序,使P3.7引脚输出音频的方波 void Time0(void ) interrupt 1 using 1 { sound=!sound; //将P3.7引脚输出电平取反,形成方波 TH0=(8192-C)/32; //可证明这是13位计数器TH0高8位的赋初值方法 TL0=(8192-C)%32; //可证明这是13位计数器TL0低5位的赋初值方法 }