【制作】基於金沙灘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/

謝謝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM