找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1784|回復(fù): 4
收起左側(cè)

51單片機播放《可可托海牧羊人》問題

[復(fù)制鏈接]
ID:886808 發(fā)表于 2021-3-2 13:18 來自手機 | 顯示全部樓層 |閱讀模式
最近有一首歌挺火,又登上春晚。過年時沒事我按《51單片機例程100》把它改成音樂編碼用單片機播放。原例程的譜子中沒有休止符,可這首歌多次出現(xiàn)不同拍節(jié)的休止符。我按音符宏定義的方法定義了休止符,頻率為0,可播放休止符時聲音變味,后來又用了關(guān)蜂鳴器等方法均不理想。在這里請教大俠,應(yīng)怎么處理。原倒程和我編的歌曲碼附后:
  1. //實例49用定時器T0的中斷實現(xiàn)"渴望"主題曲的播放 #include<reg51.h>   //包含51單片機寄存器定義的頭文件 /
  2. sbit sound=P3^7;    //將sound位定義為P3.7
  3. unsigned int C;     //儲存定時器的定時常數(shù)
  4. //以下是C調(diào)低音的音頻宏定義
  5. #define l_dao 262   //將“l(fā)_dao”宏定義為低音“1”的頻率262Hz
  6. #define l_re 286    //將“l(fā)_re”宏定義為低音“2”的頻率286Hz
  7. #define l_mi 311    //將“l(fā)_mi”宏定義為低音“3”的頻率311Hz
  8. #define l_fa 349    //將“l(fā)_fa”宏定義為低音“4”的頻率349Hz
  9. #define l_sao 392   //將“l(fā)_sao”宏定義為低音“5”的頻率392Hz
  10. #define l_la 440    //將“l(fā)_a”宏定義為低音“6”的頻率440Hz
  11. #define l_xi 494    //將“l(fā)_xi”宏定義為低音“7”的頻率494Hz
  12. //以下是C調(diào)中音的音頻宏定義
  13. #define dao 523     //將“dao”宏定義為中音“1”的頻率523Hz
  14. #define re 587      //將“re”宏定義為中音“2”的頻率587Hz
  15. #define mi 659      //將“mi”宏定義為中音“3”的頻率659Hz
  16. #define fa 698      //將“fa”宏定義為中音“4”的頻率698Hz
  17. #define sao 784     //將“sao”宏定義為中音“5”的頻率784Hz
  18. #define la 880      //將“l(fā)a”宏定義為中音“6”的頻率880Hz
  19. #define xi 987      //將“xi”宏定義為中音“7”的頻率523H      
  20. //以下是C調(diào)高音的音頻宏定義
  21. #define h_dao 1046     //將“h_dao”宏定義為高音“1”的頻率1046Hz
  22. #define h_re 1174      //將“h_re”宏定義為高音“2”的頻率1174Hz
  23. #define h_mi 1318      //將“h_mi”宏定義為高音“3”的頻率1318Hz
  24. #define h_fa 1396     //將“h_fa”宏定義為高音“4”的頻率1396Hz
  25. #define h_sao 1567    //將“h_sao”宏定義為高音“5”的頻率1567Hz
  26. #define h_la 1760     //將“h_la”宏定義為高音“6”的頻率1760Hz  #define h_xi 1975     //將“h_xi”宏定義為高音“7”的頻率1
  27. //函數(shù)功能1個延時單位延時200ms
  28. void delay()               
  29.    {
  30.      unsigned char i,j;
  31.    for(i=0;i<250;i++)
  32.      for(j=0;j<250;j++)
  33.         ;
  34.    }
  35. //函數(shù)功能主函數(shù)
  36. void main(void)
  37.   {
  38.   unsigned char i,j;            
  39. //以下是《渴望》片頭曲的一段簡譜
  40.    unsigned  int code f[]={re,mi,re,dao,l_la,dao,l_la,   //每行對應(yīng)一小節(jié)音符                          l_sao,l_mi,l_sao,l_la,dao,
  41.              l_la,dao,sao,la,mi,sao,
  42.              re,      
  43.              mi,re,mi,sao,mi,
  44.              l_sao,l_mi,l_sao,l_la,dao,                           l_la,l_la,dao,l_la,l_sao,l_re,l_mi,
  45.          l_sao,
  46.          re,re,sao,la,sao,
  47.          fa,mi,sao,mi,
  48.          la,sao,mi,re,mi,l_la,dao,
  49.          re,
  50.          mi,re,mi,sao,mi,
  51.          l_sao,l_mi,l_sao,l_la,dao,
  52.          l_la,dao,re,l_la,dao,re,mi,
  53.          re,
  54.          l_la,dao,re,l_la,dao,re,mi,
  55.          re,
  56. //以下為我編的可可托海牧羊人
  57. 前奏
  58. mi,mi,re,mi,fa,fa,mi,fa,fa,sao,la, xi,sao,fa,mi,
  59. //1.
  60. mi,re,mi,l_la,
  61. l_la,l_la,l_xi,l_la,l_la,l_xi,
  62. l_sao,l_mi,
  63. dao,dao,l_la,dao,
  64. l_la,re,mi,sao,la,mi,
  65. mi,mi,sao,sao,sao,mi,la,la,h_dao,la,sao,re,l_la,dao,re,mi,re,re,
  66. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,mi,l_xi,l_la,

  67. mi,re,mi,l_la,
  68. l_la,l_la,l_xi,l_la,l_la,l_xi,
  69. l_sao,l_mi,
  70. dao,dao,l_la,dao,
  71. l_la,dao,re,mi,sao,la,mi,
  72. mi,sao,sao,sao,mi,mi,la,xi,la,sao,mi,re,l_la,l_la,dao,re,mi,re,re,
  73. re,mi,l_sao,l_sao,l_sao,l_mi,l_mi,
  74. re,re,mi,dao,
  75. l_sao,l_sao,l_mi,l_sao,l_la,l_la,
  76. mi,sao,la,
  77. //以下反復(fù)開始
  78. la,la,sao,la,sao,la,xi,la,sao,sao,
  79. sao,la,re,
  80. re,re,mi,mi,sao,la,mi,mi,mi,
  81. mi,sao,sao,sao,sao,mi,mi,la,xi,la,sao,mi,
  82. re,l_la,l_la,dao,re,mi,re,re,
  83. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,re,mi,dao,dao,
  84. l_sao,l_sao,l_mi,l_sao,l_la,
  85. sao,la,re,re,re,mi,mi,sao,la,mi,mi,mi,
  86. mi,sao,sao,sao,mi,mi,la,xi,la,sao,mi,re,l_la,l_la,dao,re,mi,re,re,
  87. //mi,re,l_la,l_la,dao,re,mi,re,re,mi,la,
  88. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,re,mi,dao,dao,
  89. l_sao,l_sao,l_mi,l_sao,l_la,l_la,mi,sao,la,
  90. //反復(fù)結(jié)束
  91. la,la,sao,la,sao,la,xi,la,sao,sao,

  92. sao,la,re,
  93. re,re,mi,mi,sao,la,mi,mi,mi,
  94. mi,sao,sao,sao,sao,mi,mi,la,xi,la,sao,mi,
  95. re,l_la,l_la,dao,re,mi,re,re,
  96. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,re,mi,dao,dao,
  97. l_sao,l_sao,l_mi,l_sao,l_la,
  98. sao,la,re,re,re,mi,mi,sao,la,mi,mi,mi,
  99. mi,sao,sao,sao,mi,mi,la,xi,la,sao,mi,re,l_la,l_la,dao,re,mi,re,re,
  100. //mi,re,l_la,l_la,dao,re,mi,re,re,mi,la,
  101. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,re,mi,dao,dao,
  102. l_sao,l_sao,l_mi,l_sao,l_la,l_la,mi,sao,la,
  103. /*
  104. la,la,sao,la,sao,la,xi,la,sao,sao,
  105. sao,la,re,
  106. re,re,mi,mi,sao,la,mi,mi,mi,
  107. mi,sao,sao,sao,sao,mi,mi,la,xi,la,sao,mi,
  108. re,l_la,l_la,dao,re,mi,re,re,
  109. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,re,mi,dao,dao,
  110. l_sao,l_sao,l_mi,l_sao,l_la,
  111. sao,la,re,re,re,mi,mi,sao,la,mi,mi,mi,
  112. mi,sao,sao,sao,mi,mi,la,xi,la,sao,mi,re,l_la,l_la,dao,re,mi,re,re,
  113. mi,re,l_la,l_la,dao,re,mi,re,re,mi,la,
  114. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,re,mi,dao,dao,
  115. l_sao,l_sao,l_mi,l_sao,l_la,l_la,mi,sao,la,
  116. //3
  117. la,la,sao,la,sao,la,xi,la,sao,sao,
  118. sao,la,re,
  119. re,re,mi,mi,sao,la,mi,mi,mi,
  120. mi,sao,sao,sao,sao,mi,mi,la,xi,la,sao,mi,
  121. re,l_la,l_la,dao,re,mi,re,re,
  122. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,re,mi,dao,dao,
  123. l_sao,l_sao,l_mi,l_sao,l_la,
  124. sao,la,re,re,re,mi,mi,sao,la,mi,mi,mi,
  125. mi,sao,sao,sao,mi,mi,la,xi,la,sao,mi,re,l_la,l_la,dao,re,mi,re,re,
  126. mi,re,l_la,l_la,dao,re,mi,re,re,mi,la,
  127. re,mi,l_sao,l_sao,l_mi,l_sao,l_la,re,re,mi,dao,dao,
  128. l_sao,l_sao,l_mi,l_sao,l_la,l_la,mi,sao,la,*/
  129. //結(jié)束
  130. l_sao,l_sao,l_mi,l_sao,l_la,l_la,
  131.          0xff}; //以0xff作為音符的結(jié)束標(biāo)志  
  132. //以下是簡譜中每個音符的節(jié)拍
  133. //"4"對應(yīng)4個延時單位"2"對應(yīng)2個延時單位"1"對應(yīng)1個延時單位  
  134. unsigned char code JP[ ]={4,1,1,4,1,1,2,   
  135.                      2,2,2,2,8,
  136.        4,2,3,1,2,2,
  137.        10,         4,2,2,4,4,
  138.        2,2,2,2,4,
  139.                      2,2,2,2,2,2,2,
  140.        10,
  141.        4,4,4,2,2,
  142.        4,2,4,4,
  143.        4,2,2,2,2,2,2,
  144.        10,
  145.        4,2,2,4,4,
  146.        2,2,2,2,6,
  147.        4,2,2,4,1,1,4,
  148.        10,
  149.        4,2,2,4,1,1,4,
  150.          10,
  151. 6,1,2,1,6,1,2,1,3,3,1,1,1,1,6,
  152. //節(jié)拍開始
  153. 1,1,1,12,
  154. 1,1,2,1,1,2,
  155. 2,12,
  156. 1,1,1,3,
  157. 1,3,2,2,3,6,
  158. 1,1,2,2,2,2,2,1,1,2,2,2,2,1,1,1,1,3,
  159. 1,1,3,1,2,2,1,1,2,6,
  160. 1,1,1,6,
  161. 1,1,1,2,1,1,
  162. 2,12,
  163. 1,1,1,6,
  164. 1,1,2,2,1,3,6,
  165. 2,2,2,1,1,2,2,1,1,2,2,1,1,2,1,1,1,1,3,
  166. 1,1,2,2,2,1,1,
  167. 2,1,1,4,
  168. 2,1,1,2,2,4,
  169. 2,1,1,
  170. //以下反復(fù)開始
  171. 3,1,1,2,2,2,2,2,2,3,

  172. 2,2,4,
  173. 1,2,1,1,1,3,2,2,3,
  174. 2,2,1,1,1,1,2,2,1,1,2,2,
  175. 2,1,1,1,1,1,1,3,
  176. 1,1,2,1,1,2,2,2,1,1,2,2,
  177. 2,1,1,2,2,
  178. 2,2,3,1,2,1,1,1,3,2,2,4,
  179. 1,2,1,1,1,2,2,1,1,2,2,2,1,1,1,1,1,1,3,
  180. //mi,re,l_la,l_la,dao,re,mi,re,re,mi,la,
  181. 1,1,2,1,1,2,2,2,1,1,2,2,
  182. 2,1,1,2,2,4,2,1,1,
  183. //反復(fù)結(jié)束
  184. 3,1,1,2,2,2,2,2,2,4,

  185. 2,2,3,
  186. 1,2,1,1,1,3,2,2,4,
  187. 2,2,1,1,1,1,2,2,1,1,2,2,
  188. 2,1,1,1,1,1,1,3,
  189. 1,1,2,1,1,2,2,2,1,1,2,2,
  190. 2,1,1,2,2,
  191. 2,2,6,1,2,1,1,1,6,2,2,4,
  192. 1,2,1,1,1,
  193. //結(jié)束
  194. 2,1,1,2,2,4,
  195. 1,1,1,3,1,1,1,
  196. 10       };
  197.     EA=1;         //開總中斷
  198.     ET0=1;        //定時器T0中斷允許
  199.       TMOD=0x00;    // 使用定時器T0的模式113位計數(shù)器
  200.     while(1)       //無限循環(huán)
  201.    {
  202.     i=0;   //從第1個音符f[0]開始播放
  203.        while(f[i]!=0xff)            //只要沒有讀到結(jié)束標(biāo)志就繼續(xù)播放
  204.       {
  205.               C=460830/f[i];     
  206.               TH0=(8192-C)/32;   //可證明這是13位計數(shù)器TH0高8位的賦初值方法
  207.               TL0=(8192-C)%32;   //可證明這是13位計數(shù)器TL0低5位的賦初值方法
  208.               TR0=1;             //啟動定時器T0
  209.       for(j=0;j<JP[i];j++)  //控制節(jié)拍數(shù)
  210.                   delay();          //延時1個節(jié)拍單位
  211.       TR0=0;                //關(guān)閉定時器T0

  212.          i++;                 //播放下一個音符
  213.       }            
  214.   }   
  215. }
  216. //函數(shù)功能定時器T0的中斷服務(wù)子程序使P3.7引腳輸出音頻的方波
  217. void Time0(void ) interrupt 1 using 1   
  218.   {
  219.     sound=!sound;      //將P3.7引腳輸出電平取反形成方波   
  220.     TH0=(8192-C)/32;   //可證明這是13位計數(shù)器TH0高8位的賦初值方法
  221.     TL0=(8192-C)%32;   //可證明這是13位計數(shù)器TL0低5位的賦初值方法 }
  222. }
