[MM32软件] 【MM33 eMiniBoard测评报告】+播放背景音乐的尝试

[复制链接]
 楼主| hu9jj 发表于 2020-6-8 15:47 | 显示全部楼层 |阅读模式
本帖最后由 hu9jj 于 2020-6-11 13:30 编辑

    评测告一段落之后,我又开始了播放背景音乐的尝试,传统做法是通过改变延时来翻转引脚达到改变频率的目的,通常是在播放音乐时,单片机就不能做其他的事情。我则设想通过两个定时器来完成,一个毫秒定时器来控制节拍,一个微秒定时器来控制引脚的翻转。这样在主循环中只要在节拍结束时取下一个音符的频率和节拍数据,控制引脚翻转就交给定时器中断完成,如此便可以达到播放背景音乐的目的。
    测试程序用song变量表示当前音乐数组的下标序号,当song=0时停止播放,用cycle,space两个变量分别表示当前的音阶(频率)和节拍,然后用cycle_n,space_n两个变量供定时器计数,在主循环中判断,若space_n>space,则表示当前节拍完成了,取下一个音阶和节拍数据。在微秒定时器中断中一方面给cycle_n加1,另一方面判断cycle_n是否大于cycle,如果大于,则翻转引脚并清零cycle_n继续计数。在音乐数据二维数组中,下标0的数据不会被使用,数组最后必须添加两个0表示结束,以便在循环中结束播放。
    毫秒定时器就利用了delay.c里面的systic中断,只负责space_n加1,代码如下:
  1. static void TimingDelayDecrement(void)
  2. {
  3.     if (TimingDelay != 0x00) {
  4.         TimingDelay--;
  5.     }
  6.         ms++;
  7.         space_n++;        //音乐节拍计时
  8. }

    微秒定时器是启用了tim2,在定时器中断里,我开始用引脚置位后再复位的办法,也许是时间太短,喇叭无反映,尝试加__NOP()延时也不起作用,而且延时太多会引起单片机假死,只有使用引脚翻转命令才有效,但输出的频率太低,效果很差。尝试缩短定时器延时时间,受主频影响无法继续缩短,最后只好采取降低音符频率数值的办法才达到目的。下面是定时器2的配置代码:
Tim2_UPCount_test(2,47);         //控制扬声器

    在定时器2的中断处理中代码如下:
  1. void TIM2_IRQHandler(void)
  2. {

  3.     TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

  4. //    ucTim2Flag++;
  5.     if(space > 0){
  6.                 cycle_n++;
  7.                 if(cycle_n > cycle){
  8.                         SBK_TOGGLE();          //翻转引脚
  9.                         cycle_n = 0;           //重新计数
  10.                 }
  11.         }
  12. }

    在主循环中的代码如下:
  1.         //轮询按键状态
  2.                 keys[0] = GPIO_ReadInputDataBit(SW1_GPIO_Port,SW1_Pin);
  3.                 keys[1] = GPIO_ReadInputDataBit(SW2_GPIO_Port,SW2_Pin);
  4.                 keys[2] = GPIO_ReadInputDataBit(SW3_GPIO_Port,SW3_Pin);
  5.                 keys[3] = GPIO_ReadInputDataBit(SW4_GPIO_Port,SW4_Pin);
  6.                
  7.                 if(0 == keys[3]){
  8.                         LED4_ON();
  9.                         song = 1;           //启动音乐
  10.                         LED3_ON();
  11.                         space = 1;
  12.                 }
  13.                 else
  14.                         LED4_OFF();
  15.                
  16.                 if(0 == keys[2]){       //中断播放
  17.                         song = 0;
  18.                         cycle = 0;
  19.                     LED3_OFF();
  20.                 }
  21.                
  22.                 if(song > 0){           //音乐播放控制
  23.                         if((space > 0) & (space_n > space)){
  24.                                 LED4_ON();
  25.                 cycle = SONG1[song][0]>>4;//取当前的音阶cycle及节拍space
  26.                                 space = SONG1[song][1]<<1;
  27.                                 cycle_n = 0;    //音符及节拍计数清零
  28.                                 space_n = 0;

  29.                 LCD_write_value(25,3,4,0,0,cycle);
  30.                 LCD_write_value(25,4,4,0,0,space);

  31.                             song++;         //准备取下一音符
  32.                 LCD_write_value(60,3,3,0,0,song);

  33.                                 if(space == 0){
  34.                                         song = 0;   //取得末尾的0时结束播放
  35.                                     LED3_OFF();
  36.                                 }
  37.                                 LED4_OFF();
  38.                         }
  39.                 }

    经过三天时间的反复测试,程序基本上达到了预期,只是休止符的节拍延时不正确,尚未找到原因。


    下面是【城南旧事】主题歌【送别】的音乐数据:
  1. uint16_t SONG1[][2] =   //数据表,音阶(微秒)、节拍(毫秒)
  2. {
  3.         0,0,
  4.         
  5.         1276,250,    //5   
  6.         1517,125,    //3
  7.         1276,125,    //5
  8.         956, 500,    //1^
  9.         1137,250,    //6
  10.         956, 125,    //1^
  11.         1137,125,    //6
  12.         1276,500,    //5
  13.         
  14.         1276,250,    //5
  15.         1912,125,    //1
  16.         1703,125,    //2
  17.         1517,250,    //3
  18.         1703,125,    //2
  19.         1912,125,    //1
  20.         1703,750,    //2
  21.         0,50,       //0
  22.         
  23.         1276,250,    //5
  24.         1517,125,    //3
  25.         1276,125,    //5
  26.         956, 375,    //1^
  27.         1013,125,    //7
  28.         1137,250,    //6
  29.         956, 250,    //1^
  30.         1276,500,    //5
  31.         
  32.         1276,250,    //5
  33.         1703,125,    //2
  34.         1517,125,    //3
  35.         1432,375,    //4
  36.         2026,125,    //7_
  37.         1912,750,    //1
  38.     0,50,       //0

  39.         1137,250,    //6
  40.         956, 250,    //1^
  41.         956,500,    //1^
  42.         1013,250,    //7
  43.         1137,125,    //6
  44.         1013,125,    //7
  45.         956,500,    //1^
  46.         
  47.         1137,125,    //6
  48.         1013,125,    //7
  49.         956, 125,    //1^
  50.         1137,125,    //6
  51.         1137,125,    //6
  52.         1276,125,    //5
  53.         1517,125,    //3
  54.         1912,125,    //1
  55.         1703,750,    //2
  56.         0,50,       //0
  57.         
  58.         1276,250,    //5
  59.         1517,125,    //3
  60.         1276,125,    //5
  61.         956,375,     //1^
  62.         1013,125,    //7
  63.         1137,250,    //6
  64.         956, 250,    //1^
  65.         1276,500,    //5
  66.         
  67.         1276,250,    //5
  68.         1703,125,    //2
  69.         1517,125,    //3
  70.         1432,375,    //4
  71.         2026,125,    //7_
  72.         1912,1000,   //1
  73.         
  74.         0,0,
  75.         0,0,
  76.         
  77. };




 楼主| hu9jj 发表于 2020-6-8 16:00 | 显示全部楼层
    下面是本次测试项目的压缩文件包,我已经将其中的I2C读取DS1307日历模块的代码注释了,对LCD5110操作的代码不会影响到程序运行,所以此压缩包下载解压后便可运行。
