四、音乐播放器
任务要求:
设计制作一个简易音乐播放器(通过手柄板上的蜂鸣器发声,播放2到4首音
乐),同时LED模块闪烁,给人视、听觉美的感受。
评分细则:
- 按下播放按键P15开始播放音乐,再次按下停止播放;(20分)
- 按下按键P14播放下一首,按下按键P13播放上一首;(20分)
- 播放音乐时OLED显示相应的曲目名;(20分)
- 当按下"下一首"或者"上一首〃按键,但是已经播放至最后一首时,显示屏显
示"无更多曲目!",同时蜂鸣器报警三秒钟;(20分) - 歌曲名横向滚动显示;(10分)
- 具有音乐播放模式切换键,播放模式有单曲循环、顺序播放、随机播放三种
模式。(10分)
要求可以播放2至4首音乐,音乐节拍可通过网络等渠道收集。LED模块的闪烁
方式不做要求。
涉及的单片机内容以及口袋开发板模块:
单片机:I/O功能、定时/计数器、显示接口
口袋开发板:独立按键、OLED显示屏、蜂鸣器
原理:单片机使用PWM驱动无源蜂鸣器发声,PWM频率改变,发声频率就会改变。一首简谱就是由不同频率的音节组成的。
部分代码:
/* ****************************************** */
/* ******** 延时 80 ms 控制音乐节拍 */
/* ****************************************** */
void delay1()
{delay_ms( 80 );
}char taskBusy;
void main( void )
{unsigned char u = 0, t = 0;WDT_Init(); /*看门狗设置 */Clock_Init(); /* 系统时钟设置 */User_SystemInit(); /* 用户控制系统初始化函数 */Timer_Init( TimerA, 10000 ); /* 10ms定时器中断 */TBCCTL0 = CCIE; /* CCR0 interrupt enabled */TBCCR0 = 0;TBCTL = TBSSEL_2 + MC_1 + ID_3; /* SMCLK, contmode */dis_bofangmode();dis_bofangmode();_EINT();while ( 1 ){if ( taskBusy == 1 ){User_RealTimeTask( 100 ); /* 实时控制任务 */}else { /* 空闲任务(大部分时间空闲,可以用来管理一些不紧急的任务,不易放长时间执行的任务) */User_IdleTask();}delay_ms(10);if(daojishi==0 && ((music_crr == 10) ||(music_crr==-1)))//倒计时结束关闭蜂鸣器{TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */}if(daojishi!=0){TBCCR0 = SYSCLK / H7 / 2; /*选一个频率 */TBCTL = TBSSEL_2 + MC_1 + TBCLR + ID_3; /* SMCLK, upmode */}if ( (music_crr == 0) && open_flag == 1 ){u = 0; /* 从第1个音符f[0]开始播放 */while ( music0[u] != 0xff ) /* 只要没有读到结束标志就继续播放 */{if ( music_crr != 0 ) /* 切换音乐 */{TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */break;}while ( open_flag == 0 ); /* 如果暂停音乐 */TBCCR0 = SYSCLK / music0[u] / 2; /*选一个频率 */TBCTL = TBSSEL_2 + MC_1 + TBCLR + ID_3; /* SMCLK, upmode */for ( t = 0; t < music0_JP[u]; t++ ) /* 控制节拍数 */delay1(); /* 延时1个节拍单位 */TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */u++; /* 播放下一个音符 */}if(bofang_mode==1){music_crr=music_crr+1;if(music_crr==4)music_crr=0;//顺序循环}else if(bofang_mode==2){music_crr=(music_crr+13)%4;//随机}TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */}if ( music_crr == 1 && open_flag == 1 ){u = 0; /* 从第1个音符f[0]开始播放 */while ( music1[u] != 0xff ) /* 只要没有读到结束标志就继续播放 */{if ( music_crr != 1 ) /* 切换音乐 */{TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */break;}while ( open_flag == 0 ); /* 如果暂停音乐 */TBCCR0 = SYSCLK / music1[u] / 2; /*选一个频率 */TBCTL = TBSSEL_2 + MC_1 + TBCLR + ID_3; /* SMCLK, upmode */for ( t = 0; t < music1_JP[u] / 2; t++ ) /* 控制节拍数 */delay1(); /* 延时1个节拍单位 */TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */u++; /* 播放下一个音符 */}if(bofang_mode==1){music_crr=music_crr+1;if(music_crr==4)music_crr=0;//顺序循环}else if(bofang_mode==2){music_crr=(music_crr+13)%4;//随机}TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */}if ( music_crr == 2 && open_flag == 1 ){u = 0; /* 从第1个音符f[0]开始播放 */while ( music2[u] != 0xff ) /* 只要没有读到结束标志就继续播放 */{if ( music_crr != 2 ) /* 切换音乐 */{TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */break;}while ( open_flag == 0 ); /* 如果暂停音乐 */TBCCR0 = SYSCLK / music2[u] / 2; /*选一个频率 */TBCTL = TBSSEL_2 + MC_1 + TBCLR + ID_3; /* SMCLK, upmode */for ( t = 0; t < music2_JP[u]; t++ ) /* 控制节拍数 */delay1(); /* 延时1个节拍单位 */TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */u++; /* 播放下一个音符 */}if(bofang_mode==1){music_crr=music_crr+1;if(music_crr==4)music_crr=0;//顺序循环}else if(bofang_mode==2){music_crr=(music_crr+13)%4;//随机}TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */}if ( music_crr == 3 && open_flag == 1 ){u = 0; /* 从第1个音符f[0]开始播放 */while ( music3[u] != 0xff ) /* 只要没有读到结束标志就继续播放 */{if ( music_crr != 3 ) /* 切换音乐 */{TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */break;}while ( open_flag == 0 ); /* 如果暂停音乐 */TBCCR0 = SYSCLK / music3[u] / 2; /*选一个频率 */TBCTL = TBSSEL_2 + MC_1 + TBCLR + ID_3; /* SMCLK, upmode */for ( t = 0; t < music3_JP[u]; t++ ) /* 控制节拍数 */delay1(); /* 延时1个节拍单位 */TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */u++; /* 播放下一个音符 */}if(bofang_mode==1){music_crr=music_crr+1;if(music_crr==4)music_crr=0;//顺序循环}else if(bofang_mode==2){music_crr=(music_crr+13)%4;//随机}TBCTL = TBSSEL_2 + MC_0 + ID_3; /* 关闭 */GPIO_Set( P5, 6, 1 ); /* 关闭蜂鸣器 */}}
}/* Timer B0 interrupt service routine */
#pragma vector=TIMERB0_VECTOR
__interrupt void Timer_B( void )
{GPIO_turn( P5, 6 );
}
全部代码:https://github.com/xddun/blog_code_search