復(fù)制代碼

可能有轉(zhuǎn)發(fā)時有錯我試驗時除休止符外一切正常。
回復(fù)

使用道具 舉報

ID:213173 發(fā)表于 2021-3-2 16:59 | 顯示全部樓層
所謂休止就是頻率為0,蜂鳴器無輸出,但要保證蜂鳴器是復(fù)位狀態(tài)。可以設(shè)一個休止標(biāo)志,在中斷中計數(shù)判斷休止時長。
//函數(shù)功能定時器T0的中斷服務(wù)子程序使P3.7引腳輸出音頻的方波
void Time0(void ) interrupt 1 using 1   
{
        static unsigned i;
        if(xiuzhi)//xiuzhi標(biāo)志=1
        {
                sound=1;//蜂鳴器初始態(tài)
                TH0=0x??;//??=重裝值
                TL0=0x??;//
                i++;
                if(i>=x)//x=休止時長
                {
                        i=0;
                        xiuzhi=0;//休止結(jié)束
                }
        }
        else
        {
                sound=~sound;      //將P3.7引腳輸出電平取反形成方波   
                TH0=(8192-C)/32;   //可證明這是13位計數(shù)器TH0高8位的賦初值方法
                TL0=(8192-C)%32;   //可證明這是13位計數(shù)器TL0低5位的賦初值方法
        }
}
回復(fù)

使用道具 舉報

ID:886808 發(fā)表于 2021-3-2 17:48 來自手機 | 顯示全部樓層
太謝謝你了,有空把休止符加上,重新檢測一遍!把譜子補全,拍節(jié)找準(zhǔn)。再次感感謝!
回復(fù)

使用道具 舉報

ID:3666 發(fā)表于 2021-3-2 20:30 | 顯示全部樓層
你上面數(shù)組表是怎么算出來的
回復(fù)

使用道具 舉報

ID:886808 發(fā)表于 2021-3-3 10:24 來自手機 | 顯示全部樓層
liushiming82 發(fā)表于 2021-3-2 20:30
你上面數(shù)組表是怎么算出來的

不用計算。宏定義的低音dao到高音xi后邊的數(shù)值就是C調(diào)的實際振動頻率。改變了曲譜的排列順序,就改變了播放順序。實際上用簡譜1234567再加上高低音標(biāo)志就更直觀了。原例用的是拼音或英文標(biāo)注。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表