test33.rar (4.99 MB, 下载次数: 24)



 楼主| hu9jj 发表于 2020-6-8 16:12 | 显示全部楼层
本帖最后由 hu9jj 于 2020-6-8 16:16 编辑

    程序运行时,按K4键启动播放,播放时绿色LED会亮起,直到播放结束或中断停止,每次取音符和节拍数据时红色LED会闪亮一下,在播放过程中可以按K3键提前结束播放。
    修改下面的移位值可以改变音调高低:
     cycle = SONG1[song][0]>>3;//取当前的音阶cycle及节拍space

    修改下面的移位值可以改变音乐节拍(速度):

    space = SONG1[song][1]<<1;

 楼主| hu9jj 发表于 2020-6-9 10:01 | 显示全部楼层
找到休止符延时不正确的原因了,原来是在定时器中断中判断的变量错用成space了,改为cycle就行。程序完美完成。
huangzushuimd 发表于 2020-6-9 11:08 | 显示全部楼层
试用了一下, 非常棒!
 楼主| hu9jj 发表于 2020-6-9 14:27 | 显示全部楼层
huangzushuimd 发表于 2020-6-9 11:08
试用了一下, 非常棒!

声音单调了些,还可以手动改变不同音部(右移不同位数)测试。
zeshoufx 发表于 2020-7-1 08:38 | 显示全部楼层
谢谢分享【播放背景音乐的尝试】测试,,,,
usysm 发表于 2020-7-9 07:56 | 显示全部楼层
播放背景音乐牛啊
typeof 发表于 2020-7-9 07:56 | 显示全部楼层
定时器开发的吗   
typeof 发表于 2020-7-9 07:57 | 显示全部楼层
这个给力呢。   
yujielun 发表于 2020-7-9 07:58 | 显示全部楼层
这个调是怎么确定的   
htmlme 发表于 2020-7-9 07:58 | 显示全部楼层
            
pklong 发表于 2020-7-9 07:58 | 显示全部楼层
不知道效果怎么样   
touser 发表于 2020-7-9 07:58 | 显示全部楼层
hu9jj 发表于 2020-6-8 16:00
下面是本次测试项目的压缩文件包,我已经将其中的I2C读取DS1307日历模块的代码注释了,对LCD5110操作的 ...

         
myiclife 发表于 2020-7-9 07:59 | 显示全部楼层
hu9jj 发表于 2020-6-8 16:12
程序运行时,按K4键启动播放,播放时绿色LED会亮起,直到播放结束或中断停止,每次取音符和节拍数据时 ...

这个节拍是怎么确定的   
uytyu 发表于 2020-7-9 07:59 | 显示全部楼层
都么有看懂其中的原理呢   
jkl21 发表于 2020-7-9 08:00 | 显示全部楼层
播放背景音乐是所有的音乐吗  
iyoum 发表于 2020-7-9 08:00 | 显示全部楼层
做个mp3播放器吗   
pklong 发表于 2020-7-9 08:00 | 显示全部楼层
有演示的视频资料吗   
htmlme 发表于 2020-7-9 08:00 | 显示全部楼层
谢谢版主分享的资料了。   
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:Microchip
简介:让我们来为您提供帮助。我们可提供各种资源来帮助您解决一切问题。是否需要与我们的客户支持团队联系?您可以通过电话、在线聊天功能或电子邮件与他们联系。

151

主题

1063

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部
认证:Microchip
简介:让我们来为您提供帮助。我们可提供各种资源来帮助您解决一切问题。是否需要与我们的客户支持团队联系?您可以通过电话、在线聊天功能或电子邮件与他们联系。

151

主题

1063

帖子

11

粉丝
快速回复 在线客服 返回列表 返回顶部