我的蜂鸣器音乐实例【原创】

2015-02-022.2万
AI 快速预览详细 收起
本文介绍了如何使用子程序实现蜂鸣器音乐播放的方法。通过将频率存放到子程序中,并进行调用,可以实现快速高效的音乐播放。项目名称为“十年”,硬件清单包括Arduino板和蜂鸣器。最终效果是能够快速实现音乐播放功能,并方便调用。难度等级适中,适合初学者和Arduino爱好者。

复制代码

刚开始接触蜂鸣器音乐的时候,都是使用了库文件,或者直接录入频率来演奏,这会有比较大的局限性,效率也低。

刚开始学习数组和子程序功能,将频率存放到子程序中,然后进行调用返回相应音符频率,实现既能快速实现音乐播放功能,又能方便调用。这里以歌曲“十年”简谱为例进行介绍。

我的蜂鸣器音乐实例【原创】图1
以下是程序代码:

  1. <p>/************************************************************
  2. Arduino实例学习14:蜂鸣器全能演奏【子程序版】
  3. 要点:带参子程序的定义,带参子程序的使用方法
  4. 难点:带参子程序的定义,带参子程序的使用方法
  5. 学习者:顾黄凯
  6. 本代码写于2015年01月31日晚
  7. ************************************************************/
  8. //低音前面加 - ,高音前面加1
  9. #define LaBa 8
  10. int Num;  //用于存放数组元素个数
  11. char* YinDiao = "A";  //音调
  12. int PaiChang = 800; //每拍长度
  13. int PuZi[] = {  //根据简谱将音符录入PuZi数组变量
  14.   0, 0, 1, 2,
  15.   3, 3, 2, 3,
  16.   2, 1, -7, -6, 0, -3, -6,
  17.   -5, -6, -7, -6, -5, -6,
  18.   0, 1, -7, -6, -7,
  19.   -6, 0,
  20.   0, -3, 1, -7, -6, -7,
  21.   -6, 0,
  22.   0, 0, 1, 2,
  23.   3, 3, 2, 3,
  24.   2, 3, 5, 1, 0, 3,
  25.   2, 2, 2, 1, -7, 1,
  26.   0, 1, 1, -7, -6, -7,
  27.   1, -6, -6,
  28.   0, -3, 1, -7, -6, -5,
  29.   -6, -7, -6,
  30.   0, 0,
  31.   0, -5, 3, 2, 1,
  32.   2, 3, 2, 2, -5,
  33.   0, 1, -6, -7, 1, 6, 5, 1,
  34.   3, 0, 3, 2, 3,
  35.   4, 0,
  36.   2, 3, 3, 4,
  37.   2, 3,
  38.   0, 1, 2, 5, 3,
  39.   3, 3, 3, 4, 5, 6,
  40.   2, 2, 2, 4, 3, 2,
  41.   1, -3, -3, 2, 1, -7,
  42.   1, -6, -6, 0, 1, -7, -6,
  43.   -7, 4, 3, 2, -7, 1,
  44.   1, 0, 1, 2, 3,
  45.   6, 3, 4, 5, 2, 3,
  46.   3, 2, 1, 2, 5, 3,
  47.   3, 3, 3, 4, 5, 6,
  48.   2, 2, 2, 4, 3, 2,
  49.   1, -3, -3, 2, 1, -7,
  50.   1, -6, -6, 0, 1, -7, -6,
  51.   -7, 4, 3, 2, 3, 2,
  52.   2, 1, 0, 1, 2, 3,
  53.   6, 6, 3, 1, 2,
  54.   2, 1, -7,
  55.   1,
  56.   0, 0, 1, 2,
  57.   3, 3, 2, 3,
  58.   2, 3, 5, 1, 0, 3,
  59.   2, 2, 2, 1, -7,
  60.   1, 1, 1, -7, -6, 1,
  61.   -6,
  62.   0, -5, 3, 2, 1, 2,
  63.   1,
  64.   1
  65. };
  66. float JiePai[] = {  //根据简谱上节拍,将每个音符相应的节拍录入JiePai数组变量,一拍记为1,半拍记为0.5……
  67.   1, 0.5, 0.25, 0.25,
  68.   0.5, 0.5, 0.5, 0.5,
  69.   0.25, 0.25, 0.25, 0.25, 0.5, 0.25, 0.25,
  70.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  71.   1, 0.25, 0.25, 0.25, 0.25,
  72.   1, 1,
  73.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  74.   1, 1,
  75.   1, 0.5, 0.25, 0.25,
  76.   0.5, 0.5, 0.5, 0.5,
  77.   0.25, 0.25, 0.25, 0.25, 0.5 + 0.25, 0.25,
  78.   0.5, 0.5, 0.25, 0.25, 0.25, 0.25,
  79.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  80.   0.5, 0.5, 1,
  81.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  82.   0.5, 0.5, 1,
  83.   1, 1,
  84.   0.5 + 0.25, 0.25, 0.5, 0.25, 0.25,
  85.   0.5, 0.25, 0.25, 0.5, 0.5,
  86.   0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  87.   1, 0.25, 0.25, 0.25, 0.25,
  88.   1, 1,
  89.   0.5 + 0.25, 0.25, 0.5, 0.5,
  90.   0.0625, 0.9375 + 1,
  91.   1, 0.25, 0.25, 0.25, 0.25,
  92.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  93.   0.5, 0.5, 0.25, 0.25, 0.25, 0.25,
  94.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  95.   0.25, 0.25, 0.5, 0.25, 0.25, 0.25, 0.25,
  96.   0.5, 0.25, 0.25, 0.5, 0.25, 0.25,
  97.   1, 0.25, 0.25, 0.25, 0.25,
  98.   0.5 + 0.25,0.25, 0.5, 0.25, 0.03125, 0.1875 + 0.03125,
  99.   0.5, 0.5, 0.25, 0.25, 0.25, 0.25,
  100.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  101.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  102.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  103.   0.25, 0.25, 0.5, 0.25, 0.25, 0.25, 0.25,
  104.   0.5, 0.25, 0.25, 0.5, 0.25, 0.25,
  105.   0.25, 0.5 + 0.25, 0.25, 0.25, 0.25, 0.25,
  106.   0.5 + 0.25, 0.25, 0.5, 0.25, 0.25,
  107.   1 + 0.5, 0.25, 0.25,
  108.   2,
  109.   1, 0.5, 0.25, 0.25,
  110.   0.5, 0.5, 0.5, 0.5,
  111.   0.25, 0.25, 0.25, 0.25, 0.5 + 0.25, 0.25,
  112.   0.5, 0.5, 0.25, 0.25, 0.5,
  113.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  114.   2,
  115.   0.5 + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
  116.   2,
  117.   1
  118. };
  119. //为了解决连音的问题,这里使用一个连音控制数组变量,需要连音的地方使用1,否则使用0
  120. int LianYin[]={
  121.     0,0,0,0,
  122.     0,0,0,0,
  123.     0,0,0,0,0,0,0,
  124.     0,0,0,0,0,0,
  125.     0,0,0,0,0,
  126.     0,0,
  127.     0,0,0,0,0,0,
  128.     0,0,
  129.     0,0,0,0,
  130.     0,0,0,0,
  131.     0,0,0,0,0,0,
  132.     0,0,0,0,0,0,
  133.     0,0,0,0,0,0,
  134.     0,1,0,
  135.     0,0,0,0,0,0,
  136.     0,0,0,
  137.     0,0,
  138.     0,0,0,0,0,
  139.     0,0,1,0,0,
  140.     0,0,0,0,0,0,0,0,
  141.     0,0,0,0,0,
  142.     0,0,
  143.     0,1,0,0,
  144.     1,0,
  145.     0,0,0,1,0,
  146.     0,1,0,0,0,0,
  147.     0,1,0,0,0,0,
  148.     0,1,0,0,0,0,
  149.     1,0,0,0,0,0,0,
  150.     0,0,0,0,0,1,
  151.     0,0,0,0,0,
  152.     0,0,0,0,1,1,
  153.     0,0,0,0,1,0,
  154.     0,1,0,0,0,0,
  155.     0,1,0,0,0,0,
  156.     0,1,0,0,0,0,
  157.     1,0,0,0,0,0,0,
  158.     0,0,0,0,0,1,
  159.     0,0,0,0,0,0,
  160.     0,0,0,0,1,
  161.     0,1,0,
  162.     0,
  163.     0,0,0,0,
  164.     0,0,0,0,
  165.     0,0,0,0,0,0,
  166.     0,0,0,0,0,
  167.     0,0,0,0,0,0,
  168.     0,
  169.     0,0,0,0,0,0,
  170.     1,
  171.     0        
  172. };
  173. void setup(){
  174.   Num = sizeof(PuZi) / sizeof(PuZi[0]); // 通过sizeof函数,将PuZi数组的总长度/PuZi数组第一个元素的长度,获得数组元素个数。
  175.   
  176. }
  177. void loop()
  178. {
  179.    // 通过for循环,将音符数组中的音符逐一取出播放延时为节拍时间。
  180.    for (int i = 0; i < Num; i++) {     
  181.      tone(LaBa, YinFu(YinDiao, PuZi[i]));  //调用子程序YinFu,传递两个参数,YinDiao和音符,返回相应的频率
  182.      delay(PaiChang * JiePai[i] );
  183.      if (LianYin[i] == 0) {
  184.        tone(LaBa, -1);  //连音的地方不用停顿
  185.      };
  186.    }
  187.    tone(LaBa, -1);  // 设置喇叭静音
  188.    delay( 3000 );
  189. }</p><p> </p><p>//定义一个具有返回值的带参子程序,如果你有时间,可以将B大调等进行完善,为了让大家也动动手,这里只留着A大调的相关频率数据。静音为0,-1为低音do,11为高音do
  190. int YinFu(char* _YinDiao, int _FuHao) {
  191.   if (_YinDiao == "A") {
  192.     switch (_FuHao) {
  193.       case 0:
  194.         return -1;
  195.         break;
  196.       case -1:
  197.         return 221;
  198.         break;
  199.       case -2:
  200.         return 248;
  201.         break;
  202.       case -3:
  203.         return 278;
  204.         break;
  205.       case -4:
  206.         return 294;
  207.         break;
  208.       case -5:
  209.         return 330;
  210.         break;
  211.       case -6:
  212.         return 371;
  213.         break;
  214.       case -7:
  215.         return 416;
  216.         break;
  217.       case 1:
  218.         return 441;
  219.         break;
  220.       case 2:
  221.         return 495;
  222.         break;
  223.       case 3:
  224.         return 556;
  225.         break;
  226.       case 4:
  227.         return 589;
  228.         break;
  229.       case 5:
  230.         return 661;
  231.         break;
  232.       case 6:
  233.         return 742;
  234.         break;
  235.       case 7:
  236.         return 833;
  237.         break;
  238.       case 11:
  239.         return 882;
  240.         break;
  241.       case 12:
  242.         return 990;
  243.         break;
  244.       case 13:
  245.         return 1112;
  246.         break;
  247.       case 14:
  248.         return 1178;
  249.         break;
  250.       case 15:
  251.         return 1322;
  252.         break;
  253.       case 16:
  254.         return 1484;
  255.         break;
  256.       case 17:
  257.         return 1665;
  258.         break;
  259.     }
  260.   }
  261. }
复制代码
使用这个方式制作蜂鸣器歌曲播放是不是很方便快捷呀?
当你拥有了完整的音调库,只要改变JianPu、JiePai等变量值,就能很快制作出一首新曲子了,赶快动手试试吧!





创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(8)
温柔的投降
温柔的投降
可以,做的不错
李狗蛋
李狗蛋
复制了代码,显示expected unqualified-id before '<' token,怎么解决呀
celine
celine
很有趣的!演奏的也很好听
qq815076543322
qq815076543322
在你空间看的视频,弄完这首歌,lz辛苦啦
phoebe.wang40
phoebe.wang40
效果杠杠的,赞
heinau
heinau
楼主的蜂鸣器演奏的好棒,音很准呢
hnyzcj
hnyzcj
这个好像挺费事的,LZ辛苦了,赞一个。
hnyzcj
hnyzcj回复auth
哈哈,是的。
auth
auth
作者
回复hnyzcj
当你只做一首音乐的时候的确会很费事,可是如果做第二首、第N首的时候就会很方便了。
hnyzcj
hnyzcj
我以前玩的是葫芦娃,哈哈
- 没有更多了 -