久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3616|回復: 3
收起左側

遙控音樂盒制作日志(一)

  [復制鏈接]
ID:695961 發表于 2022-5-8 11:58 | 顯示全部樓層 |閱讀模式
前幾天帶兒子逛商場,兒子看上一款音樂盒,小小的一個東西要幾十塊錢,感覺很不劃算……于是帶他吃了一頓比薩,很快他就忘了這回事啦(與兒子斗其樂無窮),回來以后,孩子又把這事記起來了,感情還是對音樂盒念念不忘啊,作為一名學習電子設計的小學生,正好借這個機會練練手,給孩子做一款獨一無二的遙控音樂盒。

遙控這個東西實現手段很多,紅外、藍牙、wifi……做這玩意太復雜啦,咱們的主要目的是做音樂盒啊,于是花了8塊從萬能的某寶上買了一款【2262/2272四路無線遙控套件】(還包郵哦)


2262/2272

2262/2272


先用面包板搭一下,可是音樂從哪弄呢?當然從黑壇里搜啊。

記得很早之前在群里看到一位群友寫過一篇【51單片機音樂盒1602顯示 Proteus仿真程序】,地址為:
http://www.zg4o1577.cn/bbs/dpj-183341-1.html

可是……

可是……

可是看到一大段樂譜,我頭直接就大了,這得需要多少單片機空間啊,咱的STC89才4K程序空間,本著寫單片機要節約每一個字節的原則,我對這段樂譜進行了改造!!!壓縮它,弄死它!原樂譜如下:

  1. //《煙花易冷》
  2. unsigned char code song1[]={
  3.      5,2,1, 3,2,1, 2,2,2, 2,2,4, 3,2,1, 1,2,1, 2,2,1, 3,2,4,
  4.          5,2,1, 3,2,1, 2,2,2, 2,2,2, 5,1,1, 3,2,1, 4,2,1, 3,2,4,
  5.          3,2,1, 3,2,1, 7,2,1, 3,2,1, 2,2,2, 1,2,1, 7,1,1, 1,2,1,
  6.          2,2,1, 3,2,1, 6,2,3, 6,1,1, 1,2,1, 3,2,1, 2,2,1, 6,1,1,
  7.          1,2,1, 7,1,1, 5,1,1, 6,1,6, 5,2,1, 3,2,1, 2,2,2, 2,2,1,
  8.          2,2,1, 3,2,1, 1,2,1, 2,2,1, 3,2,4, 5,2,1, 3,2,1, 2,2,2,
  9.          2,2,1, 2,2,1, 5,1,1, 3,2,1, 4,2,1, 3,2,4, 3,2,1, 3,2,1,
  10.          7,2,3, 3,2,1, 2,2,2, 1,2,1, 7,1,1, 1,2,1, 2,2,1, 3,2,1,
  11.          6,2,3, 6,1,1, 1,2,1, 3,2,1, 2,2,1, 6,1,1, 1,2,1, 7,1,2,
  12.          5,1,2, 6,1,6, 0,0,0 };

  13. //《發如雪》
  14. unsigned char code song2[]={
  15.      5,1,1, 2,2,1, 3,2,2, 2,2,1, 3,2,1, 5,2,1, 6,2,1, 5,2,3, 1,2,1, 2,2,1,
  16.          3,2,1, 6,2,1, 5,2,1, 3,2,1, 5,2,3, 5,2,1, 6,2,1, 1,3,2, 6,2,1, 5,2,1,
  17.          3,2,1, 5,2,1, 3,2,2, 1,2,1, 2,2,1, 3,2,1, 1,2,1, 6,1,1, 3,2,1, 2,2,1,
  18.          5,1,1, 2,2,1, 3,2,2, 2,2,1, 3,2,1, 5,2,1, 6,2,1, 5,2,3, 1,2,1, 2,2,1,
  19.          3,2,1, 6,2,1, 5,2,3, 5,2,1, 6,2,1, 1,3,2, 6,2,1,
  20.          5,2,1, 3,2,1, 5,2,1, 3,2,2, 1,2,1, 6,1,1, 3,2,1, 2,2,1, 1,2,1, 6,1,1,
  21.          1,2,1, 2,2,1, 2,2,1, 1,2,4, 0,0,0 };

  22. //《簡單愛》
  23. unsigned char code song3[]={
  24.      5,1,1, 1,2,1, 2,2,1, 3,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1, 5,2,1,
  25.          4,2,1, 3,2,1, 2,2,3, 5,1,1, 1,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1,
  26.          5,2,1, 6,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2, 1,2,1, 6,1,1, 2,2,1, 2,2,1,
  27.          3,2,1, 3,2,1, 1,2,1, 5,2,1, 1,2,1, 5,2,1, 1,2,1, 7,1,1, 1,2,1, 1,2,1, 6,1,1,
  28.          2,2,1, 2,2,1, 3,2,1, 3,2,1, 5,2,1, 5,2,1,
  29.          5,2,1, 6,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2,  
  30.          5,1,1, 1,2,1, 2,1,2, 3,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1, 5,2,1,
  31.          4,2,1, 3,2,1, 2,2,3, 5,1,1, 1,2,1, 2,2,1, 3,2,1, 2,2,1, 3,2,1, 4,2,1,
  32.          5,2,1, 5,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2, 1,2,1, 6,1,1, 2,2,1, 2,2,1,
  33.          3,2,1, 3,2,1, 1,2,2, 5,2,1, 1,2,1, 5,2,1, 5,2,1, 7,1,1, 1,2,1, 0,0,0 };

  34. //《世上只有媽媽好》
  35. unsigned char code song4[]={
  36.      6,2,3, 5,2,1, 3,2,2, 5,2,2, 1,3,2, 6,2,1,
  37.          //6,2,3代表6,中音,3個半拍;
  38.          //5,2,1代表5,中音,1個半拍;
  39.          //3,2,2代表3,中音,2個半拍;
  40.          //5,2,2代表5,中音,2個半拍;
  41.          //1,3,2代表1,高音,2個半拍;
  42.          //...
  43.      5,2,1,6,2,4, 3,2,2, 5,2,1, 6,2,1, 5,2,2, 3,2,2, 1,2,1,6,1,1, 5,2,1,
  44.          3,2,1, 2,2,4, 2,2,3, 3,2,1, 5,2,2, 5,2,1, 6,2,1, 3,2,2, 2,2,2,
  45.          1,2,4, 5,2,3, 3,2,1,2,2,1, 1,2,1, 6,1,1, 1,2,1, 5,1,6, 0,0,0};

  46. //《當你孤單你會想起誰》
  47. unsigned char code song5[]={
  48.      3,2,2, 3,2,1, 4,2,1, 3,2,2, 2,2,1, 1,2,1,  2,2,2, 5,2,2, 2,2,2, 2,2,3,
  49.          1,2,2, 1,2,1, 2,2,1, 1,2,2, 7,1,1, 6,1,1, 7,1,2, 3,2,2, 7,1,2, 7,1,3,
  50.          6,1,2, 2,2,1, 3,2,1, 2,2,1, 1,2,1, 6,1,2, 5,1,2, 2,2,1, 3,2,1, 2,2,1,
  51.          1,2,1, 6,1,2, 6,1,2, 2,2,1, 3,2,1, 2,2,1, 1,2,1, 6,1,1, 7,1,1, 1,2,6, 0,0,0 };

  52. //《鄉間小路》
  53. unsigned char code song6[]={
  54.      3,1,2, 3,1,1, 3,1,1, 6,0,1, 6,0,1, 1,1,2,
  55.      6,0,1, 5,0,1, 6,0,4, 6,0,2, 6,0,1 ,6,0,1, 6,0,2, 6,0,1, 1,1,1,
  56.      2,1,2, 2,1,1, 3,1,1, 2,1,4, 3,1,1, 3,1,1, 3,1,1, 2,1,1, 4,1,2,
  57.      4,1,2, 3,1,2, 2,1,1, 1,1,1, 2,1,4, 7,0,1, 7,0,1, 7,0,1, 6,0,1,
  58.      5,0,1, 5,0,1, 6,0,1, 7,0,1, 7,0,1, 6,0,1, 5,0,1, 6,0,4, 6,1,2,
  59.      3,1,1, 6,1,1, 7,1,1, 6,1,1, 5,1,1, 5,1,2, 5,1,1, 2,1,1, 5,1,1,
  60.      6,1,1, 5,1,1, 4,1,1, 4,1,2, 4,1,1, 3,1,1, 2,1,2, 1,1,1, 2,1,1,
  61.      3,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,4, 6,1,2, 3,1,1, 6,1,1, 7,1,1,
  62.          6,1,1, 5,1,1, 5,1,2, 2,1,1, 5,1,1, 6,1,1, 5,1,1, 4,1,1, 0,0,0};     

  63. //《送別》
  64. unsigned char code song7[]={
  65.      5,1,2, 3,1,3, 5,1,1, 1,2,3, 6,1,2, 1,2,2,
  66.      5,1,4, 5,1,2, 1,1,1, 2,1,1, 3,1,2, 2,1,1, 1,1,1, 2,1,4, 5,1,2,
  67.          3,1,1, 5,1,1, 1,2,2, 7,1,1, 6,1,2, 1,2,2, 5,1,4, 5,1,2, 2,1,1,
  68.          3,1,1, 4,1,2, 7,0,1, 1,1,4, 6,1,2, 1,2,2, 1,2,4, 7,1,2, 6,1,1,
  69.          7,1,1, 1,2,4, 6,1,1, 7,1,1, 1,2,1, 6,1,1, 6,1,1, 5,1,1, 3,1,1,
  70.          1,1,1, 2,1,8, 5,1,2, 3,1,1, 5,1,1, 1,2,2, 7,1,1, 6,1,2, 1,2,2,
  71.          5,1,4, 5,1,2, 2,1,1, 3,1,1, 4,1,2, 7,0,2, 1,1,4, 0,0,0};

  72. //《最浪漫的事》
  73. unsigned char code song8[]={
  74.      5,1,1, 6,1,1, 1,2,1, 6,1,2, 6,1,1, 5,1,1, 6,1,1, 5,1,1, 3,1,1, 5,1,5,
  75.          5,1,1, 6,1,1, 1,2,1, 6,1,2, 6,1,1, 5,1,1, 6,1,1, 5,1,1, 6,1,1, 1,1,5,
  76.          1,1,1, 2,1,1, 3,1,1, 2,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 1,1,1, 6,1,1,
  77.          3,1,2, 2,1,3, 5,1,1, 6,1,1, 1,2,1, 6,1,2, 6,1,1, 5,1,1, 6,1,1, 5,1,1,
  78.          6,1,1, 1,1,5, 1,1,1, 2,1,1, 3,1,1, 4,1,2, 4,1,1, 5,1,1, 6,1,1, 6,1,1,
  79.          5,1,1, 6,1,2, 1,2,1, 6,1,3, 1,2,1, 6,1,1, 5,1,1, 5,1,4, 1,1,1, 6,1,1,
  80.          5,1,5, 5,1,1, 6,1,1, 1,2,1, 3,1,1, 2,1,1, 3,1,1, 1,1,6, 0,0,0};
