51單片機(二十七)—— 蜂鳴器播放音樂

1、實驗原理介紹

        蜂鳴器是電路中經常使用的發聲器件,我們一般使用蜂鳴器發出“嘀嘀”的聲音,用它作爲提示音。有沒有想過用蜂鳴器還可以播放音樂呢?這顯然是件很有意思的事情。

        本文使用蜂鳴器來播放音樂。爲了深入瞭解此實驗的原理,先介紹一下音樂的基礎知識,音樂中的每個音調都有其固定的音高,簡譜記譜法由7個基本唱名組成,它們分別用1、2、3、4、5、6、7表示。每個唱名對應固定的音高。由聲學角度看,音高不同,發聲物體振動的頻率就不一樣。

        下圖爲鋼琴鍵盤的一部分,圖中的C4鍵對應的就是簡譜唱名的中音1,左側爲這個唱名對應的聲波的振動頻率。由此可以向上和向下推出其它唱名的頻率。

        要想使蜂鳴器發出不同的聲音就必須通過PWM波來驅動蜂鳴器,調節PWM波的頻率就可以發出不同聲調的聲音。PWM是脈衝寬度調製的簡稱,PWM在控制中應用廣泛,可以用於電機調速,舵機控制,步進電機控制等。在這個實驗中我們用PWM波來驅動蜂鳴器發出不同聲調的聲音。

        這個實驗通過在T0中斷中改變BUZZ接口的電平狀態,來產生頻率一定的方波,來驅動蜂鳴器。改變定時器的計數初始值,就可以產生不同聲調的聲音。例如:唱名爲1的音的頻率爲262Hz,則它對應的週期約爲3816us,週期的一半爲1908us。也就是說當單片機採用12MHz晶振時,它的週期是1908個機器週期。則定時器的計數初始值爲65536-1908=63628,對應的16進制值爲0xF88C。以此類推,可以起算出其它唱名的計數初始值。

        在程序中,toneH[10]和toneL[10]用來存儲音調對應的計數初始值的高8位和低8位。soundtone[42]存儲的是需要發聲的音調,其中1~7代表唱名1~7。soundlong[42]用來存儲與soundtone[42]相對應的唱名的發聲時長。

        在本文中,我們用蜂鳴器來播放《小星星亮晶晶》這首簡單的兒歌,它的簡譜如下所示。

在使用蜂鳴器進行音樂播放時,驅動蜂鳴器的PWM信號按照簡譜的唱名改變爲相應的頻率,並持續相應的時長,就可以達到播放音樂的目的。

2、例程驗證

        在這個例程的代碼中,首先定義了幾個數組,如下所示。

code unsigned int toneH[10]={     //音調對應的定時器計數值的高8位 第一個音爲低音7
0XF8,0XF8,0XF9,0XFA,0XFA,0XFB,0XFB,0XFC,0XFC,0XFC
};
code unsigned int toneL[10]={     //音調對應的定時器計數值的低8位
0X18,0X8C,0X6B,0X15,0X67,0X04,0X90,0X0C,0X44,0XAC
};

code unsigned int soundtone[42]={
1,1,5,5,6,6,5,4,4,3,3,2,2,1,
5,5,4,4,3,3,2,5,5,4,4,3,3,2,
1,1,5,5,6,6,5,4,4,3,3,2,2,1
};

code unsigned int soundlong[42]={
1,1,1,1,1,1,2,1,1,1,1,1,1,2,
1,1,1,1,1,1,2,1,1,1,1,1,1,2,
1,1,1,1,1,1,2,1,1,1,1,1,1,2
};

在上面我們已經有了介紹,toneH[10]和toneL[10]用來存儲音調對應的計數初始值的高8位和低8位。soundtone[42]存儲的是需要發聲的音調,其中1~7代表唱名1~7,我們可以看到,這些唱名與簡譜中是一一對應的。soundlong[42]用來存儲與soundtone[42]相對應的唱名的發聲時長。

        這個例程的主函數如下所示

void main(void) 
{
    init_T0();  
    for(;;) 
    {
        for(t=0;t<42;t++) 
        {
            t_H=toneH[soundtone[t]];     //提取音調對應的定時器初始值
            t_L=toneL[soundtone[t]];
        	TH0=t_H;		  //給TH0和TL0賦值
        	TL0=t_L;
            TR0=1;              //打開定時器,蜂鳴器發聲
            delay1ms(soundlong[t]*500);    //延時soundlong[t]指定的時間長度
            BUZZ=0;             //蜂鳴器不發聲,停頓片刻
            TR0=0;
            delay1ms(50);
        }
        delay1ms(2000);
     } 
}

        在主函數中,首先初始化T0,這個初始化函數中,將T0設置爲16位定時器,在中斷處理函數中,改變蜂鳴器控制IO口的電平狀態。然後代碼進入for循環,在for循環中,又進入另一個for循環,這個for循環,對這段音樂的每個唱名進行遍歷,將T0的計時寄存器按照唱名進行賦值,並延時soundlong[42]要求的時間長度。遍歷完soundtone[42]中所有的唱名,則完成音樂的播放,再進入下一個大的for循環,進行再次播放。

        將代碼燒寫到51單片機中,可以聽到悅耳的音樂。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章