⑴ 這是一個利用89C52RC單片機蜂鳴器演奏生日快樂歌。請高手幫我解釋一下:整體思想,再在每一步添加註釋。
#include<reg51.h>
sbit speaker=P1^6;
unsigned char timer0h,timer0l,time;
//生日歌,這三個位元組一組,分別定義:旋律(1234567)、高低音(低音、中音、高音)、節奏(長度)
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 //定時器0中斷服務程序,控制聲音打頻率
{ TR0=0;
speaker=!speaker;
TH0=timer0h;
TL0=timer0l;
TR0=1;
}
void song() //啟動演奏當前頻率
{ TH0=timer0h; //當前頻率的高八位
TL0=timer0l; //當前頻率的低八位
TR0=1; //啟動定時器0
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(); //演奏當前頻率,共75/3,25個曲調。
}
}
}
//程序的設計思路就是將一首樂曲分成三個變數來控制,分別是曲調、所在音區、時長。而控制曲調的因素也就是頻率又分成高八位和第八位兩個表,每演奏一個曲調,就根據該曲調的三個變數來取值。
⑵ 求: 用51單片機c語言操作使蜂鳴器奏出「祝你生日快樂」音樂的全部程序!
#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);
}
⑶ 單片機怎麼實現演奏兩首歌(生日快樂+兩只老虎) 匯編語言
;音樂生日快樂的播放
numtim equ 20h
EQUei equ 21h
EQUwei equ 22h
EQUnled equ 23h
EQU 000hORGp startJMPg 00bh
jORGtim0
oJMP100h
ORGart:; JB P3.7,$ ;檢測播放按鍵是否按下
mov tmod,#00000001b
MOV mov ie,#10000010b
MOV mov numtim,#01h
startMOVov 30h,#00h
nextMOVv a,30h
mov MOVr,#table
MOVovc a,@a+dptr
mov r2,a
jz eMOV
anl aJZ0fh
mov r5,a
mov aMOV
swap MOV anl a,#0fh
jnz sing
clr tJNZ
jmp d1
sing: dec aJMP mov 22h,DEC rl aMOV mov dptr,#table1
MOVmovc a,@a+dptr
mov th0,a
mov MOV,a
mov MOV2h
rl aMOV inc a
movc a,@INCptr
mov tl0,a
mov MOV,a
setbMOV0
d1:lcall delay
inc 30h
jmp neINC
end0:clr JMP
jmp start0
tim0:puJMPacc
pushPUSH
mov PUSH2PSW
MOV th0,21h
MOV p1.6 ;由該口輸出音頻數據
pop psw
pop acc
POPrPSW
dPOPy: mov r7,#02h
d2: mov r4,#1MOV
d3: mov r3,#MOV
djnz r3,MOV djnz r4,d3
djnz r7,d2
djnz r5,delay
ret
table1: RET ;音樂碼表
dw 64260,64400,64524,64580
DW dw 64684,64777,64820,64898
DW dw 64968,65030,65058,65110
DW dw 65157,65178,65217
table:dDW82h,01h,81h,94h,84h
DB 0b4h,0a4h,04h
db 82hDB1h,81h,94h,84h
DB 0c4h,0b4h,04h
db 8DB,01h,81h,0f4h,0d4h
DBdb 0b4h,0a4h,94h
db 0e2DB01h,0e1h,0d4h,0b4h
DB db 0c4h,0b4h,04h
db 8DB,01h,81h,94h,84h
DB 0b4h,0a4h,04h
db 82hDB1h,81h,94h,84h
DB 0c4h,0b4h,04h
db 8DB,01h,81h,0f4h,0d4h
DBdb 0b4h,0a4h,94h
db 0e2DB01h,0e1h,0d4h,0b4h
DB db 0c4h,0b4h,04h
db 00DB
TABLE2:DB 0C0H,0F9H,DB4H,0B0H,99H,92H,8DB,0F8H,80H,90H
end
END
我只有生日快樂的程序,希望對你有幫助,從我這個程序你了解了原理,你就可以隨意搞了,玩熟悉了就簡單了!
⑷ 51單片機寫音樂的一個程序,求詳解,以下是程序。
SONG_TONE[i]/3
產生一個短延時,延時的時間正好是音符的頻率
延時時間越短產生的頻率就越高,發出的聲音也越高
SONG_LONG[i]*20
是用於音符的持續時間。
就相當於長按跟短按一個按鍵一樣
⑸ 求單片機LED燈閃爍生日快樂代碼。謝謝
生日快樂歌曲C代碼
/*******************************************/
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit beep = P1^5;
uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159,
212,212,106,126,159,169,190,119,119,126,159,142,159,0};
uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,
9,3,12,12,12,12,12,9,3,12,12,12,24,0};
//延時
void DelayMS(uint x)
{
uchar t;
while(x--) for(t=0;t<120;t++);
}
void PlayMusic()
{
uint i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{ //播放各個音符,SONG_LONG 為拍子長度
for(j=0;j<SONG_LONG[i]*20;j++)
{
beep=~beep;
//SONG_TONE 延時表決定了每個音符的頻率
for(k=0;k<SONG_TONE[i]/3;k++);
}
DelayMS(10);
i++;
}
}
void main()
{
beep=0;
while(1)
{
PlayMusic(); //播放生日快樂
DelayMS(500); //播放完後暫停一段時間
}
}
⑹ 跪求一個單片機生日快樂歌C語言程序.
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit BEEP=P1^2;//接喇叭或蜂鳴器的介面
uint h,i;
uint hz;
uchar jiep;
bit flag;
uint code fre[]={ 64400,64524,64580,64684,64777,64820,64898,64968,65030,65058,65110,65157,65178,65217};
uchar code song[]={6,9, 6,3, 7,12, 6,12, 9,12, 8,24, 6,9, 6,3, 7,12,
6,12, 10,12, 9,24, 6,9, 6,3, 13,12, 11,12, 8,12, 7,12,
12,9, 12,3, 11,12, 9,12, 10,12, 9,24}; //歌譜 2個一組(0,0)(音調,節拍)
void init () //初始化
{
EA=1;
TMOD=0x11;
ET0=1;
ET1=1;
i=0;
flag=1;
}
void sing()
{
if(flag==1)
{
h=song[i];
jiep=song[i+1];
i=i+2;
if(i>46) i=0;
hz=fre[h];
TH0=(hz)/256;
TL0=(hz)%256;
flag=0;
TR0=1;
TR1=1;
}
}
void main()
{
init();
while(1)
{
sing();
}
}
void time0() interrupt 1 //定時器0
{
TH0=(hz)/256;
TL0=(hz)%256;
if(!flag) BEEP=!BEEP;
else TR0=0;
}
void time1() interrupt 3
{
TH1=(15536)/256;
TL1=(15536)%256;
--jiep;
if(jiep==0)
flag=1;
}