51单片机实现音乐播放功能:《平凡之路》教程

怎么使用蜂鸣器播放音乐?
音乐是由一连串音符构成的,每个音符都具有特定的频率,所以可以通过一定频率数字信号使蜂鸣器产生音符效果,然后根据音乐简谱排列出音符。

部分音符频率:

1eda6009913a416384d833c3b06f0271.png

频率的产生可用定时器中断实现,定时器初值(十进制)计算代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main(void)//计算计时器初值 @11.0592MHz
{
	int x = 0;
	float result = 0;
	while (1)
	{
		printf("请输入音符频率:");
		scanf("%d", &x);
		result = 65535+1 - (float)11059200 / (12 * x);//12分频
		printf("%0.2f\n", result);
	}
	return 0;
}

《平凡之路》简谱:

61993f44ca1d4c56864a847e9aede411.jpeg

《平凡之路》为A调,完整代码如下:

#include<reg52.h>
#include<intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
sbit buzzer = P2 ^ 5;  //蜂鸣器管脚
u8 time0h = 0;         //定时器高8位
u8 time0l = 0;         //定时器低8位
u8 bats = 0;           //延时拍数
bit stop = 0;          //是否为休止符,0是,1不是(给stop赋值为非0则stop等于1)
bit smooth = 0;        //1圆滑,0不圆滑
code u8 node[] = {
	//0xf2,0xf3,0xf5,0xf5,0xf6,0xf7,0xf8,//C调低音高8位  @11.0592MHz
	//0xf9,0xf9,0xfa,0xfa,0xfb,0xfb,0xfc,//C调中音
	//0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfe,//C调高音
	//0x42,0xc1,0x17,0xaf,0xd1,0xd1,0xb6,//C调低音低8位
	//0x1e,0xde,0x8a,0xd8,0x68,0xe9,0x5b,
	//0x8f,0xf0,0x45,0x69,0xb4,0xf4,0x2e,
	//0xf3,0xf5,0xf6,0xf6,0xf7,0xf8,0xf9,//D调
	//0xf9,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,
	//0xfc,0xfd,0xfd,0xfd,0xfd,0xfe,0xfe,
	//0xc1,0x17,0x45,0xd1,0xd1,0xb6,0x80,
	//0xde,0x8a,0x23,0x68,0xe9,0x5b,0xc1,
	//0xf0,0x45,0x91,0xb4,0xf4,0x2e,0x78,
	//0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xfa,//E调
	//0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,0xfd,
	//0xfd,0xfd,0xfd,0xfd,0xfe,0xfe,0xfe,
	//0x17,0x45,0x53,0xd1,0xb6,0x80,0x36,
	//0x8a,0x23,0xab,0xe9,0x5b,0xc1,0x1c,
	//0x45,0x91,0xd5,0xf4,0x2e,0x78,0xa3,
	//0xf5,0xf6,0xf7,0xf8,0xf9,0xf9,0xfa,//F调
	//0xfa,0xfb,0xfb,0xfc,0xfc,0xfc,0xfd,
	//0xfd,0xfd,0xfd,0xfe,0xfe,0xfe,0xfe,
	//0xaf,0xd1,0xd1,0x46,0x1e,0xde,0x8a,
	//0xd8,0x68,0xe9,0x23,0x8f,0xf0,0x45,
	//0x69,0xb4,0xf4,0x12,0x60,0x8e,0xb6,
	//0xf6,0xf7,0xf8,0xf9,0xf9,0xfa,0xfb,//G调
	//0xfb,0xfb,0xfc,0xfc,0xfc,0xfd,0xfd,
	//0xfd,0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,
	//0xd1,0xd1,0xb6,0x1e,0xde,0x8a,0x23,
	//0x69,0xe9,0x5b,0x8f,0xf0,0x45,0x91,
	//0xb4,0xf4,0x2e,0x60,0x8e,0xb6,0xea,
	0xf7,0xf8,0xf9,0xf9,0xfa,0xfb,0xfb,//A调
	0xfb,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd,
	0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xff,
	0xd1,0xb6,0x80,0xde,0x8a,0x23,0xab,
	0xe9,0x5b,0xc1,0xf0,0x45,0x91,0xd5,
	0xf4,0x2e,0x78,0x8e,0xb6,0xea,0x09
	//0xf8,0xf9,0xfa,0xfa,0xfb,0xfb,0xfc,//B调
	//0xfc,0xfc,0xfd,0xfd,0xfd,0xfd,0xfe,
	//0xfe,0xfe,0xfe,0xfe,0xfe,0xff,0xff,
	//0xb6,0x80,0x36,0x8a,0x23,0xab,0x23,
	//0x5b,0xc1,0x1c,0x45,0x91,0xd5,0x12,
	//0x2e,0x78,0xa3,0xb6,0xea,0x09,0x23
};
code u8 music[] = {
	0,1,2,0, 3,1,2,0, 3,1,2,0, 6,1,1,0, 6,1,1,1, 6,1,2,0, 1,1,2,0, 2,1,2,0,
	3,1,1,0, 3,1,1,1, 3,1,4,0, 0,1,4,0, 0,1,4,0, 0,1,4,0, 0,1,2,0, 3,1,2,0,
	3,1,2,0, 6,1,2,0, 6,1,3,0, 5,1,1,0, 5,1,3,0, 4,1,1,1, 4,1,1,0, 3,1,3,1,
	3,1,4,0, 0,1,4,0, 0,1,4,0, 0,1,2,0, 3,1,2,0, 3,1,2,0, 6,1,2,1, 6,1,2,0,
	1,1,2,0, 2,1,2,0, 3,1,6,0, 0,1,4,0, 0,1,4,0, 0,1,4,0, 0,1,2,0, 3,1,2,0,
	3,1,2,0, 1,1,2,0, 3,1,2,0, 3,1,1,0, 4,1,1,1, 4,1,2,0, 3,1,2,0, 1,1,8,0,
	0,1,4,0, 0,1,4,0, 0,1,2,0, 3,1,2,0, 3,1,2,0, 6,1,1,0, 6,1,1,1, 6,1,2,0,
	1,1,2,0, 2,1,2,0, 3,1,1,0, 3,1,1,1, 3,1,4,0, 0,1,4,0, 0,1,4,0, 0,1,4,0,
	0,1,2,0, 3,1,2,0, 3,1,2,0, 6,1,2,0, 6,1,3,0, 5,1,1,0, 5,1,3,0, 4,1,1,1,
	4,1,1,0, 3,1,3,1, 3,1,4,0, 0,1,4,0, 0,1,4,0, 0,1,2,0, 3,1,1,0, 3,1,1,0,
	3,1,2,0, 6,1,2,1, 6,1,2,0, 1,1,2,0, 2,1,2,0, 3,1,2,1, 3,1,4,0, 0,1,4,0, 
	0,1,4,0, 0,1,4,0, 0,1,2,0, 3,1,2,0, 3,1,2,0, 1,1,2,0, 3,1,2,0, 3,1,1,0,
	4,1,1,1, 4,1,2,0, 3,1,2,0, 1,1,8,0, 0,1,2,0, 5,1,2,0, 6,1,2,0, 7,1,2,0,
	1,2,2,0, 7,1,1,0, 1,2,1,1, 1,2,2,0, 5,1,1,0, 6,1,1,0, 6,1,4,0, 5,1,2,0,
	4,1,1,0, 4,1,1,1, 4,1,2,0, 3,1,2,0, 3,1,2,0, 3,1,1,0, 2,1,1,1, 2,1,2,0,
	5,1,2,0, 6,1,2,0, 7,1,2,0, 1,2,2,0, 7,1,1,0, 1,2,1,1, 1,2,2,0, 5,1,1,0,
	6,1,1,0, 6,1,4,0, 6,1,2,0, 7,1,1,0, 1,2,1,1, 1,2,2,0, 1,2,2,0, 1,2,2,0,
	1,2,1,0, 2,2,1,1, 2,2,2,0, 0,1,1,0, 5,1,1,0, 6,1,2,0, 7,1,2,0, 1,2,2,0,
	7,1,1,0, 1,2,1,1, 1,2,2,0, 3,2,2,0, 6,2,3,0, 5,2,1,1, 5,2,2,0, 4,2,2,0,
	3,2,4,0, 3,2,2,0, 2,2,2,1, 2,2,4,0, 6,1,2,0, 7,1,2,0, 1,2,4,0, 1,2,2,0,
	2,2,1,0, 1,2,1,1, 1,2,3,0, 1,2,1,0, 7,1,2,0, 1,2,1,0, 2,2,1,1, 2,2,4,0,
	1,2,2,0, 7,1,2,0, 1,2,8,0, 0,1,0,0
};//歌谱格式为:音符(0-7)+低中高音(0-2)+拍数(单位0.25拍)+是否圆滑(1,0)(最后四位中的第一第三位为终止参数)
void time0() interrupt 1
{
	TR0 = 0;         //定时器关后赋值,防止从0开始定时
	buzzer = !buzzer;
	TH0 = time0h;
	TL0 = time0l;
	TR0 = 1;         //定时器开
}
void Delayms(u16 ms)//延时ms毫秒
{
	while (ms--)
	{
		u8 i, j;
		_nop_();
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}
void Sing()
{
	if (stop)
	{
		TH0 = time0h;
		TL0 = time0l;
		TR0 = 1;
	}
	else
		TR0 = 0;
	Delayms(200*bats);  //72拍/min
	if (!smooth)
	{
		TR0 = 0;
		Delayms(10);   //音符间间歇
		TR0 = 1;
	}
}
void main()
{
	u16 i = 0;
	u8  j = 0;
	EA = 1;    //总中断开
	ET0 = 1;   //T0中断允许
	TMOD = 1;  //工作方式1,16位定时计数器
	while (1)  //控制播放次数
	{
		i = 0;
		while (music[i] != 0 || music[i + 2] != 0)//这里定义音符为0与拍数为0组合代表结束歌曲
		{
			j = music[i] + 7 * music[i + 1] - 1;  //确定音符高8位位置
			time0h = node[j];
			time0l = node[j+21];
			bats = music[i + 2];
			stop = music[i];
			smooth = music[i + 3];
			Sing();
			i += 4;
		}
	}
}

/*下面是两个神秘乐谱*/
//乐谱1
/*6,1,6,0, 5,1,2,0, 3,1,4,0, 5,1,4,0, 1,2,4,0, 6,1,2,1, 5,1,2,0, 6,1,8,0,
  3,1,4,0, 5,1,2,0, 6,1,2,0, 5,1,4,0, 3,1,2,1, 2,1,2,0, 1,1,2,1, 6,0,2,0,
  5,1,2,1, 3,1,2,0, 2,1,8,0, 2,1,6,0, 3,1,2,0, 5,1,4,0, 5,1,2,0, 6,1,2,0,
  3,1,6,1, 2,1,2,0, 1,1,8,0, 5,1,6,0, 3,1,2,0, 2,1,2,1, 1,1,2,0, 6,0,2,1,
  1,1,2,0, 5,0,8,0, 0,1,0,0
*/

//乐谱2
/*1,1,4,0, 2,1,4,0, 3,1,4,0, 1,1,4,0, 1,1,4,0, 2,1,4,0, 3,1,4,0, 1,1,4,0, 
  3,1,4,0, 4,1,4,0, 5,1,8,0, 3,1,4,0, 4,1,4,0, 5,1,8,0, 5,1,3,0, 6,1,1,0, 
  5,1,3,0, 4,1,1,0, 3,1,4,0, 1,1,4,0, 5,1,3,0, 6,1,1,0, 5,1,3,0, 4,1,1,0, 
  3,1,4,0, 1,1,4,0, 1,1,4,0, 5,0,4,0, 1,1,8,0, 1,1,4,0, 5,0,4,0, 1,1,8,0, 
  0,1,0,0
*/

物联沃分享整理
物联沃-IOTWORD物联网 » 51单片机实现音乐播放功能:《平凡之路》教程

发表评论