那么,今天分享的是利用蜂鳴器來(lái)演奏一些簡(jiǎn)單的樂(lè)譜。
實(shí)驗(yàn)平臺(tái)為stm32,當(dāng)然51也完全可以做,其核心思想是相似的。
首先是對(duì)蜂鳴器的介紹。蜂鳴器是一種一體化結(jié)構(gòu)的電子訊響器,采用直流電壓供電,廣泛應(yīng)用于計(jì)算機(jī)、打印機(jī)、復(fù)印機(jī)、報(bào)警器、電子玩具、汽車(chē)電子設(shè)備、電話(huà)機(jī)、定時(shí)器等電子產(chǎn)品中作發(fā)聲器件。
蜂鳴器包括有源蜂鳴器和無(wú)源蜂鳴器,有源蜂鳴器只要通上電就可以發(fā)聲,而無(wú)源蜂鳴器需要有一定頻率的脈沖才能發(fā)聲。
上圖為無(wú)源蜂鳴器電路,下圖為有源蜂鳴器電路。因?yàn)?a target="_blank">單片機(jī)的輸出電流很小,不能直接驅(qū)動(dòng)蜂鳴器,所以用了三極管來(lái)放大電流。在上邊的電路中,當(dāng)輸入高電平時(shí),三極管導(dǎo)通,電流可以由3.3V電源流向蜂鳴器,當(dāng)輸入低電平時(shí),三極管截止,蜂鳴器與GND相連。通過(guò)單片機(jī)管腳輸出一段脈沖,即可讓蜂鳴器發(fā)聲。在下邊的電路中,只要輸入為低電平,三極管導(dǎo)通,蜂鳴器就可以發(fā)聲。
那么,蜂鳴器發(fā)出的聲音大小、音調(diào)高低和什么有關(guān)呢?聲音大小和輸入脈沖的占空比有關(guān),占空比越大,聲音越大,而音調(diào)的高低和脈沖頻率有關(guān),頻率越高,音調(diào)也就越高,通常讓輸出頻率為1.5~5kHZ。
接下來(lái)講解具體如何實(shí)現(xiàn)讓蜂鳴器演奏樂(lè)譜。
首先得對(duì)音樂(lè)簡(jiǎn)譜有一定了解。本人對(duì)音樂(lè)簡(jiǎn)譜也并不算很了解,如果要深入了解,請(qǐng)自行百度搜索。下面是我的一些粗略見(jiàn)解。
一首曲子包含音調(diào)和節(jié)拍。音調(diào)也就是平常我們說(shuō)的音調(diào),比如1,2,3,4,5,6,7。音調(diào)越來(lái)越高,音調(diào)還包括低音、中音、高音。而節(jié)拍就是一個(gè)調(diào)子唱多久,有的音拖的長(zhǎng)一些,有的音就比較短。這兩個(gè)要素是今天編程的核心。
首先說(shuō)音調(diào),前面講到,音調(diào)的高低是和脈沖的頻率有關(guān)系的,這個(gè)關(guān)系已經(jīng)有人將它做成了表格,下面截取一部分:
頻率與周期成倒數(shù),在一個(gè)脈沖里面,讓一半為高電平,一半為低電平,而脈沖周期可以通過(guò)延時(shí)函數(shù)來(lái)確定,于是,編寫(xiě)頻率發(fā)生函數(shù)。
while(1)
{
beep=!beep;
led1=0;
delay_us(music[k]);
}
其中在delay_us()這個(gè)函數(shù)里的輸入參數(shù)就可以根據(jù)樂(lè)譜然后查表得到,就是上面的半周期。 由于這個(gè)參數(shù)是隨著樂(lè)譜變化的,因此,我們可以把樂(lè)譜轉(zhuǎn)化之后的數(shù)據(jù)放到一個(gè)數(shù)組里面,持續(xù)地調(diào)用數(shù)組里的數(shù)據(jù)。
這樣,音調(diào)就解決了。 接下來(lái)解決節(jié)拍的問(wèn)題。 其實(shí)要解決節(jié)拍的問(wèn)題,無(wú)非就是要考慮music[k]多久刷新一次。 我們可以想象一下,如果music[k]是每隔固定的一段時(shí)間跳到下一個(gè),那么造成的后果就是兩個(gè)音調(diào)之間的時(shí)間是一樣的,這樣聽(tīng)起來(lái)肯定是非常怪的。 假設(shè)music[k]刷新的特別快,beep剛好發(fā)生一次翻轉(zhuǎn),music[k]就發(fā)生了改變,這樣也是不行的,因?yàn)槿绻⑿逻@么快的話(huà),它連一個(gè)完整的脈沖周期都沒(méi)有走完。 因此,music[k]應(yīng)該要刷新慢一些,并且是隨著樂(lè)譜改變的。 刷新的慢,聽(tīng)起來(lái)就會(huì)比較舒緩而已。
所以,我們可以采用定時(shí)器中斷來(lái)實(shí)現(xiàn)。 每次發(fā)生中斷,就讓數(shù)組里的數(shù)據(jù)跳到下一個(gè),實(shí)現(xiàn)數(shù)據(jù)的刷新,同時(shí),改變定時(shí)器裝載值,讓每次發(fā)生中斷所需的時(shí)間不一樣,這個(gè)時(shí)間就是由樂(lè)譜的節(jié)拍決定的。
實(shí)現(xiàn)函數(shù)
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update))
{
if(k
這樣也就完美解決了節(jié)拍的問(wèn)題。 解決了這兩個(gè)問(wèn)題,理論上我們可以把任何一首簡(jiǎn)譜轉(zhuǎn)化為頻率(周期)和節(jié)拍(間隔時(shí)間)這兩個(gè)量,然后用數(shù)組保存好,這樣就可以通過(guò)蜂鳴器演奏出來(lái)了,當(dāng)然,這需要花費(fèi)很多的時(shí)間和精力,而且對(duì)于很多人來(lái)說(shuō),并不是很容易看懂簡(jiǎn)譜。
于是,有了一款軟件可以比較方便的獲取這些數(shù)據(jù),軟件截圖如下
曲譜存貯格式 unsigned char code MusicName{音高,音長(zhǎng),音高,音長(zhǎng)...., 0,0}; 末尾:0,0 表示結(jié)束(Important)
音高由三位數(shù)字組成:
個(gè)位是表示 1~7 這七個(gè)音符
十位是表示音符所在的音區(qū):1-低音,2-中音,3-高音;
百位表示這個(gè)音符是否要升半音: 0-不升,1-升半音。
音長(zhǎng)最多由三位數(shù)字組成:
個(gè)位表示音符的時(shí)值,其對(duì)應(yīng)關(guān)系是:
|數(shù)值(n): |0 |1 |2 |3 | 4 | 5 | 6
|幾分音符: |1 |2 |4 |8 |16 |32 |64 音符=2^n
十位表示音符的演奏效果(0-2): 0-普通,1-連音,2-頓音
百位是符點(diǎn)位: 0-無(wú)符點(diǎn),1-有符點(diǎn)
調(diào)用演奏子程序的格式
Play(樂(lè)曲名,調(diào)號(hào),升降八度,演奏速度);
|樂(lè)曲名 : 要播放的樂(lè)曲指針,結(jié)尾以(0,0)結(jié)束;
|調(diào)號(hào)(0-11) :是指樂(lè)曲升多少個(gè)半音演奏;
|升降八度(1-3) : 1:降八度, 2:不升不降, 3:升八度;
|演奏速度(1-12000):值越大速度越快;
這款軟件提取的信息比較豐富,如果要求不高的話(huà),只要能夠大概使用一下就好。比如它生成的音高,如果我們只是用來(lái)延時(shí)的話(huà),那么只要把它擴(kuò)大或者縮小一定倍數(shù),使它落在頻率(周期)區(qū)間(前面講到是1.5~5kHZ,換算成半周期就是100us~500us左右),這樣就可以比較簡(jiǎn)單的利用了。
總結(jié):用蜂鳴器演奏樂(lè)曲,主要是要把握住兩個(gè)核心。 一個(gè)是音調(diào) ,這個(gè)通過(guò)改變脈沖頻率來(lái)實(shí)現(xiàn),其實(shí)就是通過(guò)精確延時(shí)來(lái)改變脈沖周期。 另一個(gè)是節(jié)拍 ,節(jié)拍可以簡(jiǎn)單理解為兩個(gè)音調(diào)之間的時(shí)間間隔,要控制不同的節(jié)拍,其實(shí)就是隔多長(zhǎng)的時(shí)間去刷新前面的音調(diào),那么可以通過(guò)定時(shí)器中斷來(lái)實(shí)現(xiàn),定時(shí)的時(shí)間就是節(jié)拍長(zhǎng)度,一旦發(fā)生中斷,就刷新前面的音調(diào),同時(shí),給定時(shí)器裝載一個(gè)新的值。
-
三極管
+關(guān)注
關(guān)注
143文章
3616瀏覽量
122086 -
報(bào)警器
+關(guān)注
關(guān)注
12文章
927瀏覽量
108801 -
蜂鳴器
+關(guān)注
關(guān)注
12文章
892瀏覽量
46001 -
有源蜂鳴器
+關(guān)注
關(guān)注
0文章
30瀏覽量
11636
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論