復制代碼
仔細觀查發現:



第一個數字音符的范圍是:1到,代表哆來咪發...
第二個數字范圍是:0123之一,代表低音\中音\高音\超高音(第幾個八度)
第三個數字范圍是:嗯……又仔細看了一下,最大的值為6,于是寫了一段note.js程序,把每首樂譜進行了壓縮(順手10字節對齊一下),把三個字節壓縮為1個字節,直接把樂譜的空間節約了三分之二……

壓縮后的樂譜代碼如下:


  1. //////////////////////////////////////////////
  2. //7-5:對應的音符1234567之一(第幾個音),代表哆來咪發...
  3. //4-3:0:低音, 1:中音, 2:高音, 3:超高音(第幾個八度)
  4. //2-0:時間長度+1, 以半拍為單位, 樂曲數據表的結尾是0
  5. //////////////////////////////////////////////
  6. //《煙花易冷》
  7. BYTE code song0[]={
  8.      0xb0, 0x70, 0x51, 0x53, 0x70, 0x30, 0x50, 0x73, 0xb0, 0x70,
  9.      0x51, 0x51, 0xa8, 0x70, 0x90, 0x73, 0x70, 0x70, 0xf0, 0x70,
  10.      0x51, 0x30, 0xe8, 0x30, 0x50, 0x70, 0xd2, 0xc8, 0x30, 0x70,
  11.      0x50, 0xc8, 0x30, 0xe8, 0xa8, 0xcd, 0xb0, 0x70, 0x51, 0x50,
  12.      0x50, 0x70, 0x30, 0x50, 0x73, 0xb0, 0x70, 0x51, 0x50, 0x50,
  13.      0xa8, 0x70, 0x90, 0x73, 0x70, 0x70, 0xf2, 0x70, 0x51, 0x30,
  14.      0xe8, 0x30, 0x50, 0x70, 0xd2, 0xc8, 0x30, 0x70, 0x50, 0xc8,
  15.      0x30, 0xe9, 0xa9, 0xcd, 0x00 };

  16. //《發如雪》
  17. BYTE code song1[]={
  18.      0xa8, 0x50, 0x71, 0x50, 0x70, 0xb0, 0xd0, 0xb2, 0x30, 0x50,
  19.      0x70, 0xd0, 0xb0, 0x70, 0xb2, 0xb0, 0xd0, 0x39, 0xd0, 0xb0,
  20.      0x70, 0xb0, 0x71, 0x30, 0x50, 0x70, 0x30, 0xc8, 0x70, 0x50,
  21.      0xa8, 0x50, 0x71, 0x50, 0x70, 0xb0, 0xd0, 0xb2, 0x30, 0x50,
  22.      0x70, 0xd0, 0xb2, 0xb0, 0xd0, 0x39, 0xd0, 0xb0, 0x70, 0xb0,
  23.      0x71, 0x30, 0xc8, 0x70, 0x50, 0x30, 0xc8, 0x30, 0x50, 0x50,
  24.      0x33, 0x00 };

  25. //《簡單愛》
  26. BYTE code song2[]={
  27.      0xa8, 0x30, 0x50, 0x70, 0x50, 0x70, 0x90, 0xb0, 0xb0, 0xb0,
  28.      0x90, 0x70, 0x52, 0xa8, 0x30, 0x50, 0x70, 0x90, 0xb0, 0xb0,
  29.      0xb0, 0xd0, 0xb1, 0x50, 0x70, 0x31, 0x30, 0xc8, 0x50, 0x50,
  30.      0x70, 0x70, 0x30, 0xb0, 0x30, 0xb0, 0x30, 0xe8, 0x30, 0x30,
  31.      0xc8, 0x50, 0x50, 0x70, 0x70, 0xb0, 0xb0, 0xb0, 0xd0, 0xb1,
  32.      0x50, 0x70, 0x31, 0xa8, 0x30, 0x49, 0x70, 0x50, 0x70, 0x90,
  33.      0xb0, 0xb0, 0xb0, 0x90, 0x70, 0x52, 0xa8, 0x30, 0x50, 0x70,
  34.      0x50, 0x70, 0x90, 0xb0, 0xb0, 0xb1, 0x50, 0x70, 0x31, 0x30,
  35.      0xc8, 0x50, 0x50, 0x70, 0x70, 0x31, 0xb0, 0x30, 0xb0, 0xb0,
  36.      0xe8, 0x30, 0x00 };

  37. //《世上只有媽媽好》
  38. BYTE code song3[]={
  39.      0xd2, 0xb0, 0x71, 0xb1, 0x39, 0xd0, 0xb0, 0xd3, 0x71, 0xb0,
  40.      0xd0, 0xb1, 0x71, 0x30, 0xc8, 0xb0, 0x70, 0x53, 0x52, 0x70,
  41.      0xb1, 0xb0, 0xd0, 0x71, 0x51, 0x33, 0xb2, 0x70, 0x50, 0x30,
  42.      0xc8, 0x30, 0xad, 0x00};

  43. //《當你孤單你會想起誰》
  44. BYTE code song4[]={
  45.      0x71, 0x70, 0x90, 0x71, 0x50, 0x30, 0x51, 0xb1, 0x51, 0x52,
  46.      0x31, 0x30, 0x50, 0x31, 0xe8, 0xc8, 0xe9, 0x71, 0xe9, 0xea,
  47.      0xc9, 0x50, 0x70, 0x50, 0x30, 0xc9, 0xa9, 0x50, 0x70, 0x50,
  48.      0x30, 0xc9, 0xc9, 0x50, 0x70, 0x50, 0x30, 0xc8, 0xe8, 0x35,
  49.      0x00 };
  50.         
  51. //《鄉間小路》
  52. BYTE code song5[]={
  53.      0x69, 0x68, 0x68, 0xc0, 0xc0, 0x29, 0xc0, 0xa0, 0xc3, 0xc1,
  54.      0xc0, 0xc0, 0xc1, 0xc0, 0x28, 0x49, 0x48, 0x68, 0x4b, 0x68,
  55.      0x68, 0x68, 0x48, 0x89, 0x89, 0x69, 0x48, 0x28, 0x4b, 0xe0,
  56.      0xe0, 0xe0, 0xc0, 0xa0, 0xa0, 0xc0, 0xe0, 0xe0, 0xc0, 0xa0,
  57.      0xc3, 0xc9, 0x68, 0xc8, 0xe8, 0xc8, 0xa8, 0xa9, 0xa8, 0x48,
  58.      0xa8, 0xc8, 0xa8, 0x88, 0x89, 0x88, 0x68, 0x49, 0x28, 0x48,
  59.      0x68, 0x48, 0x28, 0x48, 0x6b, 0xc9, 0x68, 0xc8, 0xe8, 0xc8,
  60.      0xa8, 0xa9, 0x48, 0xa8, 0xc8, 0xa8, 0x88, 0x00};

  61. //《送別》
  62. BYTE code song6[]={
  63.      0xa9, 0x6a, 0xa8, 0x32, 0xc9, 0x31, 0xab, 0xa9, 0x28, 0x48,
  64.      0x69, 0x48, 0x28, 0x4b, 0xa9, 0x68, 0xa8, 0x31, 0xe8, 0xc9,
  65.      0x31, 0xab, 0xa9, 0x48, 0x68, 0x89, 0xe0, 0x2b, 0xc9, 0x31,
  66.      0x33, 0xe9, 0xc8, 0xe8, 0x33, 0xc8, 0xe8, 0x30, 0xc8, 0xc8,
  67.      0xa8, 0x68, 0x28, 0x4e, 0xa9, 0x68, 0xa8, 0x31, 0xe8, 0xc9,
  68.      0x31, 0xab, 0xa9, 0x48, 0x68, 0x89, 0xe1, 0x2b, 0x00};

  69. //《最浪漫的事》
  70. BYTE code song7[]={
  71.      0xa8, 0xc8, 0x30, 0xc9, 0xc8, 0xa8, 0xc8, 0xa8, 0x68, 0xac,
  72.      0xa8, 0xc8, 0x30, 0xc9, 0xc8, 0xa8, 0xc8, 0xa8, 0xc8, 0x2c,
  73.      0x28, 0x48, 0x68, 0x48, 0x48, 0x48, 0x28, 0x48, 0x28, 0xc8,
  74.      0x69, 0x4a, 0xa8, 0xc8, 0x30, 0xc9, 0xc8, 0xa8, 0xc8, 0xa8,
  75.      0xc8, 0x2c, 0x28, 0x48, 0x68, 0x89, 0x88, 0xa8, 0xc8, 0xc8,
  76.      0xa8, 0xc9, 0x30, 0xca, 0x30, 0xc8, 0xa8, 0xab, 0x28, 0xc8,
  77.      0xac, 0xa8, 0xc8, 0x30, 0x68, 0x48, 0x68, 0x2d, 0x00};
