色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > mcu音樂程序的設(shè)計(jì)與實(shí)驗(yàn)

          mcu音樂程序的設(shè)計(jì)與實(shí)驗(yàn)

          作者: 時(shí)間:2016-11-27 來源:網(wǎng)絡(luò) 收藏
          利用單片機(jī)(或單板機(jī))奏樂大概是無線電愛好者感興趣的問題之一。本文從單片機(jī)的基本發(fā)間實(shí)驗(yàn)出發(fā),談?wù)?strong>音樂程序的設(shè)計(jì)原理,并給出具體實(shí)例,以供參考。

          1.單片機(jī)的基本發(fā)音實(shí)驗(yàn)

          本文引用地址:http://cafeforensic.com/article/201611/322391.htm

          我們知道,聲音的頻譜范圍約在幾十到幾千赫茲,若能利用程序來控制單處機(jī)某個(gè)口線的“高”電平或低電平,則在該口線上就能產(chǎn)生一定頻率的矩形波,接上喇叭就能發(fā)出一定頻率的聲音,若再利用延時(shí)程序控制“高”“低”電平的持續(xù)時(shí)間,就能改變輸出頻率,從而改變音調(diào)。

          例如,要產(chǎn)生200HZ的音頻信號,按圖1接入喇叭(若屬臨時(shí)實(shí)驗(yàn),也可將喇叭直接接在P1口線上),實(shí)驗(yàn)程序?yàn)椋?/p>

          其中子程序DEL為延時(shí)子程序,當(dāng)R3為1時(shí),延時(shí)時(shí)間約為20us,R3中存放延時(shí)常數(shù),對200HZ音頻,其周期為1/200秒,即5ms。這樣,當(dāng)P1.4的高電平或低電平的持續(xù)時(shí)間為2.5ms,即R3的時(shí)間常數(shù)取2500/20=125(7DH)時(shí),就能發(fā)出200HZ的音調(diào)。將上述程序鍵入學(xué)習(xí)機(jī),并不斷修改R3的常數(shù)可以感到音調(diào)的變化。

          樂曲中,每一音符對應(yīng)著確定的頻率,表1給出C調(diào)時(shí)各音符頻率及其相應(yīng)的時(shí)間常數(shù)。

          讀者可以根據(jù)表1所提供的常數(shù),將其16進(jìn)制代碼送入R3,反復(fù)練習(xí)體會(huì)。根據(jù)表1可以奏出音符。僅這還不夠,要準(zhǔn)確奏出一首曲子,必須準(zhǔn)確地控制樂曲節(jié)奏,即一音符的持續(xù)時(shí)間。

          音符的節(jié)拍我們可以用定時(shí)器T0來控制,送入不同的初值,就可以產(chǎn)生不同的定時(shí)時(shí)間。便如某歌曲的節(jié)奏為每分鐘94拍,即一拍為0.64秒。其它節(jié)拍與時(shí)間的對應(yīng)關(guān)系見表2。

          但時(shí),由于T0的最大定時(shí)時(shí)間只能為131毫秒,因此不可能直接用改變T0的時(shí)間初值來實(shí)現(xiàn)不同節(jié)拍。我們可以用T0來產(chǎn)生10毫秒的時(shí)間基準(zhǔn),然后設(shè)置一個(gè)中斷計(jì)數(shù)器,通過判別中斷計(jì)數(shù)器的值來控制節(jié)拍時(shí)間的長短。表2中也給出了各種節(jié)拍所對應(yīng)的時(shí)間常數(shù)。例如對1/4拍音符,定時(shí)時(shí)間為0.16秒,相應(yīng)的時(shí)間常數(shù)為16(即10H);對3拍音符,定時(shí)時(shí)間為1.92秒,相應(yīng)時(shí)間長數(shù)為192(即C0H)。

          我們將每一音符的時(shí)間常數(shù)和其相應(yīng)的節(jié)拍常數(shù)作為一組,按順序?qū)非械乃谐?shù)排列成一個(gè)表,然后由查表程序依次取出,產(chǎn)生音符并控制節(jié)奏,就可以實(shí)現(xiàn)演奏效果。

          此外,結(jié)束符和體止符可以分別用代碼00H和FFH來表示,若查表結(jié)果為00H,則表示曲子終了;若查表結(jié)果為FFH,則產(chǎn)生相應(yīng)的停頓效果。

          為了產(chǎn)生手彈的節(jié)奏感,在某些音符(例如兩個(gè)相同音符)音插入一個(gè)時(shí)間單位的頻率略有不同的音符。

          程序框圖如圖2所示。

          可直接在TD-III型學(xué)習(xí)機(jī)上演奏,對其它不同型號的學(xué)習(xí)機(jī),只需相應(yīng)地改變一下地址即可。本程序演奏的是民歌“八月桂花遍地開”,C調(diào),節(jié)奏為94拍/分。讀者也可以自行找出一首歌,按表1和表2給定的常數(shù),將樂曲翻譯成碼表輸入機(jī)器,而程序不變。本實(shí)驗(yàn)方法簡便,即使不懂音樂的人,將一首陌生的曲子翻譯成代碼也是易事,和著機(jī)器的演奏學(xué)唱一首歌曲,其趣味無窮。

          from:http://www.c51.cn/mcu/mcs51yy/200604/mcu_20060422123021_4081.html

          下面這個(gè)例子是我在網(wǎng)上找的簡單易懂,只不過是用C編寫的,而且基本思想跟上面講的相同。

          #i nclude
          #i nclude
          //本例采用89C52, 晶振為11.0592MHZ
          //關(guān)于如何編制音樂代碼, 其實(shí)十分簡單,各位可以看以下代碼.
          //頻率常數(shù)即音樂術(shù)語中的音調(diào),而節(jié)拍常數(shù)即音樂術(shù)語中的多少拍;
          //所以拿出譜子, 試探編吧!


          unsigned char n=0;//n為節(jié)拍常數(shù)變量
          unsigned char code music_tab[] ={
          0x18, 0x30, 0x1C , 0x10, //格式為: 頻率常數(shù), 節(jié)拍常數(shù), 頻率常數(shù), 節(jié)拍常數(shù),
          0x20, 0x40, 0x1C , 0x10,
          0x18, 0x10, 0x20 , 0x10,
          0x1C, 0x10, 0x18 , 0x40,
          0x1C, 0x20, 0x20 , 0x20,
          0x1C, 0x20, 0x18 , 0x20,
          0x20, 0x80, 0xFF , 0x20,
          0x30, 0x1C, 0x10 , 0x18,
          0x20, 0x15, 0x20 , 0x1C,
          0x20, 0x20, 0x20 , 0x26,
          0x40, 0x20, 0x20 , 0x2B,
          0x20, 0x26, 0x20 , 0x20,
          0x20, 0x30, 0x80 , 0xFF,
          0x20, 0x20, 0x1C , 0x10,
          0x18, 0x10, 0x20 , 0x20,
          0x26, 0x20, 0x2B , 0x20,
          0x30, 0x20, 0x2B , 0x40,
          0x20, 0x20, 0x1C , 0x10,
          0x18, 0x10, 0x20 , 0x20,
          0x26, 0x20, 0x2B , 0x20,
          0x30, 0x20, 0x2B , 0x40,
          0x20, 0x30, 0x1C , 0x10,
          0x18, 0x20, 0x15 , 0x20,
          0x1C, 0x20, 0x20 , 0x20,
          0x26, 0x40, 0x20 , 0x20,
          0x2B, 0x20, 0x26 , 0x20,
          0x20, 0x20, 0x30 , 0x80,
          0x20, 0x30, 0x1C , 0x10,
          0x20, 0x10, 0x1C , 0x10,
          0x20, 0x20, 0x26 , 0x20,
          0x2B, 0x20, 0x30 , 0x20,
          0x2B, 0x40, 0x20 , 0x15,
          0x1F, 0x05, 0x20 , 0x10,
          0x1C, 0x10, 0x20 , 0x20,
          0x26, 0x20, 0x2B , 0x20,
          0x30, 0x20, 0x2B , 0x40,
          0x20, 0x30, 0x1C , 0x10,
          0x18, 0x20, 0x15 , 0x20,
          0x1C, 0x20, 0x20 , 0x20,
          0x26, 0x40, 0x20 , 0x20,
          0x2B, 0x20, 0x26 , 0x20,
          0x20, 0x20, 0x30 , 0x30,
          0x20, 0x30, 0x1C , 0x10,
          0x18, 0x40, 0x1C , 0x20,
          0x20, 0x20, 0x26 , 0x40,
          0x13, 0x60, 0x18 , 0x20,
          0x15, 0x40, 0x13 , 0x40,
          0x18, 0x80, 0x00
          };

          void int0()interrupt 1//采用中斷0 控制節(jié)拍
          {TH0=0xd8;
          TL0=0xef;
          n--;
          }

          void delay (unsigned char m)//控制頻率延時(shí)
          {
          unsigned i=3*m;
          while(--i);
          }

          void delayms(unsigned char a)//豪秒延時(shí)子程序
          {
          while(--a);//采用while(--a) 不要采用while(a--); 各位可編譯一下看看匯編結(jié)果就知道了!
          }

          void main()
          { unsigned char p,m;//m為頻率常數(shù)變量
          unsigned char i=0;
          TMOD&=0x0f;
          TMOD =0x01;
          TH0=0xd8;TL0=0xef;
          IE=0x82;
          play:
          while(1)
          {
          a: p=music_tab[i];
          if(p==0x00){ i=0, delayms(1000); goto play;}//如果碰到結(jié)束符,延時(shí)1秒,回到開始再來一遍
          else if(p==0xff){ i=i+1;delayms(100),TR0=0; goto a;}//若碰到休止符,延時(shí)100ms,繼續(xù)取下一音符
          else{m=music_tab[i++], n=music_tab[i++];}//取頻率常數(shù) 和 節(jié)拍常數(shù)
          TR0=1;//開定時(shí)器1
          while(n!=0) P1=~P1,delay(m);//等待節(jié)拍完成, 通過P1口輸出音頻(可多聲道哦!)
          TR0=0;//關(guān)定時(shí)器1
          }
          }




          關(guān)鍵詞: mcu音樂程

          評論


          技術(shù)專區(qū)

          關(guān)閉