单片机演奏《上海滩》

/*--------------------------------------------------------------------------
         程序在硬件上调试通过
            本程序的单片机晶振采用11.0592M ,
   曲目为《上海滩》的主题曲
  ---------------------------------------------------------------------------*/
#include <reg51.h>
sbit      speaker=P2^3; 
unsigned char timer0h,timer0l,time;
unsigned char bdata flg;
sbit      flag=flg^0;
bit er;
        //上海滩数据表:一个音符有三个数字。前为第几个音、中为第几个八度、后为时长(以半拍为单位)
code unsigned char sszymmh[]={        3,1,1, 5,1,1, 6,1,3, /*0,0,1, 0,0,1,*/ 3,1,1, 5,1,1,
                                      2,1,2, /*0,0,1,*/ 0,0,1, 3,1,1, 5,1,1, 6,1,1, 1,2,2, 6,1,1, 5,1,2, 6,0,1, 1,1,1, 3,1,1,
                                      2,1,3, /*0,0,1, 0,0,1,*/ 2,1,1, 3,1,1, 5,1,3, /*0,0,1, 0,0,1,*/ 2,1,1, 3,1,1,
           2,1,1, 6,0,3, 0,0,1, /*0,0,1,*/ 6,0,1, 1,1,1, /*2,1,3, 3,1,1, 2,1,3, 7,0,1,//咪,中音,1个半拍;
                                      6,0,1, 1,1,1, 5,0,2, 0,0,1, /*0,0,0,*/ /*3,1,1, 5,1,2, */2,1,3, 3,1,1, 2,1,1, 7,0,1,//咪,中音,1个半拍;
                                      6,0,1, 5,0,1, 1,2,1, 0,0,1, 1,2,1, 1,2,1, 6,1,1, 1,2,2, 0,0,1, 6,1,1, 1,2,1, 6,1,1, //音调+ 音高+几个半拍
                                      5,1,2, 0,0,1, /*0,0,1,*/ 5,1,1, 3,1,1, 6,1,3, 5,1,1, 1,1,2, 2,1,1, 1,1,1, 2,1,1, 3,1,2,
           0,0,1, 3,1,1, 3,1,1, 2,1,1, 3,1,1, 0,0,1, 1,2,1, 1,2,1, 7,1,1, 6,1,1, 3,1,1, 3,1,1, 2,1,2, 3,1,1, 1,2,1, 7,1,1, 6,1,1, 3,1,1, 5,1,2,
           0,0,1, /*0,0,1, *//*3,1,1, 5,1,1, 2,1,3, 3,1,1, 2,1,1, 7,0,1, 6,0,1, 5,0,1, 1,1,2, 3,1,1, 5,1,1,
           */0,0,0};
       // 音阶频率表 高八位
/*   //--------------------------------------

记住:三个数字一组,代表一个音符。
第一个数字是1234567之一,代表音符哆来咪发...;
第二个数字是0123之一,代表低音、中音、高音、超高音;
第三个数字是半拍的个数,代表时间长度。
当三个数字都是0,就代表乐曲数据表的结尾。

             */
code unsigned char FREQH[]={
                                0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,   //低音 1,2,3,4,5,6,7
                                0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC, //中音 1,2,3,4,5,6,7,i
                                0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,   //高音     2,3,4,5,6,7
                                0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,  //超高音1,2,3,4,5,6,7
                               } ;
         // 音阶频率表 低八位
code unsigned char FREQL[]={
                                 0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
                                 0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F, //1,2,3,4,5,6,7,8,i
                                 0xEE,0x44, 0x6B,0xB4,0xF4,0x2D,
                           0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,//低音、中音、高音和超高音,四个八度共28个音符
                                };
void delay(unsigned char t)
   {
   unsigned char t1;
   unsigned long t2;
   for(t1=0;t1<t;t1++)    //双重循环, 共延时t个半拍
   {
    for(t2=0;t2<8000;t2++) //延时期间, 可进入T0中断去发音
       {
        ;
        }
   }
   TR0=0;       //关闭T0, 停止发音
 }
void t0int() interrupt 1
{
 TR0=0;
    if(flag==0)
      speaker=!speaker;    //T0中断程序,控制发音的音调
    else
      {speaker=1;}
 TH0=timer0h;    //输出方波, 发音
 TL0=timer0l;      //下次的中断时间, 这个时间, 控制音调高低
 TR0=1;
 }
void song()       //演奏一个音符
{
 TH0=timer0h;    //延时程序,控制发音的时间长度
 TL0=timer0l;
 TR0=1;       //打开T0, 开始发音
 delay(time);             //控制时间长度            
 }

 void main(void)
 {
 unsigned char k,i;
 TMOD=1; //置CT0定时工作方式1
 EA=1;
 ET0=1;//IE=0x82 //CPU开中断,CT0开中断
 while(1)
      {
       i=0; 
       while(i<100)
    {         //音乐数组长度 ,唱完从头再来       
       k=sszymmh[i]+7*sszymmh[i+1]-1; // 6+7*2-1=19
    if(k!=-1)
       {
    flag=0;
      timer0h=FREQH[k]; //K-1是因为这里的数是0开始的
         timer0l=FREQL[k];
         time=sszymmh[i+2];
         i=i+3;
         song();
       }
    else
      {
    flag=1;
    i=i+3;
       song();
   if(i==99)
   delay(10000);
          }
   
  }
      }
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值