復制代碼

note.js壓縮代碼標例:


  1. let tt = [5,1,1, 6,1,1, 1,2,1, 6,1,2, 6,1,1, 5,1,1, 6,1,1, 5,1,1, 3,1,1, 5,1,5,
  2.          5,1,1, 6,1,1, 1,2,1, 6,1,2, 6,1,1, 5,1,1, 6,1,1, 5,1,1, 6,1,1, 1,1,5,
  3.          1,1,1, 2,1,1, 3,1,1, 2,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 1,1,1, 6,1,1,
  4.          3,1,2, 2,1,3, 5,1,1, 6,1,1, 1,2,1, 6,1,2, 6,1,1, 5,1,1, 6,1,1, 5,1,1,
  5.          6,1,1, 1,1,5, 1,1,1, 2,1,1, 3,1,1, 4,1,2, 4,1,1, 5,1,1, 6,1,1, 6,1,1,
  6.          5,1,1, 6,1,2, 1,2,1, 6,1,3, 1,2,1, 6,1,1, 5,1,1, 5,1,4, 1,1,1, 6,1,1,
  7.          5,1,5, 5,1,1, 6,1,1, 1,2,1, 3,1,1, 2,1,1, 3,1,1, 1,1,6, 0,0,0];

  8. let count = 0;
  9. let offset = 0;
  10. let str = ''
  11. while(tt[offset] != 0) {
  12.         let tmp = 0;
  13.         tmp += tt[offset] << 5;
  14.         tmp += tt[offset + 1] << 3;
  15.         if(tt[offset + 2] >= 8)
  16.                 tt[offset + 2] = 7;

  17.         tmp += tt[offset + 2] - 1;
  18.         //str += '0x' + tt[offset] + tt[offset + 1] + ',' + tt[offset + 2] + ', ';
  19.         str += '0x' + tmp.toString(16) + ', ';
  20.         offset += 3;
  21.         //console.log('     ' + str);

  22.         if(++count >= 10) {
  23.                 console.log('     ' + str);
  24.                 count = 0;
  25.                 str = '';
  26.         }
  27. }

  28. console.log('     ' + str + '0x00');
