本帖最后由 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,代码如下:
static void TimingDelayDecrement(void)
{
if (TimingDelay != 0x00) {
TimingDelay--;
}
ms++;
space_n++; //音乐节拍计时
}
微秒定时器是启用了tim2,在定时器中断里,我开始用引脚置位后再复位的办法,也许是时间太短,喇叭无反映,尝试加__NOP()延时也不起作用,而且延时太多会引起单片机假死,只有使用引脚翻转命令才有效,但输出的频率太低,效果很差。尝试缩短定时器延时时间,受主频影响无法继续缩短,最后只好采取降低音符频率数值的办法才达到目的。下面是定时器2的配置代码:
Tim2_UPCount_test(2,47); //控制扬声器
在定时器2的中断处理中代码如下:
void TIM2_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// ucTim2Flag++;
if(space > 0){
cycle_n++;
if(cycle_n > cycle){
SBK_TOGGLE(); //翻转引脚
cycle_n = 0; //重新计数
}
}
}
在主循环中的代码如下:
//轮询按键状态
keys[0] = GPIO_ReadInputDataBit(SW1_GPIO_Port,SW1_Pin);
keys[1] = GPIO_ReadInputDataBit(SW2_GPIO_Port,SW2_Pin);
keys[2] = GPIO_ReadInputDataBit(SW3_GPIO_Port,SW3_Pin);
keys[3] = GPIO_ReadInputDataBit(SW4_GPIO_Port,SW4_Pin);
if(0 == keys[3]){
LED4_ON();
song = 1; //启动音乐
LED3_ON();
space = 1;
}
else
LED4_OFF();
if(0 == keys[2]){ //中断播放
song = 0;
cycle = 0;
LED3_OFF();
}
if(song > 0){ //音乐播放控制
if((space > 0) & (space_n > space)){
LED4_ON();
cycle = SONG1[song][0]>>4;//取当前的音阶cycle及节拍space
space = SONG1[song][1]<<1;
cycle_n = 0; //音符及节拍计数清零
space_n = 0;
LCD_write_value(25,3,4,0,0,cycle);
LCD_write_value(25,4,4,0,0,space);
song++; //准备取下一音符
LCD_write_value(60,3,3,0,0,song);
if(space == 0){
song = 0; //取得末尾的0时结束播放
LED3_OFF();
}
LED4_OFF();
}
}
经过三天时间的反复测试,程序基本上达到了预期,只是休止符的节拍延时不正确,尚未找到原因。
下面是【城南旧事】主题歌【送别】的音乐数据: uint16_t SONG1[][2] = //数据表,音阶(微秒)、节拍(毫秒)
{
0,0,
1276,250, //5
1517,125, //3
1276,125, //5
956, 500, //1^
1137,250, //6
956, 125, //1^
1137,125, //6
1276,500, //5
1276,250, //5
1912,125, //1
1703,125, //2
1517,250, //3
1703,125, //2
1912,125, //1
1703,750, //2
0,50, //0
1276,250, //5
1517,125, //3
1276,125, //5
956, 375, //1^
1013,125, //7
1137,250, //6
956, 250, //1^
1276,500, //5
1276,250, //5
1703,125, //2
1517,125, //3
1432,375, //4
2026,125, //7_
1912,750, //1
0,50, //0
1137,250, //6
956, 250, //1^
956,500, //1^
1013,250, //7
1137,125, //6
1013,125, //7
956,500, //1^
1137,125, //6
1013,125, //7
956, 125, //1^
1137,125, //6
1137,125, //6
1276,125, //5
1517,125, //3
1912,125, //1
1703,750, //2
0,50, //0
1276,250, //5
1517,125, //3
1276,125, //5
956,375, //1^
1013,125, //7
1137,250, //6
956, 250, //1^
1276,500, //5
1276,250, //5
1703,125, //2
1517,125, //3
1432,375, //4
2026,125, //7_
1912,1000, //1
0,0,
0,0,
};
|
共2人点赞
|