#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
#ifndef __SOUNDPLAY_H_REVISION_FIRST__
#define __SOUNDPLAY_H_REVISION_FIRST__
#define SYSTEM_OSC 12000000 //定義晶振頻率12000000HZ
#define SOUND_SPACE 4/5 //定義普通音符演奏的長度分率,//每4分音符間隔
uint code FreTab[12] = { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始頻率表
uchar code SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在頻率表中的位置
uchar code LengthTab[7]= { 1,2,4,8,16,32,64 };
uchar Sound_Temp_TH0,Sound_Temp_TL0; //音符定時器初值暫存
uchar Sound_Temp_TH1,Sound_Temp_TL1; //音長定時器初值暫存
uchar shang,slie,slie1,aa,a,kk,n,m;
uint x,y,z;
void key(); // 按鍵檢測
void delay(uint z); //*****************************延時
void init(); //******************************初始化
void hangl();//**************************************************行外圍逐列個亮
void ceng();//***************************************1234層循環(huán)亮
void houqian();//******************************************從后向前
void zuoyou();//****************************************從左向右亮
void shanshuo(); //*****************************全部以200ms的速度閃爍50次,關閉
void rao(); //*************************************環(huán)繞
void InitialSound(void);//*************音樂初始化
void Play(uchar *Sound,uchar Signature,unsigned Octachord,uint Speed);
void Delay1ms(uint count)
{
unsigned int i,j;
for(i=0;i<count;i++)
for(j=0;j<120;j++);
}
uchar code Music_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 };
sbit cai=P3^3; //高電平點亮
sbit yy=P3^4; //蜂鳴器
sbit k1=P3^5; // 按鍵 左
sbit k2=P3^6; //按鍵 中
sbit k3=P3^7; //按鍵 右
//*******************************************行選
uchar code hang[]={
0x00, //全開
0xff,//全關
0x7f,//開底層
0xbf,//開底二
0xdf,//開底三層
0xef,//開最高層
};
//***************************************列選P0
uchar code lie[]={
0xff,//全開
0x00,//全關
};
//****************************************列選P1
uchar code lie1[]={
0xff,//全開
0x00,//全關
};
//--------------------------------------------------------------主程序
void main()
{
init(); //初始化設置
while(1)
{
P0=0xff; P1=0xff; P2=0x00; //全亮
key();
}
}
//====================================各種模塊=================================================
void delay(uint z) //***************************延時
{
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//============================================================================================
void init() //******************************初始化
{
kk=0;
P2=0xff; //關閉行選
P0=0x00; //關閉列選
P1=0x00; //關閉列選
cai=0; //關閉彩燈
}
//=====================================================音樂初始化
void InitialSound(void)
{
yy = 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;
}
//============================================================================================
void shanshuo() //*****************************各種閃爍
{
for(a=0;a<10;a++)
{
P2=hang[0]; //開所有行選
for(slie=0;slie<2;slie++)
{
P0=lie[slie];
P1=lie1[slie];
delay(60);
}
}
P2=0xff; P0=P1=0x00; //全部關閉
for(a=0;a<10;a++)
{
P2=0x00;
P1=0x99; P0=0x99; delay(50);
P2=0xff; P0=0X00;P1=0x00; //全部關閉
delay(50);
}
for(a=0;a<10;a++)
{
P2=0x00;
P1=0x66; P0=0x66; delay(50);
P2=0xff; P0=0X00;P1=0x00; //全部關閉
delay(50);
}
for(a=0;a<10;a++)
{
P2=0x00;
P1=0x55; P0=0x55; delay(50);
P2=0xff; P0=0x00; P1=0x00; //全部關閉
delay(50);
}
for(a=0;a<10;a++)
{
P2=0x00;
P1=0xaa; P0=0xaa; delay(50);
P2=0xff; P0=0x00; P1=0x00; //全部關閉
delay(50);
}
delay(1000);
P2=0x3f;
P0=0x60; P1=0x06; delay(1000);
P2=0x00; P0=0xff; P1=0xff; delay(1000);
}
//============================================================================================
void zuoyou()//****************************************從左向右亮
{
for(a=0;a<8;a++)
{
P2=0x00;
P1=0x11; P0=0x11; delay(50);
P1=0x22; P0=0x22; delay(50);
P1=0x44; P0=0x44; delay(50);
P1=0x88; P0=0x88; delay(50);
P2=0xff; P0=0x00; P1=0x00; //全部關閉
delay(50);
}
}
//============================================================================================
void houqian()//******************************************從后向前
{
for(a=0;a<8;a++)
{
P2=0x00;
P0=0x0f; delay(50);
P0=0xf0; delay(50); P0=0x00;
P1=0x0f; delay(50);
P1=0xf0; delay(50);
P2=0xff; P0=0x00; P1=0x00; //全部關閉
delay(400);
}
}
//============================================================================================
void ceng()//***************************************1234層循環(huán)亮
{
for(a=0;a<15;a++)
{
P0=0xff;P1=0xff;
P2=0x7f; delay(50);
P2=0xbf; delay(50);
P2=0xdf; delay(50);
P2=0xef; delay(150);
P2=0xdf; delay(50);
P2=0xbf; delay(50);
P2=0xff; P0=P1=0x00; //全部關閉
}
}
void hangl()//**************************************************行外圍逐個亮
{
for(a=0;a<8;a++)
{
P0=0x88; P1=0x88;
P2=0xef; delay(50);
P2=0xdf; delay(50);
P2=0xbf; delay(50);
P2=0x7f; delay(50);
P0=0x44; P1=0x44; delay(50);
P0=0x22; P1=0x22; delay(50);
P0=0x11; P1=0x11; delay(50);
P2=0xbf; delay(50);
P2=0xdf; delay(50);
P2=0xef;
P0=0x11; P1=0x11; delay(50);
P0=0x22; P1=0x22; delay(50);
P0=0x44; P1=0x44; delay(50);
} P2=0xff; P0=P1=0x00; //全部關閉
}
void rao()
{ P2=0xff; P0=P1=0x00; //全部關閉
//-----------------------------------------------------------------------------------------
P2=0x7f; P1=0xf0; delay(200);
P2=0x3f; delay(200);
P2=0x1f; delay(200);
P2=0x0f; delay(800);
P1=0x70; delay(200);
P1=0xb0; delay(200);
P1=0xd0; delay(200);
P1=0xe0; delay(200); P1=0X00;
for(a=0;a<4;a++)
{
P1=0x71; delay(100);
P1=0x31; P0=0x10; delay(100);
P1=0x11; P0=0x11; delay(100);
P1=0x01; P0=0x13; delay(100);
P1=0X00; P0=0x17; delay(100);
P0=0x0f; delay(100);
P0=0x8e; delay(100);
P1=0x08; P0=0x46; delay(100);
P1=0x88; P0=0x88; delay(100);
P1=0xc8; P0=0x80; delay(100);
P1=0xe8; P0=0X00; delay(100);
P1=0xf0; delay(100);
}
P1=0x70; delay(200);
P1=0x30; delay(200);
for(a=0;a<4;a++)
{
P1=0x10; delay(200); P1=0X00; delay(200);
} P1=0x10;
P2=0x1f; delay(200);
P2=0x3f; delay(200);
P2=0x7f; delay(500);
P2=0Xff;P0=0X00;P1=0X00;
}
//============================================================================================
void key() //***********************************按鍵檢測
{
if(k1==0) //********************左鍵
{ if(kk==6)
{kk=0;}
delay(10);
if(k1==0)
{
while(!k1);
if(kk==1)
{shanshuo();} //全部以200ms的速度閃爍
if(kk==2)
{hangl();} //行外圍逐列個亮
if(kk==5)
{houqian();} // 從后向前
if(kk==3)
{zuoyou();} // 從左向右亮
if(kk==4)
{ceng();} // 1234層循環(huán)亮
if(kk==0)
{rao();}
}
kk++;
}
if(k3==0) //***************************右鍵
{
delay(10);
if(k3==0)
{ while(!k3);
cai=~cai;
}
}
if(k2==0) //***************************中鍵
{
delay(10);
if(k2==0)
{
while(!k2);
InitialSound();
Play(Music_Same,0,3,360);
Delay1ms(500);
// P0=0x00;
}
}
}
void BeepTimer0(void) interrupt 1 //音符發(fā)生中斷
{
yy = !yy;
TH0 = Sound_Temp_TH0;
TL0 = Sound_Temp_TL0;
}
void Play(uchar *Sound,uchar Signature,unsigned Octachord,uint Speed)
{
uint NewFreTab[12]; //新的頻率表
uchar i,j;
uint Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
uchar Tone,Length,SL,SH,SM,SLen,XG,FD;
for(i=0;i<12;i++) // 根據(jù)調(diào)號及升降八度來生成新的頻率表
{
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);//計算計數(shù)器初值
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; //算出不發(fā)音的長度
if (SL!=0)
{
TR0=1;
for(i=LDiv1;i>0;i--) //發(fā)規(guī)定長度的音
{
while(TF1==0);
TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TF1=0;
}
}
if(LDiv2!=0)
{
TR0=0; yy=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];
}
yy = 0;
}
|