復制代碼

使用單片機的T2(16位自動重裝定時器)驅動發生,因為人的聽力是非常敏感的,程序執行過程中把T2設置為最高優先級!

另外,原文的控制部分看的我也是一臉的蒙B。。。原文代碼如下:

  1. ////////////////////////////////////////////////////////////////////////////////////
  2. void music_play(void)//播放相應歌曲的某個音符
  3. {
  4.         if(((music_num==1)&&(play_enable==1))&&(power_enable==1))
  5.         {
  6.                 LCDDispNum(5,2,music_num);
  7.                 fre=song1[num]+7*song1[num+1]-1;//第i個是音符,第i+1個是第幾個八度
  8.                 timer0h=FREQH[fre];                    //從數據表中讀出頻率數值,實際上是定時的時間長度
  9.             timer0l=FREQL[fre];
  10.             time=song1[num+2];              //讀出時間長度數值
  11.             num+=3;
  12.                 if(fre<0)                //判斷歌曲的結束位,結束后轉到下一首
  13.                 {
  14.                         num=0;            //下一首從頭播放
  15.                         miao=0;
  16.                         music_num=2;
  17.             }
  18.                 song();                //發出一個音符
  19.         }
  20. ////////////////////////////////////////////////////////////////////////////////////
  21.         if(((music_num==2)&&(play_enable==1))&&(power_enable==1))
  22.         {  
  23.                 LCDDispNum(5,2,music_num);
  24.                 fre=song2[num]+7*song2[num+1]-1;
  25.                 timer0h=FREQH[fre];
  26.             timer0l=FREQL[fre];
  27.             time=song2[num+2];
  28.             num+=3;
  29.                 if(fre<0)
  30.                 {
  31.                         num=0;
  32.                         miao=0;
  33.                         music_num=3;
  34.             }
  35.                 song();               
  36.         }
  37. ////////////////////////////////////////////////////////////////////////////////////
  38.                 if(((music_num==3)&&(play_enable==1))&&(power_enable==1))
  39.         {  
  40.                 LCDDispNum(5,2,music_num);
  41.                 fre=song3[num]+7*song3[num+1]-1;
  42.                 timer0h=FREQH[fre];
  43.             timer0l=FREQL[fre];
  44.             time=song3[num+2];
  45.             num+=3;
  46.                 if(fre<0)
  47.                 {
  48.                         num=0;
  49.                         miao=0;
  50.                         music_num=4;
  51.             }
  52.                 song();               
  53.         }
  54. ////////////////////////////////////////////////////////////////////////////////////
  55.         if(((music_num==4)&&(play_enable==1))&&(power_enable==1))
  56.         {
  57.                 LCDDispNum(5,2,music_num);
  58.                 fre=song4[num]+7*song4[num+1]-1;
  59.                 timer0h=FREQH[fre];
  60.             timer0l=FREQL[fre];
  61.             time=song4[num+2];
  62.             num+=3;
  63.                 if(fre<0)
  64.                 {
  65.                         num=0;
  66.                         miao=0;
  67.                         music_num=5;
  68.             }
  69.                 song();               
  70.         }
  71. ////////////////////////////////////////////////////////////////////////////////////
  72.         if(((music_num==5)&&(play_enable==1))&&(power_enable==1))
  73.         {
  74.                 LCDDispNum(5,2,music_num);
  75.                 fre=song5[num]+7*song5[num+1]-1;
  76.                 timer0h=FREQH[fre];
  77.             timer0l=FREQL[fre];
  78.             time=song5[num+2];
  79.             num+=3;
  80.                 if(fre<0)
  81.                 {
  82.                         num=0;
  83.                         miao=0;
  84.                         music_num=1;
  85.             }
  86.                 song();               
  87.         }

  88. ////////////////////////////////////////////////////////////////////////////////////
  89. }
