zoukankan      html  css  js  c++  java
  • Keil C51学习 6 控制播放音乐

    变频救护车

    #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位的赋初值方法 
      }
            
    播放《渴望》片头曲
  • 相关阅读:
    MongoDB安装与启动
    Mac node.js express-generator脚手架安装
    AJAX状态值与状态码
    博客园 Markdown编辑器简要教程
    高效、可维护、组件化的CSS
    如何在mac上运行vue项目
    前端chrome调试
    Light of future-冲刺集合
    团队作业第六次—事后诸葛亮
    Light of future-冲刺总结
  • 原文地址:https://www.cnblogs.com/bymeet/p/14349805.html
Copyright © 2011-2022 走看看