求: 用51单片机c语言操作使蜂鸣器奏出“祝你生日快乐”音乐的全部程序!

如题所述

#include <reg51.h>
sbit speaker=P1^2;
unsigned char timer0h,timer0l,time;
//生日歌
code unsigned char sszymmh[]={5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4,
5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2,
4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4};
// 音阶频率表 高八位
code unsigned char FREQH[]={
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,
} ;
// 音阶频率表 低八位
code unsigned char FREQL[]={
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,
};
void delay(unsigned char t)
{
unsigned char t1;
unsigned long t2;
for(t1=0;t1<t;t1++)
{
for(t2=0;t2<8000;t2++)
{
;
}
}
TR0=0;
}
void t0int() interrupt 1
{
TR0=0;
speaker=!speaker;
TH0=timer0h;
TL0=timer0l;
TR0=1;
}
void song()
{
TH0=timer0h;
TL0=timer0l;
TR0=1;
delay(time);
}

void main(void)
{
unsigned char k,i;
TMOD=1; //置CT0定时工作方式1
EA=1;
ET0=1;//IE=0x82 //CPU开中断,CT0开中断
while(1)
{
i=0;
while(i<75){ //音乐数组长度 ,唱完从头再来
k=sszymmh[i]+7*sszymmh[i+1]-1;
timer0h=FREQH[k];
timer0l=FREQL[k];
time=sszymmh[i+2];
i=i+3;
song();
}
}
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-01-01
#include <REGX51.H>
unsigned char num1=0;
unsigned char num2=0;
//sbit P34 = P3^4; //定义用来软件复位

//**************************************************************************

#define SYSTEM_OSC 12000000//11059200// //定义晶振频率12000000HZ
#define SOUND_SPACE 4/5 //定义普通音符演奏的长度分率,//每4分音符间隔
//sbit BeepIO = P3^4; //定义输出管脚
sbit BeepIO = P1^5; //定义输出管脚

unsigned int code FreTab[12] = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率表
unsigned char code SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在频率表中的位置
unsigned char code LengthTab[7]= { 1,2,4,8,16,32,64 };
unsigned char code led[8]= { 0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01 };
unsigned char Sound_Temp_TH0,Sound_Temp_TL0; //音符定时器初值暂存
unsigned char Sound_Temp_TH1,Sound_Temp_TL1; //音长定时器初值暂存
//**************************************************************************

//生日快乐
unsigned char code Music_birth[]={ 0x0F,0x03, 0x0F,0x03, 0x10,0x02, 0x0F,0x02, 0x15,0x02,
0x11,0x01, 0x0F,0x02, 0x0F,0x02, 0x10,0x02, 0x0F,0x02,
0x16,0x02, 0x15,0x01, 0x0F,0x03, 0x0F,0x03, 0x19,0x02,
0x17,0x02, 0x15,0x02, 0x11,0x0C, 0x10,0x02, 0x18,0x03,
0x18,0x03, 0x17,0x02, 0x15,0x02, 0x16,0x02, 0x15,0x0B,
0x00,0x00 };

void InitialSound(void)
{
BeepIO = 1;
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; //两个定时器都工作在16位计数/计时器模式
ET0 = 1;
ET1 = 0;
TR0 = 0;
TR1 = 0;
EA = 1;
}

void BeepTimer0(void) interrupt 1 using 1 //音符发生中断
{
BeepIO = !BeepIO;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0;
}
//**************************************************************************
void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
{
unsigned int NewFreTab[12]; //新的频率表
unsigned char i,j,k,l;
unsigned int Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
unsigned char Tone,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;
else if(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 < SoundLength)
{
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是对中断延时的补偿
//音乐彩灯的闪烁
k=l;
k=Temp_T%8;
if(k==l) k=k+2;
P0=led[k];

}
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=1;
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 = 1;
}
//**************************************************************************
void delay() //为了显示的延迟
{
unsigned int j;
// for (i=0;i<50;i++)
for (j=0;j<30;j++);
}

void main()
{
IT0=1; IT1=1; //外部中断下降沿触发
EX0=1;EX1=1;
EA=1; //开总中断

InitialSound();
Play(Music_birth,4,2,300);
}
第2个回答  2011-01-01
参考一下:
http://hi.baidu.com/%D7%F6%B6%F8%C2%DB%B5%C0/blog/item/88bfff323ec42ef21b4cff09.html
-------------------
;生日快乐歌的程序
ORG 0000H
SJMP START
ORG 000BH
LJMP TIM0
;-------------------------------------------
START:
MOV TMOD, #01H
MOV IE, #82H
;-------------------------------------------
START0:
MOV 30H, #0
;-------------------------------------------
GET_TONE:
MOV A, 30H
MOV DPTR, #TAB
MOVC A, @A+DPTR //假设取到82H
MOV R2, A //谱码82H存到R2
JZ END0 //是否取到结束码00H?
ANL A, #0FH //取(低四位)节拍码2
MOV R5, A //节拍码存于R5=2
MOV A, R2
SWAP A
ANL A, #0FH //取(高四位)音符码8
JNZ SING //取到的音符码是否为0
CLR TR0 //是,不发音
D1:
CALL DELAY
INC 30H
JMP GET_TONE
;-------------------------------------------
SING:
DEC A
MOV 22H, A //22H=07H
RL A //A=2*07H
MOV DPTR, #TAB1
MOVC A, @A+DPTR
MOV TH0, A
MOV 21H, A //21h=64898
MOV A, 22H
RL A
INC A
MOVC A, @A+DPTR
MOV TL0, A
MOV 20H, A //20h=64968
SETB TR0
SJMP D1
;-------------------------------------------
END0: CLR TR0
JMP START0
;-------------------------------------------
TIM0:
MOV TL0, 20H
MOV TH0, 21H
CPL P3.7 ;外接扬声器 发音
RETI
;-------------------------------------------
DELAY: MOV R7, #02
D2: MOV R4, #125
D3: MOV R3, #248
DJNZ R3, $
DJNZ R4, D3
DJNZ R7, D2
DJNZ R5, DELAY
RET

TAB1: DW 64260,64400,64524,64580,64684,64777,64820
DW 64898,64968,65030,65058,65110,65157,65178,65217
TAB:
DB 82H,01H,81H,94H,84H,0B4H,0A4H,04H
DB 82H,01H,81H,94H,84H,0C4H,0B4H,04H
DB 82H,01H,81H,0F4H,0D4H,0B4H,0A4H,94H
DB 0E2H,01H,0E1H,0D4H,0B4H,0C4H,0B4H,04H
DB 82H,01H,81H,94H,84H,0B4H,0A4H,04H
DB 82H,01H,81H,94H,84H,0C4H,0B4H,04H
DB 82H,01H,81H,0F4H,0D4H,0B4H,0A4H,94H
DB 0E2H,01H,0E1H,0D4H,0B4H,0C4H,0B4H,04H
DB 00H
END
第3个回答  2011-01-01
是想送给谁吧...
你可以将“祝你生日快乐”这段音乐的音调用不同的频率表示。具体代码我也没有时间写,希望对你有些帮助
相似回答