復制代碼

額,好吧,再改!把每首樂譜的內存地址記錄下來


  1. // 記錄每個曲子的地址
  2. uint16 code songAddr[] = {song0, song1, song2, song3, song4, song5, song6, song7};
復制代碼

這樣就可以使用序號代表樂曲了。修改后的播放與控制部分如下(播放時間和按鈕防抖使用和個軟件定時器來控制,防止程序進入空轉等待,影響音樂的播放):



  1. /**
  2. * 初始化音樂
  3. */
  4. void MusicInit()
  5. {
  6.         SPEAK = 1;                // 設定為高電位
  7.         
  8.         // 初始化T2
  9.         PT2 = 1;                // 將中斷2設置為最高優先級
  10.         //PT2H = 1;
  11.         
  12.         T2MOD = 0;                // 初始化模式寄存器
  13.         T2CON = 0;                // 初始化控制寄存器
  14.         ET2 = 1;                // 開啟中斷
  15.         
  16.         // 播放第1個音符
  17.         //PlayNote();
  18.         PlayMusic(5);
  19. }

  20. /**
  21. * 播放音樂
  22. * index 音樂序號
  23. */
  24. void PlayMusic(uint8 index)
  25. {
  26.         TR2 = 0;                                        // 停止定時器2
  27.         timers[0].enabled = FALSE;        // 停止音符演奏
  28.         currMusic = index;                        // 要播放的音樂序號
  29.         musicOffset = 0;                        // 音樂偏移量為0
  30.         PlayNote();                                        // 開始播放第1個音符
  31. }

  32. /**
  33. * 上一首
  34. */
  35. void PreviousMusic()
  36. {
  37.         currMusic--;
  38.         if(currMusic <= 1)
  39.                 currMusic = 7;
  40.         
  41.         PlayMusic(currMusic);
  42. }

  43. /**
  44. * 下一首
  45. */
  46. void NextMusic()
  47. {
  48.         currMusic++;
  49.         if(currMusic >= 8)
  50.                 currMusic = 0;
  51.         
  52.         PlayMusic(currMusic);
  53. }

  54. /**
  55. * 播放音符
  56. */
  57. void PlayNote()
  58. {
  59.         BYTE fre;        // 音樂頻率
  60.         
  61.         BYTE code *musicAddr = (BYTE*)songAddr[currMusic];
  62.         BYTE tmp = *(musicAddr + musicOffset);
  63.         
  64.         // 判斷是否播放完畢
  65.         if(tmp == 0)
  66.         {
  67.                 SPEAK = 1;
  68.                 //CLOSE_GREEN_LED();                        // 關閉LED
  69.                 timers[0].enabled = FALSE;
  70.                 return;
  71.         }
  72.         
  73.         fre = ((tmp & 0xF0) >> 5) + ((tmp & 0x18) >> 3) * 7 - 1;
  74.         TL2 = FrL[fre];                        // 設置定時初值
  75.         TH2 = FrH[fre];                        // 設置定時初值
  76.         RCAP2L = FrL[fre];                // 設置定時重載值
  77.         RCAP2H = FrH[fre];                // 設置定時重載值

  78.         timers[0].count = ((tmp & 7) + 1) * 60;                // 300ms做為一拍
  79.         
  80.         if(!timers[0].enabled)
  81.         {
  82.                 timers[0].enabled = TRUE;
  83.                 timers[0].value = 0;
  84.         }
  85.         
  86.         // 開啟定時器
  87.         TR2 = 1;
  88.         
  89.         //SWAP_GREEN_LED();        // 切換綠燈
  90. }

  91. /**
  92. * 音樂軟中斷處理程序
  93. */
  94. void MusicHandle()
  95. {
  96.         TR2 = 0;                        // 停止定時器2
  97.         musicOffset++;
  98.         PlayNote();                        // 播放音符
  99. }

  100. // T2硬件中斷處理程序
  101. void tm2_isr() interrupt 5
  102. {
  103.         TF2 = 0;                        // 清除中斷標志(T2定時器不會自動清除中斷)
  104.         SPEAK = !SPEAK;
  105. }
