四、音乐播放器
任务要求:
设计制作一个简易音乐播放器(通过手柄板上的蜂鸣器发声,播放2到4首音
乐),同时LED模块闪烁,给人视、听觉美的感受。
评分细则:
要求可以播放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