- 实验目的
用51系列单片机设计一个可以切歌的音乐播放器。
- 实验仪器
AT89C52单片机。
音乐播放模块。
- 设计要求
采用重装定时器计数方式1的初值来实现发出不同频率的声音,通过控制延时长度来实现不同的节拍,之后将音乐数据表填入,即可实现音乐播放。
可通过功能按键切换歌曲
- 实验原理
音乐播放采用重装定时器计数方式1的初值来实现发出不同频率的声音,通过控制延时长度来实现不同的节拍,之后将音乐数据表填入,即可实现音乐播放。
音乐切换方面采取按键输入,按键检测到低电平,则判断有信号输入,等待10ms去抖后,等待下一个高电平,进行音乐的切换。
- 实验流程
- 根据课本学习喇叭发生实验、警车声音、救护车声音、喇叭滴答声音、报警发声、消防车、音乐播放等一系列实验了解了喇叭发声以及调节频率的方法。学习独立按键的用法用于切换歌曲
- 模仿音乐播放的代码,进行修改,将源代码的歌曲乐谱换成“铃儿响叮当”和“Spider Dance”的乐谱
- 将单片机喇叭短接,代码烧录入单片机。
- 实验结果
单片机正常运行,先播放“铃儿响叮当”的旋律,当我按下独立按键INT1时,歌曲切换为“Spider Dance”的旋律,如果重新按下独立按键INT1,可以切换回“铃儿响叮当”。
- 代码
#include <reg52.h>
sbit SPK = P1 ^ 2; //定义喇叭接口
sbit KEY = P3 ^ 3; //设置独立按键INT1,按下按键时切换歌曲
sbit LED = P1 ^ 7; //用于切换歌曲的显示,当LED = 1时播放铃儿响叮当,否则播放Spider Dance
int Timer0_H, Timer0_L, Time; //定义定时器变量和时间变量
code unsigned char MUSIC1[] = { //歌曲“铃儿响叮当”的乐谱,每个音由3个变量构成,前两个变量用来确定音乐频率,第三个变量确定持续时间
3,2,2,3,2,2, 3,2,4, 3,2,2,3,2,2, 3,2,4,
3,2,2,5,2,2, 1,2,3,2,2,1, 3,2,8,
4,2,2,4,2,2, 4,2,2,4,2,2, 4,2,2,3,2,2, 3,2,2,3,2,2,
5,2,2,5,2,2, 4,2,2,2,2,2, 1,2,4, 1,3,4, 0,0,0
};
code unsigned char MUSIC2[] = { //歌曲“Spider Dance”的乐谱,如果前两个变量为(0,0)时则为空拍
6,3,4, 3,3,4, 1,3,4, 6,2,4,
0,0,2, 2,3,2, 2,3,2, 0,0,4, 2,3,2, 1,3,2, 5,2,2, 6,2,2,
0,0,2, 3,3,2, 2,3,2, 1,3,2, 2,3,2, 3,3,2, 5,2,2, 6,2,2,
1,3,2, 6,2,2, 5,2,2, 6,3,2, 0,0,2, 5,3,2, 3,3,1, 2,3,1, 1,3,2,
6,2,4, 4,2,4, 7,2,4, 4,2,4,
1,3,4, 4,2,4, 2,3,8,
3,3,4, 2,3,4, 6,3,4, 3,3,4,
5,3,4, 4,3,4, 3,3,4, 0,0,4,
6,3,2, 3,4,2, 2,4,2, 3,4,2, 6,3,2, 3,4,2, 2,4,2, 3,4,2,
3,3,2, 2,4,2, 2,4,2, 2,4,2, 3,3,2, 3,4,2, 7,3,2, 2,4,2,
6,3,2, 3,4,2, 2,4,2, 3,4,2, 7,3,2, 3,4,2, 2,4,2, 3,4,2,
1,4,2, 3,4,2, 2,4,2, 3,4,2, 2,4,2, 4,4,2, 3,4,2, 4,4,2,
4,3,2, 1,4,2, 7,3,2, 1,4,2, 4,3,2, 2,4,2, 1,4,2, 2,4,2,
4,3,2, 3,4,2, 2,4,2, 3,4,2, 4,3,2, 4,4,2, 3,4,2, 4,4,2, 0,0,0
};
code unsigned char FREQH[]= { //频率表前八位,第0行频率为低两个8度的音,第1行频率为低一个8度的音,第2行为正常音,第3行为高8度的音
//(抱歉,乐理基础没学好,音的标准说法忘了咋说了,懂意思就好)
// 比如说正常音la,持续时间为2,那就是(6,2,2)
0xF2,0XF3,0xF5,0xF5,0XF6,0XF7,0XF8,
0xF9,0XF9,0XFA,0XFA,0XFB,0XFB,0XFC,0XFC,
0xFC,0XFD,0XFD,0XFD,0XFD,0XFE,
0xFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFF
};
code unsigned char FREQL[]= { //频率表后八位
0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F,
0xEE,0x44,0x6B,0xB4,0xF4,0x2D,
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16
};
void DelayUs2x(unsigned char t) //延迟函数
{
while (--t)
{
}
}
void DelayMs(unsigned char t) //延迟时间函数,略微修改,时间不准
{
while (--t)
{
DelayUs2x(245);
}
}
void delay(unsigned char t) //延迟时间函数
{
unsigned char i;
for (i = 0; i < t; i++)
DelayMs(125);
TR0 = 0;
}
void Init_Timer0(void) //定时器初始化函数
{
TMOD |= 0x01; //模式1,16位定时器/计数器
EA = 1; //总中断打开
ET0 = 1; //定时器中断打开
}
void TIM0_ISR() interrupt 1 //定时器中断函数,用于读取音符频率值,产生对应的音符
{
TR0 = 0; //定时器暂停
SPK = !SPK; //喇叭反转
TH0 = Timer0_H; //重置定时
TL0 = Timer0_L;
TR0 = 1; //定时器开始
}
void Song()
{
if (Timer0_H == -1 && Timer0_L == -1) //空拍判断,喇叭不发声
{
delay(Time);
}
else
{
TH0 = Timer0_H; //重置定时
TL0 = Timer0_L;
TR0 = 1;
delay(Time);
}
}
void main(void)
{
unsigned char k, i;
Init_Timer0();
KEY = 1;
LED = 1;
while (1)
{
i = 0;
if (LED) //播放“铃儿响叮当”
{
while (i < 76) //这个数字是MUSIC数组里的变量数
{
k = MUSIC1[i] + 7 * MUSIC1[i + 1] - 1;//频率位置,用两个变量进行判断
Timer0_H = FREQH[k];// 获取频率高八位
Timer0_L = FREQL[k];// 获取频率低八位
Time = MUSIC1[i + 2];// 获取持续时间
i += 3;
Song();
if (!KEY) //判断独立按键按下
{
while (!KEY) //判断按键释放
{ }
LED = !LED; //切歌
break;
}
}
}
else
{
while (i < 280) //播放“Spider Dance”
{
k = MUSIC2[i] + 7 * MUSIC2[i + 1] - 1;
Timer0_H = FREQH[k];
Timer0_L = FREQL[k];
Time = MUSIC2[i + 2];
i += 3;
Song();
if (!KEY)
{
while (!KEY)
{ }
LED = !LED;
break;
}
}
}
}
}