復制代碼

由于遙控板輸出的是高電平,所以使用了一個4069(69?這個好,我喜歡!!!)將高電平轉為低電平(先前使用NPN三極管搭了一個非門,考慮到搖控器上有四個按鈕,所以換成了4069,某寶國產的4毛錢一片,進口的1塊左右,包郵)

至此音樂部分改造完成,效果如下:


2.jpg



東西雖然簡單,但是改造樂譜部分還是讓我收獲很大。整體程序編譯下來,從2000多字節一下子降到893個字節,特別有成就感。


  1. Program Size: data=53.0 xdata=0 const=583 code=839
  2. creating hex file from ".\Objects\test"...
  3. ".\Objects\test" - 0 Error(s), 0 Warning(s).
  4. Build Time Elapsed:  00:00:01
復制代碼


后面準備增加一個12232,用于顯示播放時間,第幾首樂曲,時間,溫度、濕度、節日提醒功能。


感謝51黑論壇,感謝群友提供的樂譜以及設計靈感。


單片機代碼等做完后統一發,嗯,先哄兒子玩會,哈哈……
51hei.png
視頻: 視頻.7z (2.77 MB, 下載次數: 6)

評分

參與人數 1黑幣 +60 收起 理由
admin + 60 很給力!

查看全部評分

