简易的单片机音乐控制.docx
《简易的单片机音乐控制.docx》由会员分享,可在线阅读,更多相关《简易的单片机音乐控制.docx(11页珍藏版)》请在冰豆网上搜索。
简易的单片机音乐控制
简易的单片机音乐控制
作者:
侯静
针对以前转贴的那篇单片机音乐控制,其算法对初学者不是很容易弄懂
此,我根据网上提供的资料。
用C语言写了一个《八月桂花香》的音乐控制。
音调是由不同的频率产生的,而每一个音调都是由一个音符和一个节拍组成,音符决定该音调的高低,节拍则决定了该音调是多少拍。
因此,一个音调是由两个字节组成的。
根据音符字节产生该大小次数的延时,声音输出口取反,就可以得到该音调的高低音。
根据设置单位节拍的延时大小,可以控制音乐演唱速度。
因此算法很简单:
定义单片机的一个I/O端脚为声音输出口,在规定的节拍内,根据音符字节的大小产生延时,将声音输出口不断的置高置低(即取反),就可以得到该音调。
只要选取合适的单位节拍延时,就可以输出动听的音乐。
算法流程图如下:
//**********主程序*********
#include
#include"SoundPlay.h"
uchardatacount=0;
voidinit_com()
{
TMOD=0x01;
TH0=0xff;
TL0=0xff;
EA=1;
ET0=1;
}
voidtimer0(void)interrupt1using3
{
counter=counter+1;//节拍次数计数
TH0=0xd8;//定义单位节拍的延时大小
TL0=0xef;
}
voiddelay(ucharn)
{
uchari;
while(n--)
for(i=0;i<125;i++);//延时1毫秒
}
voidsound_delay(ucharn)
{
uchari;
while(n--)
{
for(i=0;i<2;i++);
}
}
voidmain()
{
uinti;
ucharsound_signal;//定义音符大小
ucharsound_pace;//定义节拍大小
init_com()
//array[i]=0x00代表歌曲演唱完毕
//array[i]=0xff代表是休止符
while
(1)
{
i=0;
while(array[i]!
=0x00)
{
//如果是休止符,延时100ms,并终止本次循环,进入下一个循环
if(array[i]==0xff)
{
TR0=0;
i++;
delay(100);
continue;
}
//从表中取得音符大小
sound_signal=array[i];
i=i+1;
//从表中取得节拍大小
sound_pace=array[i];
TR0=1;
//当节拍数未达到时候,继续循环,产生该音调的声音
while(counter!
=sound_pace)
{
sound=~sound;
sound_delay(sound_signal);
}
i++;
counter=0;//节拍计数器置0,进入下一个音调
}
delay(10);//歌曲演唱完毕后,延时一段时间
}
}
//*******soundplay.h**********
#ifndef__SOUNDPLAY_H_REVISION_FIRST__
#define__SOUNDPLAY_H_REVISION_FIRST__
#defineucharunsignedchar
#defineuintunsignedint
sbitsound=P1^2;
uintcounter=0;
ucharcodearray[]=
{
0x18,0x30,0x1C,0x10,
0x20,0x40,0x1C,0x10,
0x18,0x10,0x20,0x10,
0x1C,0x10,0x18,0x40,
0x1C,0x20,0x20,0x20,
0x1C,0x20,0x18,0x20,
0x20,0x80,0xFF,0x20,
0x30,0x1C,0x10,0x18,
0x20,0x15,0x20,0x1C,
0x20,0x20,0x20,0x26,
0x40,0x20,0x20,0x2B,
0x20,0x26,0x20,0x20,
0x20,0x30,0x80,0xFF,
0x20,0x20,0x1C,0x10,
0x18,0x10,0x20,0x20,
0x26,0x20,0x2B,0x20,
0x30,0x20,0x2B,0x40,
0x20,0x20,0x1C,0x10,
0x18,0x10,0x20,0x20,
0x26,0x20,0x2B,0x20,
0x30,0x20,0x2B,0x40,
0x20,0x30,0x1C,0x10,
0x18,0x20,0x15,0x20,
0x1C,0x20,0x20,0x20,
0x26,0x40,0x20,0x20,
0x2B,0x20,0x26,0x20,
0x20,0x20,0x30,0x80,
0x20,0x30,0x1C,0x10,
0x20,0x10,0x1C,0x10,
0x20,0x20,0x26,0x20,
0x2B,0x20,0x30,0x20,
0x2B,0x40,0x20,0x15,
0x1F,0x05,0x20,0x10,
0x1C,0x10,0x20,0x20,
0x26,0x20,0x2B,0x20,
0x30,0x20,0x2B,0x40,
0x20,0x30,0x1C,0x10,
0x18,0x20,0x15,0x20,
0x1C,0x20,0x20,0x20,
0x26,0x40,0x20,0x20,
0x2B,0x20,0x26,0x20,
0x20,0x20,0x30,0x30,
0x20,0x30,0x1C,0x10,
0x18,0x40,0x1C,0x20,
0x20,0x20,0x26,0x40,
0x13,0x60,0x18,0x20,
0x15,0x40,0x13,0x40,
0x18,0x80,0x00
};
#endif
用单片机控制蜂鸣器放音乐
悬赏分:
0-解决时间:
2008-11-2514:
44
下面的程序怎么理解,数组是怎么得到的
#include"reg51.h"
unsignedcharCount;
sbitFMQ=P3^5;//蜂鸣器控制脚
unsignedcharcodeSONG[]={
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,
0x26,0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,
0x26,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,0x20,0x80,0x2b,0x20,
0x26,0x20,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,
0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,
0x39,0x10,0x26,0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x26,0x10,
0x26,0x80,0x26,0x20,0x2b,0x10,0x2b,0x10,0x2b,0x20,0x30,0x10,
0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x20,
0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x18,0x20,
0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x40,0x26,0x20,0x2b,0x20,
0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,0x1c,0x20,
0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,
0x10,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,
0x10,0x2b,0x10,0x2b,0x80,0x18,0x20,0x18,0x20,0x26,0x20,0x20,
0x20,0x20,0x60,0x26,0x10,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,
0x20,0x20,0x20,0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,
0x20,0x39,0x20,0x26,0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,
0x10,0x40,0x10,0x20,0x10,
0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00,};
voidTime0_Init()//定时器0初始化函数
{
TMOD=0x01;//工作模式选择
IE=0x82;//中断设置
TH0=0xD8;//装初值
TL0=0xEF;//12MZ晶振,10ms
}
voidTime0_Int()interrupt1//定时器0中断子函数
{
TH0=0xD8;
TL0=0xEF;
Count++;//长度加1
}
voidPlay_Song(unsignedchari)
{
unsignedcharTemp1,Temp2;
unsignedintAddr;
Count=0;//中断计数器清0
Addr=i*217;
while
(1)
{
Temp1=SONG[Addr++];
if(Temp1==0xFF)//休止符
{
TR0=0;
Delay_xMs(100);
}
elseif(Temp1==0x00)//歌曲结束符
{
return;
}
else
{
Temp2=SONG[Addr++];
TR0=1;
while
(1)
{
FMQ=~FMQ;
Delay_xMs(Temp1);
if(Temp2==Count)
{
Count=0;
break;
}
}
}
}
}
问题补充:
谢谢你,我已经自己编出来了,恩,你说的问题确实是延时定义有问题。
提问者:
guduyishuai-二级
最佳答案
看起来数组应该是音乐数据,其中包括四种数据,就是休止符(每个100毫秒)、歌曲结束符、音阶(给出的是蜂鸣器的震荡周期)、一个音阶持续的时间长度。
如果你的晶振是12MHz,按照定时器中断给Count加一来看,音阶持续的时间应该是以10毫秒为单位。
Play_Song函数要求给出参数i,我的看法是这个i是指要播放第几段乐曲,i*217表示每段乐曲都是217个字节。
本例中,数组只给出217个字节,所以只有一段乐曲,播放时需要给出参数i=0.
if(Temp1==0xFF)//休止符
{
TR0=0;
Delay_xMs(100);
}
所以休止符每个固定是100毫秒。
如果读到第一个不是休止符或者结束符的字节,那就是音阶,而下一个字节就是这个音阶的长度或者说节拍
while
(1)
{
FMQ=~FMQ;
Delay_xMs(Temp1);
if(Temp2==Count)
{
Count=0;
break;
}
}
这一段是说,如果当前音阶的时间(Temp2次定时器中断,由Count计时)还没完,就每隔Temp1毫秒震动一次蜂鸣器,就形成一个震动频率,这段时间就发出一定音调的乐音。
不过我也有疑惑,震荡周期如果以毫秒为单位恐怕只能发出次声波,所以以上对有关Delay_xMs函数时间的估算都可能有问题,还得看Delay_xMs函数的具体定义才行。
一个简单的单片机音乐播放程序
电子工程师之路2010-04-2017:
59:
56阅读8评论0字号:
大中小
#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
sbit speaker=P1^2; //定义音乐输出端口,需要连接到对应的喇叭
unsignedchartimer0h,timer0l,time;
//《挥剑问情》数据表
codeunsignedcharhjwq[]={ 3,2,2, 3,2,1, 2,2,1,3,2,2,3,2,1,2,2,1,3,2,1,
6,2,1, 5,2,1, 3,2,1,2,2,2,1,2,1,2,2,1,3,2,2,
3,2,1, 2,2,1, 3,2,2,3,2,1,2,2,1,3,2,1,1,3,1,
6,2,1, 5,2,1, 3,2,2,3,2,1,3,2,1,5,2,1,6,2,2,
6,2,1, 1,3,1, 6,2,2,5,2,1,3,2,1,2,2,5,1,2,1,
2,2,1, 3,2,2, 3,2,1,5,2,1,3,2,2,3,2,1,1,2,1,
2,2,5, 3,2,1, 2,2,1,3,2,2,3,2,1,2,2,1,3,2,2,
3,2,1, 2,2,1, 3,2,1,6,2,1,5,2,1,3,2,1,2,2,2,
3,2,1, 5,2,1, 6,2,3,1,3,1,6,2,3,1,3,1,5,2,1,
6,2,1, 1,3,1, 7,2,1,6,2,1,5,2,1,3,2,1,5,2,1,
6,2,5, 3,2,1, 5,2,1,6,2,5,3,2,1,5,2,1,6,2,1,
1,3,1, 6,2,5, 5,2,4,3,2,2,5,2,2,6,2,3,1,3,1,
5,2,2, 3,2,2, 2,2,4,5,2,2,2,2,2,3,2,3,6,2,1,
5,2,2, 2,2,2, 3,2,4,2,2,2,3,2,1,2,2,1,1,2,6,
2,2,1, 1,2,1, 6,1,2,1,2,2,2,2,2,3,2,2,5,2,2,
6,2,2, 3,2,3, 1,2,1,2,2,4,3,2,2,5,2,2,6,2,3,
1,3,1, 5,2,2, 3,2,2,2,2,4,5,2,2,2,2,2,3,2,3,
6,2,1, 5,2,2, 3,2,2,5,2,4,6,2,2,1,3,2,2,3,4,
6,2,4, 5,2,4, 6,2,4,1,3,2,3,3,2,2,3,2,1,3,2,
5,2,2, 6,2,10
};
//音阶频率表高八位
codeunsignedcharFREQH[]={
0xF2,0xF3,0xF5,0xF5,0xF6,0xF7,0xF8,
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,0xFC,//1,2,3,4,5,6,7,8,i
0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
};
//音阶频率表低八位
codeunsignedcharFREQL[]={
0x42,0xC1,0x17,0xB6,0xD0,0xD1,0xB6,
0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B,0x8F,//1,2,3,4,5,6,7,8,i
0xEE,0x44,0x6B,0xB4,0xF4,0x2D,
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
};
/******************************************************************/
/* 延时函数 */
/******************************************************************/
voiddelay(unsignedchart)
{
unsignedchart1;
unsignedlongt2;
for(t1=0;t1 {
for(t2=0;t2<8000;t2++)
{
;
}
}
TR0=0;
}
/******************************************************************/
/* 定时器中断函数 */
/*****************************