zoukankan      html  css  js  c++  java
  • 【制作】基于金沙滩51单片机的蜂鸣器音乐

    基于金沙滩51单片机的蜂鸣器音乐 - 克罗地亚狂想曲

    当年刚学单片机蜂鸣器不久做的一个小项目,能用蜂鸣器播放音乐,之前的网站挂了,在这里重新发一下。

    下面是原文:

    当温度超过设置值时,怎么设置使蜂鸣器发出某首音乐声?

    敲黑板画重点啦!!!这里的重点是音乐声而不是温度超过设置值

    于是去参考了下宋老师的代码:

    蜂鸣器音乐实例代码

    #include <reg52.h>
    
    sbit BUZZ = P1^6;  //蜂鸣器控制引脚
    
    unsigned int code NoteFrequ[] = {  //中音1-7和高音1-7对应频率列表
        523,  587,  659,  698,  784,  880,  988,  //中音1-7
        1047, 1175, 1319, 1397, 1568, 1760, 1976  //高音1-7
    };
    unsigned int code NoteReload[] = { //中音1-7和高音1-7对应的定时器重载值
        65536 - (11059200/12) / (523*2),  //中音1
        65536 - (11059200/12) / (587*2),  //2
        65536 - (11059200/12) / (659*2),  //3
        65536 - (11059200/12) / (698*2),  //4
        65536 - (11059200/12) / (784*2),  //5
        65536 - (11059200/12) / (880*2),  //6
        65536 - (11059200/12) / (988*2),  //7
        65536 - (11059200/12) / (1047*2), //高音1
        65536 - (11059200/12) / (1175*2), //2
        65536 - (11059200/12) / (1319*2), //3
        65536 - (11059200/12) / (1397*2), //4
        65536 - (11059200/12) / (1568*2), //5
        65536 - (11059200/12) / (1760*2), //6
        65536 - (11059200/12) / (1976*2), //7
    };
    bit enable = 1;   //蜂鸣器发声使能标志
    bit tmrflag = 0;  //定时器中断完成标志
    unsigned char T0RH = 0xFF;  //T0重载值的高字节
    unsigned char T0RL = 0x00;  //T0重载值的低字节
    
    void PlayTwoTiger();
    
    void main()
    {
        unsigned int i;
        
        EA = 1;       //使能全局中断
        TMOD = 0x01;  //配置T0工作在模式1
        TH0 = T0RH;
        TL0 = T0RL;
        ET0 = 1;      //使能T0中断
        TR0 = 1;      //启动T0
        
        while (1)
        {
            PlayTwoTiger();  //播放乐曲--两支老虎
            for (i=0; i<40000; i++);  //停止一段时间
        }
    }
    /* 两只老虎乐曲播放函数 */
    void PlayTwoTiger()
    {
        unsigned char beat;   //当前节拍索引
        unsigned char note;   //当前节拍对应的音符
        unsigned int time = 0;      //当前节拍计时
        unsigned int beatTime = 0;  //当前节拍总时间
        unsigned int soundTime = 0; //当前节拍需发声时间
        //两只老虎音符表
        unsigned char code TwoTigerNote[] = {
            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,   1, 5, 1,
        };
        //两只老虎节拍表,4表示一拍,1就是1/4拍,8就是2拍
        unsigned char code TwoTigerBeat[] = {
            4,   4,   4, 4,    4,   4,   4, 4,   4, 4, 8,   4, 4, 8,
            3,1, 3,1, 4, 4,    3,1, 3,1, 4, 4,   4, 4, 8,   4, 4, 8,
        };
        
        for (beat=0; beat<sizeof(TwoTigerNote); )  //用节拍索引作为循环变量
        {
            while (!tmrflag);  //每次定时器中断完成后,检测并处理节拍
            tmrflag = 0;
            if (time == 0)  //当前节拍播完则启动一个新节拍
            {
                note = TwoTigerNote[beat] - 1;
                T0RH = NoteReload[note] >> 8;
                T0RL = NoteReload[note];
                //计算节拍总时间,右移2位相当于除4,移位代替除法可以加快执行速度
                beatTime = (TwoTigerBeat[beat] * NoteFrequ[note]) >> 2;
                //计算发声时间,为总时间的0.75,移位原理同上
                soundTime = beatTime - (beatTime >> 2);
                enable = 1;  //指示蜂鸣器开始发声
                time++;
            }
            else  //当前节拍未播完则处理当前节拍
            {
                if (time >= beatTime)  //当前持续时间到达节拍总时间时归零,
                {                      //并递增节拍索引,以准备启动新节拍
                    time = 0;
                    beat++;
                }
                else  //当前持续时间未达到总时间时,
                {
                    time++;   //累加时间计数
                    if (time == soundTime)  //到达发声时间后,指示关闭蜂鸣器,
                    {                       //插入0.25*总时间的静音间隔,
                        enable = 0;         //用以区分连续的两个节拍
                    }
                }
            }
        }
    }
    /* T0中断服务函数,用于控制蜂鸣器发声 */
    void InterruptTimer0() interrupt 1
    {
        TH0 = T0RH;   //重新加载重载值
        TL0 = T0RL;
        tmrflag = 1;
        if (enable)   //使能时反转蜂鸣器控制电平
            BUZZ = ~BUZZ;
        else          //未使能时关闭蜂鸣器
            BUZZ = 1;
    }
    
    

    下载到单片机后,传来了美妙的“两只老虎” ✧٩(ˊωˋ*)و✧

    然而我并不喜欢把两只老虎作为报警音乐.......

    宋老师的代码主要由数据和控制组成,而数据分为节拍数据和音调数据,那我们要换一首歌不就是换音调和节拍。

    于是去百度“单片机蜂鸣器音乐代码”,得到如下结果:

    都是些八月桂花,生日快乐,两只蝴蝶,祝你平安这些经典音乐,没有POP吗?

    那就自己动手吧,只要得到节拍数据和音调数据就好了,应该有转换工具的,就像LED点阵一样有点阵图形转换工具,于是百度:

    还真有 (*≧▽≦) , 叫 music encode

    于是下载,解包

    还有Dome和说明,太好了。于是下载了Dome。是八月桂花....

    然而我不喜欢这个,翻了翻音乐列表,就设置为“克罗地亚狂想曲”吧

    ٩(●´৺`●)૭٩(●´৺'●)و

    于是去问度娘要乐谱,好不容易找到了由玉面小嫣然改编的古筝简谱,其他的都是五线谱,原谅我看不懂五线谱 ( •̩̩̩̩_•̩̩̩̩ )


    克罗地亚狂想曲钢琴谱

    找到乐谱后就开始输乐谱........ (つд⊂) , 一个漫长的过程.........

    终于输好了,生成代码下载进去...... ٩(●´৺`●)૭٩(●´৺'●)و

    克罗地亚狂想曲乐谱

    乐谱

     0, 0, 0, 0,| 7__, .1__, 6_, 0, 3__, 4__, 2_, 0,| #, 4__, #, 5__, 3_, 3_, 7.__, 1__, 6._, 7.__, 1__, 6.,| 7__, .1__, 6_,  0, .3__, 6__, 3__, 4__, 2_, 0, 6__, 2__,|
     #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__, 6.,| 7__, .1__, 6_,  0, .3__, 6__, 7__, .1__, 6_,  0, .3__, 6__,| 7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__, 6,| 7__, .1__, 6_,  0, .3__, 6__, 7__, .1__, 6_,  0, .3__, 6__,|
     7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__, 6,| 7__, .1__, 6_,  0, .3__, 6__,  3__, 4__, 2_, 0,| #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__, 6.,| 7__, .1__, 6_,  0, .3__, 6__,  3__, 4__, 2_, 0,|
     #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__, 6.,| 7__, .1__, 6_,  0, .3__, 6__, 7__, .1__, 6_,  0, .3__, 6__,| 7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__, 6,| 7__, .1__, 6_,  0, .3__, 6__, 7__, .1__, 6_,  0, .3__, 6__,|
     7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__, 6,||| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,| 7__, 3__, #, 5__, 6__,  7__, 3__, 5__, 7__,  .1__, 3__, 7__, 3__,  6__, 3__, .3__, 3__,| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,|
     .3__, 3__, #, 5__, 3__,  .1__, 3__, 7__, 3__,  6__, 3__, .3__, 3__, 6,||| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,| 7__, 3__, #, 5__, 6__,  7__, 3__, 5__, 7__,  .1__, 3__, 7__, 3__,  6__, 3__, .3__, 3__,| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,|
     .3__, 3__, #, 5__, 3__,  .1__, 3__, 7__, 3__,  6__, 3__, .3__, 3__, 6,|| .3__, 6__, .1__, .2__,  .3__, 6__, .1__, .5__,  .4__, 6__, .3__, 6__, .2__, 6__, .1__, 6__,| .2__, 5__, 7__, .1__,  .2__, 5__, 7__, .4__,  .3__, 5__, .2__, 5__,  .1__, 5__, 7__, 5__,| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,|
     7_, 3_,  .1_, 7_,  6_, .3_,  .6,| 7_, 3_,  .1_, 7_,  6._, 6_,  6,| .3__, 6__, .1__, .2__,  .3__, 6__, .1__, .5__,  .4__, 6__, .3__, 6__,  .4__, 6__, .6__, 6__,| .5__, 7__, .2__, .6__,  .5__, 7__, .4__, 7__,  .3__, 3__, .2__, 3__,  .1__, 3__, 7__, 3__,| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,|
     7__, 3__, #, 5__, 7__,  .2__, 5__, 7__, .2__,  .3__, 7__, .2__, .3__,  #, .5__, .2__, .3__, .5__,| 7__, 3__, #, 5__, 7__,  .2__, 5__, 7__, .2__,  .3__, 7__, .2__, .3__,  #, .5__, .2__, .3__, .5__,| .6,  -,  -,  -,| 6.__, 1_, 3__,  2__, 6.__, 1__, 5.__,  6.__, 1_, 3__,  2__, 6.__, 1_,|
     0, 6__, 1__, 3__,  6.__, 1__, 6._,  0, #, 2.__, 3.__, 6.__,  1__, 2__, 1_,| 3.__, 5._, 3.__,  6.__,  3.__, 5.__, 2.__,  3.__, 5._, 3.__,  6.__, 3.__, 5._,| 7__, .1__, 6_,  0, .3__, 6__,  3__, 4__, 2_,  0,| #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__,  6.,|
     7__, .1__, 6_,  0, .3__, 6__,  3__, 4__, 2_,  0,| #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__,  6.,| 7__, .1__, 6_,  0, .3__, 6__,  7__, .1__, 6_,  0, .3__, 6__,| 7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__, 6,|
     7__, .1__, 6_,  0, .3__, 6__,  7__, .1__, 6_,  0, .3__, 6__,| 7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__, 6,| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,| 7__, 3__, #, 5__, 6__,  7__, 3__, 5__, 7__,  .1__, 3__, 7__, 3__,  6__, 3__, .3__, 3__,|
     .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,| .3__, 3__, #, 5__, 3__,  .1__, 3__, 7__, 3__,  6__, 3__, .3__, 3__,  6,| .3__, 6__, .1__, .2__,  .3__, 6__, .1__, .5__,  .4__, 6__, .3__, 6__,  .4__, 6__, .6__, 6__,| .5__, 7__, .2__, .6__,  .5__, 7__, .4__, 7__,  .3__, 3__, .2__, 3__,  .1__, 3__, 7__, 3__,|
     .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,| 7__, 3__, #, 5__, 7__,  .2__, 5__, 7__, .2__,  .3__, 7__, .2__, .3__,  #, .5__, .3__, .2__, .1__,| 7, -, .3, -,| 7__, .1__, 6_,  7__, .1__, 6_,  3__, 4__, 2_,  3__, 4__, 2_,|
     #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__,  6.,| 7__, .1__, 6_,  7__, .1__, 6_,  3__, 4__, 2_,  3__, 4__, 2_,| #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__,  6.,| 7__, .1__, 6_,  0, .3__, 6__,  7__, .1__, 6_,  0, .3__, 6__,|
     7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__,  6,| 7__, .1__, 6_,  0, .3__, 6__,  7__, .1__, 6_,  0, .3__, 6__,| 7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__,  6,| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,|
     7__, 3__, #, 5__, 6__,  7__, 3__, 5__, 7__,  .1__, 3__, 7__, 3__,  6__, 3__, .3__, 3__,| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,| .3__, 3__, #, 5__, 3__,  .1__, 3__, 7__, 3__,  6__, 3__, .3__, 3__,  6,| .3__, 6__, .1__, .2__,  .3__, 6__, .1__, .5__,  .4__, 6__, .3__, 6__,  .4__, 6__, .6__, 6__,|
     .5__, 7__, .2__, .6__,  .5__, 7__, .4__, 7__,  .3__, 3__, .2__, 3__,  .1__, 3__, 7__, 3__,| .1__, 3__, 6__, 7__,  .1__, 3__, 6__, .1__,  .2__, 3__, .1__, 3__,  7__, 3__, 6__, 3__,| 7__, 3__, #, 5__, 7__,  .2__, 5__, 7__, .2__,  .3__, 7__, .2__, .3__,  #, .5__, .3__, .2__, .1__,|  7__, .1__, 6_,  7__, .1__, 6_,  3__, 4__, 2_,  3__, 4__, 2_,|
     #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__,  6.,| 7__, .1__, 6_,  7__, .1__, 6_,  3__, 4__, 2_,  3__, 4__, 2_,| #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__,  6.,| 7__, .1__, 6_,  0, .3__, 6__, 7__, .1__, 6_,  0, .3__, 6__,|
     7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__,  6,| 7__, .1__, 6_,  0, .3__, 6__, 7__, .1__, 6_,  0, .3__, 6__,| 7__, .1__, 6_,  6_, #, 5__, 6__,  0, 7__, .1__,  6,| 7__, .1__, 6_,  7__, .1__, 6_,  3__, 4__, 2_,  3__, 4__, 2_,|
     #, 4__, #, 5__, 3_,  3_, 7.__, 1__,  6._, 7.__, 1__,  6.,| 7__, .1__, 6_,  7__, .1__, 6_,  3__, 4__, 2_,  3__, 4__, 2_,| #, 4__, #, 5__, 3_,  3_, 7_,  6_, .3_,  .6,| #, 4__, #, 5__, 3_,  3_, 7_,  3_, 6_,  .3,| #, 4__, #, 5__, 3_,  3_, 7_,  3_, 6_,  6,|
    

    此处应有视频......

    Nice!

    需要用到的原理图和软件

    DS18B20读写时序

    Music Encode:点击下载

    源代码和解释:

    只播放音乐的代码:(按K1可以暂停哦......)

    #include <reg52.h>
     
    sbit keyin = P2^4;
    sbit keyout = P2^3;
     
    /*----------------音乐函数申明------------------------------*/
    void Play();
    void InitialSound(unsigned char *Sound0,unsigned char Signature0,
        unsigned char Octachord0,unsigned int Speed0);
    /*----------------音乐数据申明------------------------------*/
    extern unsigned char code Music_Croatian_Rhapsody[];
    //数据太大,放后面了,所以加extern以说明
    void delay10ms(void)   //误差 0us
    {
        unsigned char a,b,c;
        for(c=1;c>0;c--)
            for(b=38;b>0;b--)
                for(a=130;a>0;a--);
    }
    void main()
    {
        unsigned int cnt = 0;
        InitialSound(Music_Croatian_Rhapsody,0,2,360);  //蜂鸣器初始化
         
        keyout = 0;
         
        while(1)
        {
            if(keyin == 0)
            {
                delay10ms();
                if(keyin == 0)
                {
                    if(cnt<40)cnt = 200;
                    else cnt = 20;
                    while(keyin == 0);
                }
            }
             
            if(cnt < 40)
            {
                Play();                                 //蜂鸣器
            }
        }
    }
     
     
     
    /*-----------------------以下是蜂鸣器演奏------------------*/
    #define SYSTEM_OSC      11059200    //12000000  //定义晶振频率12000000HZ
    #define SOUND_SPACE     4/5         //定义普通音符演奏的长度分率,//每4分音符间隔
    sbit    BeepIO    =     P1^6;       //定义输出管脚
     
    unsigned int  code FreTab[12]  = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表
    unsigned char code SignTab[7]  = { 0,2,4,5,7,9,11 };                                  //1~7在频率表中的位置
    unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };                      
    unsigned char Sound_Temp_TH0,Sound_Temp_TL0;    //音符定时器初值暂存 
    unsigned char Sound_Temp_TH1,Sound_Temp_TL1;    //音长定时器初值暂存
    unsigned char Signature;
    unsigned char Octachord;
    unsigned int Speed;
    unsigned char *Sound;
    unsigned int NewFreTab[12];                     //新的频率表
    unsigned char i,j;
    unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
    unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
     
    void InitialSound(unsigned char *Sound0,unsigned char Signature0,unsigned char Octachord0,unsigned int Speed0)
    {
            Signature = Signature0;
        Octachord = Octachord0;
        Speed = Speed0;
        Sound = Sound0;
        
        for(i=0;i<12;i++)               // 根据调号及升降八度来生成新的频率表 
        {
            j = i + Signature;
            if(j > 11)
            {
                j = j-12;
                NewFreTab[i] = FreTab[j]*2;
            }
            else
                NewFreTab[i] = FreTab[j];
    
            if(Octachord == 1)
                NewFreTab[i]>>=2;
            else if(Octachord == 3)
                NewFreTab[i]<<=2;
        }                                   
        
        SoundLength = 1;
        while(Sound[SoundLength] != 0x00)   //计算歌曲长度
        {
            SoundLength+=2;
        }
    
        Point = 0;
        Tone   = Sound[Point];  
        Length = Sound[Point+1];            // 读出第一个音符和它时时值
        
        LDiv0 = 12000/Speed;                // 算出1分音符的长度(几个10ms)    
        LDiv4 = LDiv0/4;                    // 算出4分音符的长度 
        LDiv4 = LDiv4-LDiv4*SOUND_SPACE;    // 普通音最长间隔标准 
        
        BeepIO = 1;
        Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256;   // 计算TL1应装入的初值  (10ms的初装值)
        Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256;   // 计算TH1应装入的初值 
        TH1 = Sound_Temp_TH1;
        TL1 = Sound_Temp_TL1;
        TMOD  |= 0x11;
        ET0    = 1;
        ET1    = 0;
        TR0    = 0;
        TR1    = 0;
        EA     = 1;
    }
     
    void BeepTimer0(void) interrupt 1   //音符发生中断
    {
        BeepIO = !BeepIO;
        TH0    = Sound_Temp_TH0;
        TL0    = Sound_Temp_TL0;
    }
     
    void Play()
    {
        EA = 1;
        TR0   = 0;
        TR1   = 1;
        if(Point < SoundLength)
        {
            SL=Tone%10;                                 //计算出音符 
            SM=Tone/10%10;                              //计算出高低音 
            SH=Tone/100;                                //计算出是否升半 
            CurrentFre = NewFreTab[SignTab[SL-1]+SH];   //查出对应音符的频率     
            if(SL!=0)
            {
                if (SM==1) CurrentFre >>= 2;        //低音 
                if (SM==3) CurrentFre <<= 2;        //高音
                Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
                Sound_Temp_TH0 = Temp_T/256; 
                Sound_Temp_TL0 = Temp_T%256; 
                TH0 = Sound_Temp_TH0;  
                TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿 
            }
            SLen=LengthTab[Length%10];  //算出是几分音符
            XG=Length/10%10;            //算出音符类型(0普通1连音2顿音) 
            FD=Length/100;
            LDiv=LDiv0/SLen;            //算出连音音符演奏的长度(多少个10ms)
            if (FD==1) 
            {
                LDiv=LDiv+LDiv/2;
            }
            
            if(XG!=1)
            {           
                if(XG==0)               //算出普通音符的演奏长度 
                {
                    if (SLen<=4)    
                    {
                        LDiv1=LDiv-LDiv4;
                    }else{
                        LDiv1=LDiv*SOUND_SPACE;
                    }
                }else{
                    LDiv1=LDiv/2;       //算出顿音的演奏长度 
                }
            }else{
                LDiv1=LDiv;
            }
            
            if(SL==0) 
            {
                LDiv1=0;
            }
            
            LDiv2=LDiv-LDiv1;       //算出不发音的长度 
            
            if (SL!=0)
            {
                TR0=1;
                for(i=LDiv1;i>0;i--)    //发规定长度的音 
                {
                    while(TF1==0);      //等待节拍过去
                    TH1 = Sound_Temp_TH1;//重装初值
                    TL1 = Sound_Temp_TL1;
                    TF1=0;              //清除中断标志位
                }
            }
            
            if(LDiv2!=0)
            {
                TR0=0; BeepIO=1;
                for(i=LDiv2;i>0;i--)    //音符间的间隔
                {
                    while(TF1==0);      //等待节拍过去
                    TH1 = Sound_Temp_TH1;//重装初值
                    TL1 = Sound_Temp_TL1;
                    TF1=0;              //清除中断标志位
                }
            }
            
            Point+=2; 
            Tone=Sound[Point];
            Length=Sound[Point+1];
            
        }
        else
        {
            /*SoundLength = len;
            Point = poi;*/
            InitialSound(Music_Croatian_Rhapsody,0,2,360);
        }
        BeepIO = 1;
        
        TR0   = 0;
        TR1   = 0;
    }
     
    //这里放生成的音乐数据
    unsigned char code Music_Croatian_Rhapsody[]={
        0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x17,0x04, 0x18,0x04,
        0x16,0x7B, 0x18,0x68, 0x19,0x04, 0x17,0x03, 0x17,0x03,
        0x11,0x04, 0x15,0x04, 0x10,0x03, 0x11,0x04, 0x15,0x04,
        0x10,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04,
        0x1A,0x04, 0x17,0x04, 0x18,0x04, 0x16,0x17, 0x1A,0x04,
        0x16,0x68, 0x18,0x68, 0x19,0x04, 0x17,0x03, 0x17,0x03,
        0x11,0x04, 0x15,0x04, 0x10,0x03, 0x11,0x04, 0x15,0x04,
        0x10,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x1A,0x67,
        0x19,0x04, 0x1A,0x18, 0x1B,0x04, 0x1F,0x04, 0x1A,0x02,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x1A,0x67, 0x19,0x04,
        0x1A,0x18, 0x1B,0x04, 0x1F,0x04, 0x1A,0x02, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04, 0x17,0x04,
        0x18,0x04, 0x16,0x7B, 0x18,0x68, 0x19,0x04, 0x17,0x03,
        0x17,0x03, 0x11,0x04, 0x15,0x04, 0x10,0x03, 0x11,0x04,
        0x15,0x04, 0x10,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17,
        0x21,0x04, 0x1A,0x04, 0x17,0x04, 0x18,0x04, 0x16,0x7B,
        0x18,0x68, 0x19,0x04, 0x17,0x03, 0x17,0x03, 0x11,0x04,
        0x15,0x04, 0x10,0x03, 0x11,0x04, 0x15,0x04, 0x10,0x02,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x1A,0x67, 0x19,0x04,
        0x1A,0x18, 0x1B,0x04, 0x1F,0x04, 0x1A,0x02, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x03, 0x1A,0x67, 0x19,0x04, 0x1A,0x18,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x02, 0x1F,0x04, 0x17,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04,
        0x1F,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x1B,0x04,
        0x17,0x68, 0x19,0x04, 0x1A,0x04, 0x1B,0x04, 0x17,0x04,
        0x19,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04,
        0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x21,0x04, 0x17,0x04,
        0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04,
        0x17,0x04, 0x1A,0x04, 0x1F,0x04, 0x20,0x04, 0x17,0x04,
        0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04,
        0x17,0x04, 0x21,0x04, 0x17,0x68, 0x19,0x04, 0x17,0x04,
        0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04,
        0x17,0x04, 0x21,0x04, 0x17,0x04, 0x1A,0x02, 0x1F,0x04,
        0x17,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04,
        0x1A,0x04, 0x1F,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04,
        0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x68, 0x19,0x04, 0x1A,0x04, 0x1B,0x04,
        0x17,0x04, 0x19,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x21,0x04,
        0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1B,0x04,
        0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1F,0x04, 0x20,0x04,
        0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04,
        0x1A,0x04, 0x17,0x04, 0x21,0x04, 0x17,0x68, 0x19,0x04,
        0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04,
        0x1A,0x04, 0x17,0x04, 0x21,0x04, 0x17,0x04, 0x1A,0x02,
        0x21,0x04, 0x1A,0x04, 0x1F,0x04, 0x20,0x04, 0x21,0x04,
        0x1A,0x04, 0x1F,0x04, 0x23,0x04, 0x22,0x04, 0x1A,0x04,
        0x21,0x04, 0x1A,0x04, 0x20,0x04, 0x1A,0x04, 0x1F,0x04,
        0x1A,0x04, 0x20,0x04, 0x19,0x04, 0x1B,0x04, 0x1F,0x04,
        0x20,0x04, 0x19,0x04, 0x1B,0x04, 0x22,0x04, 0x21,0x04,
        0x19,0x04, 0x20,0x04, 0x19,0x04, 0x1F,0x04, 0x19,0x04,
        0x1B,0x04, 0x19,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1F,0x04,
        0x20,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04,
        0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x1B,0x03, 0x17,0x03,
        0x1F,0x03, 0x1B,0x03, 0x1A,0x03, 0x21,0x03, 0x24,0x02,
        0x1B,0x03, 0x17,0x03, 0x1F,0x03, 0x1B,0x03, 0x10,0x03,
        0x1A,0x03, 0x1A,0x02, 0x21,0x04, 0x1A,0x04, 0x1F,0x04,
        0x20,0x04, 0x21,0x04, 0x1A,0x04, 0x1F,0x04, 0x23,0x04,
        0x22,0x04, 0x1A,0x04, 0x21,0x04, 0x1A,0x04, 0x22,0x04,
        0x1A,0x04, 0x24,0x04, 0x1A,0x04, 0x23,0x04, 0x1B,0x04,
        0x20,0x04, 0x24,0x04, 0x23,0x04, 0x1B,0x04, 0x22,0x04,
        0x1B,0x04, 0x21,0x04, 0x17,0x04, 0x20,0x04, 0x17,0x04,
        0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1F,0x04,
        0x17,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04,
        0x1A,0x04, 0x1F,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04,
        0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x68, 0x19,0x04, 0x1B,0x04, 0x20,0x04,
        0x19,0x04, 0x1B,0x04, 0x20,0x04, 0x21,0x04, 0x1B,0x04,
        0x20,0x04, 0x21,0x68, 0x23,0x04, 0x20,0x04, 0x21,0x04,
        0x23,0x04, 0x1B,0x04, 0x17,0x68, 0x19,0x04, 0x1B,0x04,
        0x20,0x04, 0x19,0x04, 0x1B,0x04, 0x20,0x04, 0x21,0x04,
        0x1B,0x04, 0x20,0x04, 0x21,0x68, 0x23,0x04, 0x20,0x04,
        0x21,0x04, 0x23,0x04, 0x24,0x00, 0x10,0x04, 0x15,0x03,
        0x17,0x04, 0x16,0x04, 0x10,0x04, 0x15,0x04, 0x0F,0x04,
        0x10,0x04, 0x15,0x03, 0x17,0x04, 0x16,0x04, 0x10,0x04,
        0x15,0x17, 0x1A,0x04, 0x15,0x04, 0x17,0x04, 0x10,0x04,
        0x15,0x04, 0x10,0x7B, 0x0C,0x04, 0x0D,0x04, 0x10,0x04,
        0x15,0x04, 0x16,0x04, 0x15,0x03, 0x0D,0x04, 0x0F,0x03,
        0x0D,0x04, 0x10,0x04, 0x0D,0x04, 0x0F,0x04, 0x0C,0x04,
        0x0D,0x04, 0x0F,0x03, 0x0D,0x04, 0x10,0x04, 0x0D,0x04,
        0x0F,0x03, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04,
        0x1A,0x04, 0x17,0x04, 0x18,0x04, 0x16,0x7B, 0x18,0x68,
        0x19,0x04, 0x17,0x03, 0x17,0x03, 0x11,0x04, 0x15,0x04,
        0x10,0x03, 0x11,0x04, 0x15,0x04, 0x10,0x02, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04, 0x17,0x04,
        0x18,0x04, 0x16,0x7B, 0x18,0x68, 0x19,0x04, 0x17,0x03,
        0x17,0x03, 0x11,0x04, 0x15,0x04, 0x10,0x03, 0x11,0x04,
        0x15,0x04, 0x10,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17,
        0x21,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17,
        0x21,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03,
        0x1A,0x67, 0x19,0x04, 0x1A,0x18, 0x1B,0x04, 0x1F,0x04,
        0x1A,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x1A,0x67,
        0x19,0x04, 0x1A,0x18, 0x1B,0x04, 0x1F,0x04, 0x1A,0x02,
        0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04,
        0x17,0x04, 0x1A,0x04, 0x1F,0x04, 0x20,0x04, 0x17,0x04,
        0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04,
        0x17,0x04, 0x1B,0x04, 0x17,0x68, 0x19,0x04, 0x1A,0x04,
        0x1B,0x04, 0x17,0x04, 0x19,0x04, 0x1B,0x04, 0x1F,0x04,
        0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04,
        0x21,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1F,0x04,
        0x20,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04,
        0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x21,0x04, 0x17,0x68,
        0x19,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04,
        0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x21,0x04, 0x17,0x04,
        0x1A,0x02, 0x21,0x04, 0x1A,0x04, 0x1F,0x04, 0x20,0x04,
        0x21,0x04, 0x1A,0x04, 0x1F,0x04, 0x23,0x04, 0x22,0x04,
        0x1A,0x04, 0x21,0x04, 0x1A,0x04, 0x22,0x04, 0x1A,0x04,
        0x24,0x04, 0x1A,0x04, 0x23,0x04, 0x1B,0x04, 0x20,0x04,
        0x24,0x04, 0x23,0x04, 0x1B,0x04, 0x22,0x04, 0x1B,0x04,
        0x21,0x04, 0x17,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04,
        0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04,
        0x1F,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x1B,0x04,
        0x17,0x68, 0x19,0x04, 0x1B,0x04, 0x20,0x04, 0x19,0x04,
        0x1B,0x04, 0x20,0x04, 0x21,0x04, 0x1B,0x04, 0x20,0x04,
        0x21,0x68, 0x23,0x04, 0x21,0x04, 0x20,0x04, 0x1F,0x04,
        0x1B,0x01, 0x21,0x01, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x17,0x04, 0x18,0x04,
        0x16,0x03, 0x17,0x04, 0x18,0x04, 0x16,0x67, 0x18,0x68,
        0x19,0x04, 0x17,0x03, 0x17,0x03, 0x11,0x04, 0x15,0x04,
        0x10,0x03, 0x11,0x04, 0x15,0x04, 0x10,0x02, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x03, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03,
        0x17,0x04, 0x18,0x04, 0x16,0x03, 0x17,0x04, 0x18,0x04,
        0x16,0x67, 0x18,0x68, 0x19,0x04, 0x17,0x03, 0x17,0x03,
        0x11,0x04, 0x15,0x04, 0x10,0x03, 0x11,0x04, 0x15,0x04,
        0x10,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x1A,0x67,
        0x19,0x04, 0x1A,0x18, 0x1B,0x04, 0x1F,0x04, 0x1A,0x02,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x21,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x1A,0x67, 0x19,0x04,
        0x1A,0x18, 0x1B,0x04, 0x1F,0x04, 0x1A,0x02, 0x1F,0x04,
        0x17,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04,
        0x1A,0x04, 0x1F,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04,
        0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x68, 0x19,0x04, 0x1A,0x04, 0x1B,0x04,
        0x17,0x04, 0x19,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x21,0x04,
        0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1B,0x04,
        0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1F,0x04, 0x20,0x04,
        0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04,
        0x1A,0x04, 0x17,0x04, 0x21,0x04, 0x17,0x68, 0x19,0x04,
        0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04,
        0x1A,0x04, 0x17,0x04, 0x21,0x04, 0x17,0x04, 0x1A,0x02,
        0x21,0x04, 0x1A,0x04, 0x1F,0x04, 0x20,0x04, 0x21,0x04,
        0x1A,0x04, 0x1F,0x04, 0x23,0x04, 0x22,0x04, 0x1A,0x04,
        0x21,0x04, 0x1A,0x04, 0x22,0x04, 0x1A,0x04, 0x24,0x04,
        0x1A,0x04, 0x23,0x04, 0x1B,0x04, 0x20,0x04, 0x24,0x04,
        0x23,0x04, 0x1B,0x04, 0x22,0x04, 0x1B,0x04, 0x21,0x04,
        0x17,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1F,0x04,
        0x20,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04,
        0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x68,
        0x19,0x04, 0x1B,0x04, 0x20,0x04, 0x19,0x04, 0x1B,0x04,
        0x20,0x04, 0x21,0x04, 0x1B,0x04, 0x20,0x04, 0x21,0x68,
        0x23,0x04, 0x21,0x04, 0x20,0x04, 0x1F,0x04, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x03, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03,
        0x17,0x04, 0x18,0x04, 0x16,0x03, 0x17,0x04, 0x18,0x04,
        0x16,0x67, 0x18,0x68, 0x19,0x04, 0x17,0x03, 0x17,0x03,
        0x11,0x04, 0x15,0x04, 0x10,0x03, 0x11,0x04, 0x15,0x04,
        0x10,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x03, 0x17,0x04, 0x18,0x04, 0x16,0x03,
        0x17,0x04, 0x18,0x04, 0x16,0x67, 0x18,0x68, 0x19,0x04,
        0x17,0x03, 0x17,0x03, 0x11,0x04, 0x15,0x04, 0x10,0x03,
        0x11,0x04, 0x15,0x04, 0x10,0x02, 0x1B,0x04, 0x1F,0x04,
        0x1A,0x17, 0x21,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04,
        0x1A,0x17, 0x21,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04,
        0x1A,0x03, 0x1A,0x67, 0x19,0x04, 0x1A,0x18, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17,
        0x21,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x17,
        0x21,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03,
        0x1A,0x67, 0x19,0x04, 0x1A,0x18, 0x1B,0x04, 0x1F,0x04,
        0x1A,0x02, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x1B,0x04,
        0x1F,0x04, 0x1A,0x03, 0x17,0x04, 0x18,0x04, 0x16,0x03,
        0x17,0x04, 0x18,0x04, 0x16,0x67, 0x18,0x68, 0x19,0x04,
        0x17,0x03, 0x17,0x03, 0x11,0x04, 0x15,0x04, 0x10,0x03,
        0x11,0x04, 0x15,0x04, 0x10,0x02, 0x1B,0x04, 0x1F,0x04,
        0x1A,0x03, 0x1B,0x04, 0x1F,0x04, 0x1A,0x03, 0x17,0x04,
        0x18,0x04, 0x16,0x03, 0x17,0x04, 0x18,0x04, 0x16,0x67,
        0x18,0x68, 0x19,0x04, 0x17,0x03, 0x17,0x03, 0x1B,0x03,
        0x1A,0x03, 0x21,0x03, 0x24,0x66, 0x18,0x68, 0x19,0x04,
        0x17,0x03, 0x17,0x03, 0x1B,0x03, 0x17,0x03, 0x1A,0x03,
        0x21,0x66, 0x18,0x68, 0x19,0x04, 0x17,0x03, 0x17,0x03,
        0x1B,0x03, 0x17,0x03, 0x1A,0x03, 0x1A,0x02, 0x00,0x00
    };
    

    题目的代码,emmm.....音乐数据太多,只放了一小段

    #include <reg52.h>
    #include <intrins.h>
    //_nop_()函数所在头文件
    
    char code waringset = 22;   //报警温度
    
    /*----------------音乐函数申明------------------------------*/
    void InitialSound(unsigned char *Sound0,unsigned char Signature0,
        unsigned char Octachord0,unsigned int Speed0);
    void Play();
    
    
    /*----------------音乐数据申明------------------------------*/
    extern unsigned char code Music_Croatian_Rhapsody[];
    //(数据太大,放后面了,所以加extern以说明)
    
    
    /*----------------温度传感器申明----------------------------*/
    bit Start18B20();           //初始化DS18B20
    bit Get18B20Temp(int *temp);//读取温度
    
    
    /*----------------LCD1602显示模块申明------------------------*/
    void InitLcd1602();         //LCD1602初始化函数
    void display();         //显示控制模块
    
    /*-------------------LCD1602显示缓存-------------------------*/
    unsigned char strbuff[11];//格式:“+125.0.0625°C”
    unsigned char code waringstr[] = "     Alarm!     ";//报警显示文字
    unsigned char code striswaring[] = "            ";//取消报警显示文字
    
    
    /*----------------------其他全局变量-------------------------*/
    int Temp = 0;       //读取到的当前温度值(16bit二进制)
    int intT, decT;     //温度值的整数和小数部分
    bit sign;           //温度值的正负(1正,0负)
    bit iswaring = 0;   //是否报警标志位
    
    void main()
    {
        bit sta;                //是否成功读取标志
        unsigned int cnt = 0;   //检测标志,主要用于控制检测温度的频率
        
        InitialSound(Music_Croatian_Rhapsody,0,2,360);  //蜂鸣器初始化
        Start18B20();           //启动DS18B20
        InitLcd1602();          //初始化LCD1602液晶模块
        
        while(1)
        {
            cnt++;
            if(((iswaring == 0)&&(cnt>14000))||((iswaring == 1)&&(cnt>3)))              //大约0.8s(仿真得到) DS18B20最多750ms转化好
            {
                cnt = 0;
                sta = Get18B20Temp(&Temp);  //读取当前温度
                if (sta)                    //读取成功时,刷新当前温度显示
                {
                    if((Temp >> 11) < 4)    //如果前面5位大部分是0
                    {
                        sign = 1;           //正号,温度值为正
                    }else{
                        sign = 0;           //温度值为负
                    }
                    
                    if(sign == 1)           //正号
                    {
                        intT = Temp >> 4;       //分离出温度值整数部分
                        decT = Temp & 0x0F;     //分离出温度值小数部分
                        decT = decT * 625;      //小数转换成10进制精度
                        //ftemp = intT + decT/10000;/*无效*/  //转换为浮点,以便比较
                    }else{                  //负号
                        Temp = (~Temp)+1;       //取反后+1
                        intT = (Temp >> 4)*(-1);//分离出温度值整数部分
                        decT = Temp & 0x0F;     //分离出温度值小数部分
                        decT = decT * 625;      //小数转换成10进制精度           
                        //ftemp = (intT + decT/10000)*(-1);//转换为浮点
                    }
                }
                else                            //读取失败时,给出错误信息
                {
                    intT = 200;                 //这个值随便给,主要是大于126就好
                    //ftemp = intT;
                }
                Start18B20();                   //重新启动下一次转换
                display();                      //显示
                
                if(intT >= waringset)
                {
                    iswaring = 1;
                }else{
                    iswaring = 0;
                }
                
            }
            
            if((iswaring == 1)&&(intT<126)&&(intT>-55))
            {
                Play();                                 //蜂鸣器
            }else{
                EA = 0;         //蜂鸣器是用中断,关掉
            }
        }
    }
    
    /*-----------------------以下是LCD1602显示驱动------------------*/
    //定义LCD1602显示相关的IO接口
    #define LCD1602_DB  P0
    sbit LCD1602_RS = P1^0;
    sbit LCD1602_RW = P1^1;
    sbit LCD1602_E  = P1^5;
    //LCD1602函数调用申明
    void LcdShowStr(unsigned char x, unsigned char y,unsigned char *str, unsigned char len);
    //显示控制模块
    void display()
    {
        
        static int intTb, decTb;    //温度值的整数和小数部分备份
        static bit signb;           //温度值的正负(1正,0负)备份
        if(iswaring == 1)
        {
            LcdShowStr(0,1,waringstr,16);
        }
        else
        {
            LcdShowStr(0,1,striswaring,11);
        }
        if((decTb != decT) || (intTb != intT) || (signb != sign))//如果有变化
        {
            /*备份当前值*/
            decTb = decT;
            intTb = intT;
            signb = sign;
            if(intT>126)    //如果信息错误,这个判断是温度显示特有的
            {
                unsigned char i = 1;
                //显示错误Error!
                strbuff[10] = '!';
                strbuff[9] = 'r';
                strbuff[8] = 'o';
                strbuff[7] = 'r';
                strbuff[6] = 'r';
                strbuff[5] = 'E';
                for(i = 0;i<5;i++)
                {
                    strbuff[i] = ' ';
                }
            }else{          //信息正确
                if(sign == 1)strbuff[0] = ' ';else strbuff[0] = '-';//符号位
                if((intT/100) == 0)strbuff[1] = ' ';else strbuff[1] = ((intT/100)%10)+0x30;//百位
                if((intT/10) == 0)strbuff[2] = ' ';else strbuff[2] = ((intT/10)%10)+0x30;//十位
                if((intT) == 0)strbuff[3] = ' ';else strbuff[3] = (intT%10)+0x30;//个位加“.”
                if((decT/1000) == 0)strbuff[5] = '0';else strbuff[5] = ((decT/1000)%10)+0x30;//十分位
                if((decT/100) == 0)strbuff[6] = '0';else strbuff[6] = ((decT/100)%10)+0x30;//百分位
                if((decT/10) == 0)strbuff[7] = '0';else strbuff[7] = ((decT/10)%10)+0x30;//千分位
                if((decT) == 0)strbuff[8] = '0';else strbuff[8] = (decT%10)+0x30;//万分位
                /*以上是 载数码管缓存代码,把十进制分离,大家自己研究这里不多解释*/
                strbuff[4] = '.';
                strbuff[9] = 0XDF;//‘°’
                strbuff[10] = 'C';
            }
            
            LcdShowStr(4,0,strbuff,11); //显示,初始位置随意,只要能显示完整就好
        }
    }
    
    //等待液晶准备好
    void LcdWaitReady()
    {
        unsigned char sta;
         
        LCD1602_DB = 0xFF;
        LCD1602_RS = 0;
        LCD1602_RW = 1;
        do {
            LCD1602_E = 1;      //使能LCD1602
            sta = LCD1602_DB;   //读取状态字
            LCD1602_E = 0;      //避免干扰其他器件
        } while (sta & 0x80);   //第七位等于1表示液晶正忙,重复检测直到第七位等于0为止
    }
    //向LCD1602液晶写入一字节命令,cmd为待写入命令值
    void LcdWriteCmd(unsigned char cmd)
    {
        LcdWaitReady();
        LCD1602_RS = 0;
        LCD1602_RW = 0;
        LCD1602_DB = cmd;
        LCD1602_E  = 1;
        LCD1602_E  = 0;
    }
    //向LCD1602液晶写入一字节数据,dat为待写入数据值
    void LcdWriteDat(unsigned char dat)
    {
        LcdWaitReady();
        LCD1602_RS = 1;
        LCD1602_RW = 0;
        LCD1602_DB = dat;
        LCD1602_E  = 1;
        LCD1602_E  = 0;
    }
    //设置显示RAM起始地址,亦即光标位置,(x,y)对应屏幕上的字符的坐标
    void LcdSetCursor(unsigned char x, unsigned char y)
    {
        unsigned char addr;
         
        if (y == 0)             //由输入的屏幕坐标计算显示RAM的地址
            addr = 0x00 + x;    //第一行字符地址从0x00起始
        else
            addr = 0x40 + x;    //第二行字符地址从0x40起始
        LcdWriteCmd(addr | 0x80);   //设置RAM地址
    }
    //在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,
    //str-字符串指针,len-需显示的字符长度
    void LcdShowStr(unsigned char x, unsigned char y,unsigned char *str, unsigned char len)
    {
        LcdSetCursor(x, y);   //设置起始地址
        while (len--)         //连续写入len个字符数据
        {
            LcdWriteDat(*str++);  //先取str指向的数据,然后str自加1
        }
    }
    
    void InitLcd1602()//初始化1602液晶
    {
        LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口
        LcdWriteCmd(0x0C);  //显示器开,光标关闭
        LcdWriteCmd(0x06);  //文字不动,地址自动+1
        LcdWriteCmd(0x01);  //清屏
    }
    
    
    /*-----------------------以下是温度传感器驱动------------------*/
    //DS18B20通信引脚
    sbit IO_18B20 = P3^2;
    void DelayX10us(unsigned char t)
    {
        do {
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
        } while (--t);
        /*_nop_()函数在12M晶振中延迟1us,为什么这里是8个_nop_()
        因为while和--t也是需要时间的,这里不一定是准确的10us/循环
        只是大致的时间*/
    }
    bit Get18B20Ack() //DS18B20存在检测函数 
    {
        bit ack;
    
        EA = 0;             //关中断 
        IO_18B20 = 0;       //拉低引脚 
        DelayX10us(50);     //延时500us(480us - 960us) 
        IO_18B20 = 1;       //释放总线 
        DelayX10us(6);      //延时60us(15us - 60us) 
        ack = IO_18B20;     //读取响应(60us - 240us) 
        while(!IO_18B20);   //等待DS18B20释放总线 (60us - 240us) 
        EA = 1;             //取消关中断 
    
        return ack;         //返回是否存在 (0:存在 1:不存在) 
    }
    
    void  Write18B20(unsigned char dat) //写DS18B20 
    {
        unsigned char mask;         //临时变量定义 
        EA = 0;                     //关中断 
        for(mask=0x01; mask!= 0; mask<<=1)  //循环发送单个bit位 
        {
            IO_18B20 = 0;           //拉低(请求读写操作) 
            _nop_();                //延时(1us < time <= 15us) 
            _nop_();
            if((mask&dat) == 0)     //按位读取dat 
                IO_18B20 = 0;       //本位是0,拉低 
            else
                IO_18B20 = 1;       //本位是1,拉高 
                //上面这个操作DS18B20读取(最小时间 0us<time<15us,
                //典型时间 15us,最大时间45us) 
            DelayX10us(6);          //等待60us(足够DS18B20读取) 
            IO_18B20 = 1;           //释放总线 
        }
        EA = 1;                     //取消关中断 
    }
    
    unsigned char Read18B20()       //读DS18B20 
    {
        unsigned char dat;          //数据缓存变量 
        unsigned char mask;         //临时变量 
    
        EA = 0;                     //关中断 
        for(mask=0x01; mask!=0; mask<<=1)//同上循环按位操作 
        {
            IO_18B20 = 0;           //读写请求 
            _nop_();                //等待(1us < time < 15us) 
            _nop_();
            IO_18B20 = 1;           //初始化读操作 
            _nop_();                //等待DS18B20输出 
            _nop_();
            if(!IO_18B20)           //读 
                dat &= ~mask;       //“0” 
            else
                dat |= mask;        //“1” 
            DelayX10us(6);          //等待DS18B20释放总线 
        }
        EA = 1;                     //取消关中断 
    
        return dat;                 //返回数据 
    }
    
    bit Start18B20()        //初始化DS18B20 
    {
        bit ack;            //存在标志 
    
        ack = Get18B20Ack();//检测存在 
        if(ack == 0)        //存在 
        {                   //写命令使工作
            Write18B20(0xCC);   //跳过ROM检测 
            Write18B20(0x44);   //启动温度转换 
        }
        return ~ack;        //返回是否成功(1是,0否) 
    }
    
    bit Get18B20Temp(int *temp) //获取DS18B20温度存于temp 
    {
        bit ack;                //存在标志 
        unsigned char LSB, MSB; //数据低/高位 
    
        ack = Get18B20Ack();    //检测存在 
        if(ack == 0)            //存在 
        {                       //写指令 
            Write18B20(0xCC);   //跳过ROM检测 
            Write18B20(0xBE);   //读寄存器 
            LSB = Read18B20();  //读低位 
            MSB = Read18B20();  //读高位 
            *temp = ((int)MSB<<8) + LSB;    //合并 
        }
        return ~ack;            //返回结果(1成功,0失败) 
    }
    
    
    /*-----------------------以下是蜂鸣器演奏------------------*/
    #define SYSTEM_OSC      11059200    //12000000  //定义晶振频率12000000HZ
    #define SOUND_SPACE     4/5         //定义普通音符演奏的长度分率,//每4分音符间隔
    sbit    BeepIO    =     P1^6;       //定义输出管脚
    
    unsigned int  code FreTab[12]  = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表
    unsigned char code SignTab[7]  = { 0,2,4,5,7,9,11 };                                  //1~7在频率表中的位置
    unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };                      
    unsigned char Sound_Temp_TH0,Sound_Temp_TL0;    //音符定时器初值暂存 
    unsigned char Sound_Temp_TH1,Sound_Temp_TL1;    //音长定时器初值暂存
    unsigned char Signature;
    unsigned char Octachord;
    unsigned int Speed;
    unsigned char *Sound;
    unsigned int NewFreTab[12];                     //新的频率表
    unsigned char i,j;
    unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
    unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
    //unsigned int len = 0,poi = 0;     //备份SoundLength
    
    
    void InitialSound(unsigned char *Sound0,unsigned char Signature0,
        unsigned char Octachord0,unsigned int Speed0)
    {
        Signature = Signature0;
        Octachord = Octachord0;
        Speed = Speed0;
        Sound = Sound0;
        
        for(i=0;i<12;i++)               // 根据调号及升降八度来生成新的频率表 
        {
            j = i + Signature;
            if(j > 11)
            {
                j = j-12;
                NewFreTab[i] = FreTab[j]*2;
            }
            else
                NewFreTab[i] = FreTab[j];
    
            if(Octachord == 1)
                NewFreTab[i]>>=2;
            else if(Octachord == 3)
                NewFreTab[i]<<=2;
        }                                   
        
        SoundLength = 1;
        while(Sound[SoundLength] != 0x00)   //计算歌曲长度
        {
            SoundLength+=2;
        }
    
        Point = 0;
        Tone   = Sound[Point];  
        Length = Sound[Point+1];            // 读出第一个音符和它时时值
        
        LDiv0 = 12000/Speed;                // 算出1分音符的长度(几个10ms)    
        LDiv4 = LDiv0/4;                    // 算出4分音符的长度 
        LDiv4 = LDiv4-LDiv4*SOUND_SPACE;    // 普通音最长间隔标准 
        
        BeepIO = 1;
        Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256;   // 计算TL1应装入的初值  (10ms的初装值)
        Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256;   // 计算TH1应装入的初值 
        TH1 = Sound_Temp_TH1;
        TL1 = Sound_Temp_TL1;
        TMOD  |= 0x11;
        ET0    = 1;
        ET1    = 0;
        TR0    = 0;
        TR1    = 0;
        EA     = 1;
            
        /*len = SoundLength;
        poi = Point;*/
    }
    
    void BeepTimer0(void) interrupt 1   //音符发生中断
    {
        BeepIO = !BeepIO;
        TH0    = Sound_Temp_TH0;
        TL0    = Sound_Temp_TL0;
    }
    
    void Play()
    {
        EA = 1;
        TR0   = 0;
        TR1   = 1;
        if(Point < SoundLength)
        {
            SL=Tone%10;                                 //计算出音符 
            SM=Tone/10%10;                              //计算出高低音 
            SH=Tone/100;                                //计算出是否升半 
            CurrentFre = NewFreTab[SignTab[SL-1]+SH];   //查出对应音符的频率     
            if(SL!=0)
            {
                if (SM==1) CurrentFre >>= 2;        //低音 
                if (SM==3) CurrentFre <<= 2;        //高音
                Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//计算计数器初值
                Sound_Temp_TH0 = Temp_T/256; 
                Sound_Temp_TL0 = Temp_T%256; 
                TH0 = Sound_Temp_TH0;  
                TL0 = Sound_Temp_TL0 + 12; //加12是对中断延时的补偿 
            }
            SLen=LengthTab[Length%10];  //算出是几分音符
            XG=Length/10%10;            //算出音符类型(0普通1连音2顿音) 
            FD=Length/100;
            LDiv=LDiv0/SLen;            //算出连音音符演奏的长度(多少个10ms)
            if (FD==1) 
            {
                LDiv=LDiv+LDiv/2;
            }
            
            if(XG!=1)
            {           
                if(XG==0)               //算出普通音符的演奏长度 
                {
                    if (SLen<=4)    
                    {
                        LDiv1=LDiv-LDiv4;
                    }else{
                        LDiv1=LDiv*SOUND_SPACE;
                    }
                }else{
                    LDiv1=LDiv/2;       //算出顿音的演奏长度 
                }
            }else{
                LDiv1=LDiv;
            }
            
            if(SL==0) 
            {
                LDiv1=0;
            }
            
            LDiv2=LDiv-LDiv1;       //算出不发音的长度 
            
            if (SL!=0)
            {
                TR0=1;
                for(i=LDiv1;i>0;i--)    //发规定长度的音 
                {
                    while(TF1==0);      //等待节拍过去
                    TH1 = Sound_Temp_TH1;//重装初值
                    TL1 = Sound_Temp_TL1;
                    TF1=0;              //清除中断标志位
                }
            }
            
            if(LDiv2!=0)
            {
                TR0=0; BeepIO=1;
                for(i=LDiv2;i>0;i--)    //音符间的间隔
                {
                    while(TF1==0);      //等待节拍过去
                    TH1 = Sound_Temp_TH1;//重装初值
                    TL1 = Sound_Temp_TL1;
                    TF1=0;              //清除中断标志位
                }
            }
            
            Point+=2; 
            Tone=Sound[Point];
            Length=Sound[Point+1];
            
        }
        else
        {
            /*SoundLength = len;
            Point = poi;*/
            InitialSound(Music_Croatian_Rhapsody,0,2,360);
        }
        BeepIO = 1;
        
        TR0   = 0;
        TR1   = 0;
    }
    
    //这里放生成的音乐数据
    unsigned char code Music_Croatian_Rhapsody[]={
        0x1B,0x04, 0x1F,0x04, 0x1A,0x17, 0x17,0x04, 0x18,0x04,
        0x16,0x7B, 0x18,0x68, 0x19,0x04, 0x17,0x03, 0x17,0x03,
        0x11,0x04, 0x15,0x04, 0x10,0x03, 0x11,0x04, 0x15,0x04,
        0x10,0x02, 0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1B,0x04,
        0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1F,0x04, 0x20,0x04,
        0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04,
        0x1A,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x68, 0x19,0x04,
        0x1A,0x04, 0x1B,0x04, 0x17,0x04, 0x19,0x04, 0x1B,0x04,
        0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04,
        0x17,0x04, 0x21,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04,
        0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04,
        0x1F,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x21,0x04,
        0x17,0x68, 0x19,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04,
        0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x21,0x04,
        0x17,0x04, 0x1A,0x02, 0x1F,0x04, 0x17,0x04, 0x1A,0x04,
        0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1A,0x04, 0x1F,0x04,
        0x20,0x04, 0x17,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04,
        0x17,0x04, 0x1A,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x68,
        0x19,0x04, 0x1A,0x04, 0x1B,0x04, 0x17,0x04, 0x19,0x04,
        0x1B,0x04, 0x1F,0x04, 0x17,0x04, 0x1B,0x04, 0x17,0x04,
        0x1A,0x04, 0x17,0x04, 0x21,0x04, 0x17,0x04, 0x1F,0x04,
        0x17,0x04, 0x1A,0x04, 0x1B,0x04, 0x1F,0x04, 0x17,0x04,
        0x1A,0x04, 0x1F,0x04, 0x20,0x04, 0x17,0x04, 0x1F,0x04,
        0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04,
        0x21,0x04, 0x17,0x68, 0x19,0x04, 0x17,0x04, 0x1F,0x04,
        0x17,0x04, 0x1B,0x04, 0x17,0x04, 0x1A,0x04, 0x17,0x04,
        0x21,0x04, 0x17,0x04, 0x1A,0x02, 0x00,0x00
    };
    

    怎么样

    音乐是不是很动听呢? ٩(●´৺`●)૭٩(●´৺'●)و,想尝试创作更多的蜂鸣器音乐吗?快发表你的看法吧!!

    哔哩哔哩效果视频演示:https://www.bilibili.com/video/BV1Dt41197b9/

    谢谢

  • 相关阅读:
    Java之IO(一)InputStream和OutputStream
    bitset库
    assert
    C++ 与 Python 混合编程
    C++多线程
    C++11新特性
    C++性能优化指南
    C++随机数
    C++中struct与class的区别
    C++杂记
  • 原文地址:https://www.cnblogs.com/minuy/p/14261843.html
Copyright © 2011-2022 走看看