回復

使用道具 舉報

ID:230742 發表于 2022-5-8 23:15 | 顯示全部樓層
高手!支持一下。
回復

使用道具 舉報

ID:1034262 發表于 2023-4-30 11:52 | 顯示全部樓層
我做過一個電子八音盒,12通道,給孩子玩非常不錯。
回復

使用道具 舉報

ID:1070015 發表于 2023-6-14 21:33 | 顯示全部樓層
代碼可以發下嘛
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美 日韩 国产 成人 在线 | 综合色久| 91pao对白在线播放 | 午夜a区 | 亚洲激情综合 | 欧美日韩免费一区二区三区 | 丁香六月伊人 | 午夜电影在线播放 | 黄色网页在线观看 | 黄色片在线免费看 | 精品综合久久久 | 日韩成人在线电影 | 欧美黑人狂野猛交老妇 | 日韩成人免费av | 国产目拍亚洲精品99久久精品 | 二区三区视频 | 能免费看的av | www.亚洲.com| 久久aⅴ乱码一区二区三区 亚洲国产成人精品久久久国产成人一区 | 久久99精品视频 | 99视频在线免费观看 | 殴美一级片 | 色姑娘综合网 | 日韩电影一区 | 亚洲精品久久久久中文字幕欢迎你 | 亚洲网在线 | 国产日本精品视频 | 精品在线观看入口 | 99这里只有精品视频 | 亚洲精品播放 | 亚洲三级国产 | 亚洲在线中文字幕 | 91精品国产综合久久久久 | 麻豆久久久9性大片 | 亚洲精品免费观看 | 91在线看网站 | 欧美一区二区三区在线 | 国产视频线观看永久免费 | 久久99精品国产 | 久久久久久一区 | 91在线精品视频 |