单片机播放音乐的编程方法网络整理版.docx
- 文档编号:3552232
- 上传时间:2022-11-23
- 格式:DOCX
- 页数:11
- 大小:20KB
单片机播放音乐的编程方法网络整理版.docx
《单片机播放音乐的编程方法网络整理版.docx》由会员分享,可在线阅读,更多相关《单片机播放音乐的编程方法网络整理版.docx(11页珍藏版)》请在冰豆网上搜索。
单片机播放音乐的编程方法网络整理版
我将阐述播放音乐的软件编程方法。
原理:
1’要让单片机控制扬声器发出音调只要计算出某一音频的频率,进而计算出周期,然后将这一周期除以二,即为半周期的时间。
利用定时器计数这半个周期。
每当计数到这个时间就将输出I/O口取反,重复这个步骤就可以得到这个音调的脉冲。
2’利用80C51扥内部定时器使用其工作在计数器模式MODE1下,改变计数值TH0,及TL0易产生不同频率的方法。
例如长生频率为532HZ的脉冲,其周期为T=1/523=1912us。
因此只要计数器计数956/1us=956。
在每次计数956次后将I/O口取反,就可得到中音DO(523HZ)。
计数脉冲值与频率的关系公式如下:
N=Fi÷2÷FrN:
计算值
Fi:
内部计数时一次计数为1us,故其频率为1MHZ.
3’其计数值的求法如下;
T=65536-N=65536-Fi÷2÷Fr其计数值的求法如下
例如:
设K=65536,F=1000000=Fi=1MHZ,求低音DO(261HZ),中
音DO(523HZ),高音DO(1046HZ)的计算值。
T=65536-N=65536-Fi÷2÷Fr=65536-1000000÷2÷Fr=65536-500000/Fr。
低音DO的T=65536-500000/262=63627
中音DO的T=65536-500000/523=64580
高音DO的T=65536-500000/1047=65059
4’C调各音符频率与计数值T的对照表如下所示.
在音乐中所谓音调其实就是我们所说的音高,在音乐中我们常把C调上方的A作为标准音调,其频率等于440HZ。
当两个声音信号的频率相差一倍是也即f1=2f2,则称相差一个倍频程,在音乐中低音1和中音1,低和中2正好相差一个倍频程在音乐上称他们相差一个八度音,一个八音度有12个伴音,即为1-#1,#1-2,2-#2,#2-3,3-4,4-#4,#4-5,5-#5,#5-6,6-#6,#6-7,7-i.如果我们知道了这十二个基本音调的频率,我们就可以根据倍频程的关系得到其他调。
例如产生标准音高440HZ音调:
T=1/f=1/440=2272us,t=T/2=1136us.
这个t就是定时器中断触发时间一般情况下单片机播放音乐工作于方式1,它以振荡器的十二分频作为脉冲信号:
f0=12MHZ,
TH=(65536-t*f0/12)/256,TL=(65536-t*f0/12)%256
则TH440=FBH,TL440=90H.
音符频率简码(T值)音符频率简码(T值)
低1DO26263628#1DO#27763731
低2RE29463853#2RE#31163928
低3MI33064021
低4FA34964103#4FA#37064185
低5SO39264260#5SO#41564331
低6LA44064400#6LA#46664463
低7SI49464524
中1DO52364580#1DO#55464580
中2RE58764684#2RE#62264732
中3MI65964777
中4FA69864820#4FA#74064860
中5SO78464898#5SO#83164934
中6LA88064968#6LA#93264994
中7SI98865030
高1DO104665058#1DO#110965085
高2RE117565110#2RE#124565134
高3MI131865157
高4FA139765178#4FA#148065198
高5SO156865217#5SO#166165235
高6LA176065252#6LA#186565268
高7SI196765283
5’乐普节拍知识
每个音符使用1个字节,字节的高四位代表音符的高低,低四位代表音符的节拍,表1为节拍与节拍码的对照。
如果1拍为0.4秒,1/4拍是0.1秒,只要设定延迟时间就可求得节拍的时间。
假设1/4拍为1DELAY,则1拍为4×DELAY,以此类推所以只要求的1/4拍的DELAY时间其余的节拍就是他的倍数如表2所示为1/41/8节拍的时间设定。
节拍码
节拍数
1
1/4拍
2
2/4拍
3
3/4拍
4
1拍
5
1又1/4拍
6
1又1/2拍
8
2拍
A
2又1/2拍
C
3拍
F
3又3/4拍
表1:
节拍码
节拍数
1
1/8拍
2
1/4拍
3
3/8拍
4
1/2拍
5
5/8拍
6
3/4拍
8
1拍
A
1又1/4拍
C
1又1/2拍
表3各调1/4节拍的时间设定各调1/8节拍的时间设定
曲调值
DELAY
曲调值
DELAY
调4/4
125毫秒
调4/4
62毫秒
调3/4
187毫秒
调3/4
94毫秒
调2/4
250毫秒
调2/4
125毫秒
7’编码建立音乐的步骤
1,先把乐谱的音符找出,然后由表4建立的T值表的顺寻。
2,把T值表建立在TABLE1,构成发音符的计数值放在“TABLE”。
3,简谱码(音符为高位),节拍为(节拍数)为低四位,音符节拍码放在程序的“TABLE”处。
简谱
发音
简谱码
T值
5
低SO
1
64260
6
低LA
2
64400
7
低SI
3
64524
1
中DO
4
64580
2
中RE
5
64684
3
中MI
6
64777
4
中FA
7
64820
5
中SO
8
64898
6
中LA
9
64968
7
中SI
A
65030
1
高DO
B
65058
2
高RE
C
65110
3
高MI
D
65157
4
高FA
E
65178
5
高SO
F
65217
1/4拍的延迟时间=187毫秒
DELAY:
MOVR7.#02
D2:
MOVR6.#187
D3:
MOVR5.#248
DJNZR5.$
DJNZR6.D3
DJNZR7.D2
RET
程序如下:
曲谱存贮格式unsignedcharcodeMusicName{音高,音长,音高,音长....,0,0};末尾:
0,0表示结束(Important)
音高由三位数字组成:
个位是表示1~7这七个音符
十位是表示音符所在的音区:
1-低音,2-中音,3-高音;
百位表示这个音符是否要升半音:
0-不升,1-升半音。
音长最多由三位数字组成:
位表示音符的时值,其对应关系是:
|数值(n):
|0|1|2|3|4|5|6
|几分音符:
|1|2|4|8|16|32|64音符=2^n
十位表示音符的演奏效果(0-2):
0-普通,1-连音,2-顿音
百位是符点位:
0-无符点,1-有符点
调用演奏子程序的格式
Play(乐曲名,调号,升降八度,演奏速度);
|乐曲名:
要播放的乐曲指针,结尾以(0,0)结束;
|调号(0-11):
是指乐曲升多少个半音演奏;
|升降八度(1-3):
1:
降八度,2:
不升不降,3:
升八度;
|演奏速度(1-12000):
值越大速度越快;******************************************/
#ifndef__SOUNDPLAY_H_REVISION_FIRST__
#define__SOUNDPLAY_H_REVISION_FIRST__
//*************************************#defineSYSTEM_OSC11059200
//定义晶振频率12000000HZ
#defineSOUND_SPACE4/5//定义普通音符演奏的长度分率,//每4分音符间隔
sbitBeepIO=P2^0;//定义输出管脚
unsignedintcodeFreTab[12]={262,277,294,311,330,349,369,392,415,440,466,494};//原始频率表
unsignedcharcodeSignTab[7]={0,2,4,5,7,9,11};//1~7在频率表中的位置
unsignedcharcodeLengthTab[7]={1,2,4,8,16,32,64};
unsignedcharSound_Temp_TH0,Sound_Temp_TL0;//音符定时器初值暂存
unsignedcharSound_Temp_TH1,Sound_Temp_TL1;//音长定时器初值暂存
//*****************************************
voidInitialSound(void)
{
BeepIO=0;
Sound_Temp_TH1=(65535-(1/1200)*SYSTEM_OSC)/256;
//计算TL1应装入的初值(10ms的初装值)
Sound_Temp_TL1=(65535-(1/1200)*SYSTEM_OSC)%256;
//计算TH1应装入的初值
TH1=Sound_Temp_TH1;
TL1=Sound_Temp_TL1;
TMOD|=0x11;
ET0=1;
ET1=0;
TR0=0;
TR1=0;
EA=1;
}
voidBeepTimer0(void)interrupt1//音符发生中断
{
BeepIO=!
BeepIO;
TH0=Sound_Temp_TH0;
TL0=Sound_Temp_TL0;
}
//**************************************************************************
voidPlay(unsignedchar*Sound,unsignedcharSignature,unsignedOctachord,unsignedintSpeed)
{
unsignedintNewFreTab[12];//新的频率表
unsignedchari,j;
unsignedintPoint,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
unsignedcharTone,Length,SL,SH,SM,SLen,XG,FD;
for(i=0;i<12;i++)//根据调号及升降八度来生成新的频率表
{
j=i+Signature;
if(j>11)
{
j=j-12;
NewFreTab[i]=FreTab[j]*2;
}
else
NewFreTab[i]=FreTab[j];
if(Octachord==1)
NewFreTab[i]>>=2;
elseif(Octachord==3)
NewFreTab[i]<<=2;
}
SoundLength=0;
while(Sound[SoundLength]!
=0x00)//计算歌曲长度
{
SoundLength+=2;
}
Point=0;
Tone=Sound[Point];
Length=Sound[Point+1];//读出第一个音符和它时时值
LDiv0=12000/Speed;//算出1分音符的长度(几个10ms)
LDiv4=LDiv0/4;//算出4分音符的长度
LDiv4=LDiv4-LDiv4*SOUND_SPACE;//普通音最长间隔标准
TR0=0;
TR1=1;
while(Point { SL=Tone%10;//计算出音符 SM=Tone/10%10;//计算出高低音 SH=Tone/100;//计算出是否升半 CurrentFre=NewFreTab[SignTab[SL-1]+SH];//查出对应音符的频率 if(SL! =0) { if(SM==1)CurrentFre>>=2;//低音 if(SM==3)CurrentFre<<=2;//高音 Temp_T=65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC); //计算计数器初值 Sound_Temp_TH0=Temp_T/256; Sound_Temp_TL0=Temp_T%256; TH0=Sound_Temp_TH0; TL0=Sound_Temp_TL0+12;//加12是对中断延时的补偿 } SLen=LengthTab[Length%10];//算出是几分音符 XG=Length/10%10;//算出音符类型(0普通1连音2顿音) FD=Length/100; LDiv=LDiv0/SLen;//算出连音音符演奏的长度(多少个10ms) if(FD==1) LDiv=LDiv+LDiv/2; if(XG! =1) if(XG==0)//算出普通音符的演奏长度 if(SLen<=4) LDiv1=LDiv-LDiv4; else LDiv1=LDiv*SOUND_SPACE; else LDiv1=LDiv/2;//算出顿音的演奏长度 else LDiv1=LDiv; if(SL==0)LDiv1=0; LDiv2=LDiv-LDiv1;//算出不发音的长度 if(SL! =0) {TR0=1; for(i=LDiv1;i>0;i--)//发规定长度的音 {while(TF1==0); TH1=Sound_Temp_TH1; TL1=Sound_Temp_TL1; TF1=0; } } if(LDiv2! =0) { TR0=0;BeepIO=0; for(i=LDiv2;i>0;i--)//音符间的间隔 { while(TF1==0); TH1=Sound_Temp_TH1; TL1=Sound_Temp_TL1; TF1=0; } } Point+=2; Tone=Sound[Point]; Length=Sound[Point+1]; } BeepIO=0; } //************************************* #endif #include #include"SoundPlay.h" //downloadby voidDelay1ms(unsignedintcount) { unsignedinti,j; for(i=0;i for(j=0;j<120;j++); } //****************Music**************** //同一首歌 unsignedcharcodeMusic_Same[]={0x0F,0x01,0x15,0x02,0x16,0x02,0x17,0x66,0x18,0x03,0x17,0x02,0x15,0x02,0x16,0x01,0x15,0x02,0x10,0x02,0x15,0x00,0x0F,0x01,0x15,0x02,0x16,0x02,0x17,0x02,0x17,0x03,0x18,0x03,0x19,0x02,0x15,0x02,0x18,0x66,0x17,0x03,0x19,0x02,0x16,0x03,0x17,0x03,0x16,0x00,0x17,0x01,0x19,0x02,0x1B,0x02,0x1B,0x70,0x1A,0x03,0x1A,0x01,0x19,0x02,0x19,0x03,0x1A,0x03,0x1B,0x02,0x1A,0x0D,0x19,0x03,0x17,0x00,0x18,0x66,0x18,0x03,0x19,0x02,0x1A,0x02,0x19,0x0C,0x18,0x0D,0x17,0x03,0x16,0x01,0x11,0x02,0x11,0x03,0x10,0x03,0x0F,0x0C,0x10,0x02,0x15,0x00,0x1F,0x01,0x1A,0x01,0x18,0x66,0x19,0x03,0x1A,0x01,0x1B,0x02,0x1B,0x03,0x1B,0x03,0x1B,0x0C,0x1A,0x0D,0x19,0x03,0x17,0x00,0x1F,0x01,0x1A,0x01,0x18,0x66,0x19,0x03,0x1A,0x01,0x10,0x02,0x10,0x03,0x10,0x03,0x1A,0x0C,0x18,0x0D,0x17,0x03,0x16,0x00,0x0F,0x01,0x15,0x02,0x16,0x02,0x17,0x70,0x18,0x03,0x17,0x02,0x15,0x03,0x15,0x03,0x16,0x66,0x16,0x03,0x16,0x02,0x16,0x03,0x15,0x03,0x10,0x02,0x10,0x01,0x11,0x01,0x11,0x66,0x10,0x03,0x0F,0x0C,0x1A,0x02,0x19,0x02,0x16,0x03,0x16,0x03,0x18,0x66,0x18,0x03,0x18,0x02,0x17,0x03,0x16,0x03,0x19,0x00, 0x00,0x00}; //*************************************** main() { InitialSound(); while (1) { Play(Music_Same,0,3,360); Delay1ms(500); } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 播放 音乐 编程 方法 网络 整理