#ifndef _MAIN_H_
#define _MAIN_H_
#define ledDB P0 //led顯示端口
#define thesongMAX 8 //總計X首歌
#include<reg52.h>
/********************************************
定義各口
*********************************************/
sbit BUZZ = P2^0; //蜂鳴器連續的IO口
sbit led0 = P0^0; //各LED小燈
sbit led1 = P0^1;
sbit led2 = P0^2;
sbit led3 = P0^3;
sbit led4 = P0^4;
sbit led5 = P0^5;
sbit led6 = P0^6;
sbit led7 = P0^7;
sbit ledF = P3^7; //功能指示燈(處于演奏狀態時亮
sbit key0 = P1^0; //各按鍵
sbit key1 = P1^1;
sbit key2 = P1^2;
sbit key3 = P1^3;
sbit key4 = P1^4;
sbit key5 = P1^5;
sbit key6 = P1^6;
sbit key7 = P1^7;
sbit keyF = P3^2; //功能切換鍵——外中斷0端口
/********************************************
頻率初值表
*********************************************/
unsigned char code chuzhi[]={
0xFF,0xFF, // low mid high
0xFC,0x44, //1 ## 5 6 7 1 2 3 4 5 6 7 1 2 3
0xFC,0xAC, //2 ## D C B 1 2 3 4 5 6 7 8 9 A
0xFD,0x09, //3
0xFD,0x34, //4
0xFD,0x82, //5
0xFD,0xC8, //6
0xFE,0x06, //7
0xFE,0x22, //8 --high 1 N = 470;
0xFE,0x56, //9 --hign 2 N = 440;
0xFE,0x85, //A --hign 3 N = 410;
0xFC,0x0C, //B---low 7 N = 1012
0xFB,0x90, //C --low 6
0xFB,0x04, //D --low 5
0xFA,0x15 //E --low 3
};
unsigned char T0TH = 0; //T0定時器重載值,用以控制頻率
unsigned char T0TL = 0;
bit func = 0; //功能模式:0-彈奏;1-播放
int yinma = 0; //音碼,高4為音調,低4為節拍
char thesong = 0; //正在播放的曲子
void LedShowJiePai();
void InitSys();
void Delay1ms(int cnt);
#endif
#ifndef _MUSIC_H_
#define _MUSIC_H_
//高4位為音調,低四位為節拍
/********************************************
歌曲(C調)
*********************************************/
unsigned char code song0[]={ //兩只老虎
0x08,0x14,0x24,0x34,0x14,0x14,0x24,0x34,0x14,
0x34,0x44,0x58,0x34,0x44,0x58,
0x53,0x61,0x53,0x41,0x34,0x14,
0x53,0x61,0x53,0x41,0x34,0x14, //16--1
0x14,0x54,0x18, //8 --2
0x14,0x54,0x18, //4 --4
0xFF //歌曲結束標志
};
unsigned char code song1[]={ //送別
0x08,0x54,0x32,0x52,0x88,0x64,0x84,0x58,
0x54,0x12,0x22,0x34,0x22,0x12,0x28,0x04,0x04,
0x54,0x32,0x52,0x86,0x72,0x64,0x84,0x58,
0x54,0x22,0x32,0x46,0xB2,0x18,0x04,0x04,
0x64,0x84,0x88,0x74,0x62,0x72,0x88,
0x62,0x72,0x82,0x62,0x62,0x52,0x32,0x12,0x28,0x04,0x04,
0x54,0x32,0x52,0x86,0x72,0x64,0x84,0x58,
0x54,0x22,0x32,0x46,0xB2,0x18,0x04,0x04,
0xFF
};
unsigned char code song2[]={ //數鴨子
0x08,0x34,0x14,0x32,0x32,0x14,0x32,0x32,0x52,0x62,0x54,0x04,
0x62,0x62,0x62,0x52,0x42,0x42,0x44,
0x22,0x32,0x22,0x12,0x22,0x04,
0x34,0x12,0x02,0x34,0x12,0x02,0x32,0x32,0x52,0x62,0x64,0x04,
0x84,0x52,0x52,0x64,0x34,0x22,0x12,0x22,0x32,0x58,
0x84,0x52,0x52,0x64,0x34,0x22,0x12,0x22,0x32,0x18, //第二遍
0xFF
};
unsigned char code song3[]={ //喜歡你
0x08,0x23,0x21,0x22,0x32,0x22,0x12,0xd2,0x12,0x12,0xb4,0xc1,0xe1,0xe6,0x02,
0x23,0x21,0x22,0x32,0x22,0x12,0xd2,0x12,0x12,0xb4,0x11,0xb1,0xc4,
0xc2,0x12,0x32,0x22,0x22,0x11,0x21,0x24,0xc2,0x12,0x32,0x22,0x22,0x12,0x28,
0x04,0x23,0x21,0x22,0x32,0x22,0x12,0xd2,0x12,0x12,0xb4,0xc1,0xe1,0xe6,0x02, //secondly
0x23,0x21,0x22,0x32,0x22,0x12,0xd2,0x12,0x12,0xb4,0x11,0xb1,0xc4,
0xc2,0x12,0x32,0x22,0x22,0x11,0x21,0x24,0xc2,0x12,0x32,0x22,0x22,0x12,0x28,
0x04,0x34,0x31,0x21,0x12,0x18,0x12,0x22,0x12,0xB2,0xC8, //high up
0x12,0x22,0x12,0xB2,0xC8,0xB4,0x14,0x28,0x34,0X31,0x21,0x12,0x18,0x12,0x22,0x12,0xB2,0xC8,
0x12,0x22,0x12,0xB2,0xC8,0xB4,0x14,0x28,0x14,0xB4,0x1B,0X04,
0xFF
};
unsigned char code song4[]={ //哈巴狗
0x08,0x12,0x12,0x12,0x22,0x38,
0x32,0x32,0x32,0x42,0x58,
0x62,0x62,0x52,0x42,0x38,
0x52,0x52,0x22,0x32,0x18,
0XFF
};
unsigned char code song5[]={ //幸福拍手歌
0x08,0XD3,0XD1,0X13,0X11,0X13,0X11,0X13,0X11,0XB3,0X11,0X24,0XA3,0X01,0XA3,0X01,
0XD3,0XD1,0X23,0X21,0X23,0X21,0X23,0X21,0X13,0X21,0X34,0XA3,0X01,0XA3,0X01,
0X33,0X31,0X33,0X31,0X34,0X23,0X31,0X44,0X33,0X21,0X14,0XB3,0X11,
0X24,0X23,0X11,0XB3,0XD1,0XC3,0XB1,0X14,0XA3,0X01,0XA3,0X01,
0X04,0XD3,0XD1,0X13,0X11,0X13,0X11,0X13,0X11,0XB3,0X11,0X24,0XA3,0X01,0XA3,0X01,
0XD3,0XD1,0X23,0X21,0X23,0X21,0X23,0X21,0X13,0X21,0X34,0XA3,0X01,0XA3,0X01,
0X33,0X31,0X33,0X31,0X34,0X23,0X31,0X44,0X33,0X21,0X14,0XB3,0X11,
0X24,0X23,0X11,0XB3,0XD1,0XC3,0XB1,0X14,0XA3,0X01,0XA3,0X01,
0XFF
};
unsigned char code song6[]={ //龍的傳人
0x08,0X64,0X72,0X82,0X94,0XA2,0X92,0X84,0X82,0X72,0X68,
0X64,0X72,0X82,0X94,0XA2,0X92,0X82,0X72,0X82,0X92,0XA8,
0X64,0X72,0X82,0X94,0XA2,0X92,0X82,0X72,0X82,0X72,0X68,
0X74,0X74,0X72,0X84,0X72,0X64,0X62,0X52,0X68,
0XA4,0XA4,0XA4,0X92,0X82,0X94,0X92,0XA2,0X98,
0X84,0X84,0X84,0X92,0X82,0X74,0X72,0X82,0X78,
0XA4,0XA4,0XA2,0XA2,0X92,0X82,0X94,0X92,0XA2,0X98,
0X84,0X84,0X72,0X84,0X72,0X64,0X62,0X52,0X68, //secondly
0X04,0X64,0X72,0X82,0X94,0XA2,0X92,0X84,0X82,0X72,0X68,
0X64,0X72,0X82,0X94,0XA2,0X92,0X82,0X72,0X82,0X92,0XA8,
0X64,0X72,0X82,0X94,0XA2,0X92,0X82,0X72,0X82,0X72,0X68,
0X74,0X74,0X72,0X84,0X72,0X64,0X62,0X52,0X68,
0XA4,0XA4,0XA4,0X92,0X82,0X94,0X92,0XA2,0X98,
0X84,0X84,0X84,0X92,0X82,0X74,0X72,0X82,0X78,
0XA4,0XA4,0XA2,0XA2,0X92,0X82,0X94,0X92,0XA2,0X98,
0X84,0X84,0X72,0X84,0X72,0X64,0X62,0X52,0X68,
0XFF
};
unsigned char code song7[]={ //上學歌
0x08,0x12,0x22,0x32,0x12,0x58,0x62,0x62,0x82,0x62,0x58,
0x62,0x62,0x84,0x52,0x62,0x34,
0x62,0x52,0x32,0x52,0x32,0x12,0x22,0x32,0x18, //secondly
0x04,0x12,0x22,0x32,0x12,0x58,0x62,0x62,0x82,0x62,0x58,
0x62,0x62,0x84,0x52,0x62,0x34,
0x62,0x52,0x32,0x52,0x32,0x12,0x22,0x32,0x18,
0XFF
};
unsigned char code song8[]={ //一分錢
0x08,0x54,0x84,0x62,0x82,0x54,0x32,0x52,0x22,0x32,0x54,0x04,
0x32,0x52,0x62,0x82,0x52,0x62,0x52,0x32,0x52,0x14,0x32,0x24,0x04,
0x32,0x22,0x12,0x22,0x38,0x62,0x52,0x32,0x52,0x64,0x04,
0x52,0x82,0x62,0x52,0x32,0x52,0x24,0x52,0x22,0x32,0x22,0x18,
0xFF
};
#endif
#ifndef _PLAYING_H_
#define _PLAYING_h_
void Playing() //彈奏
{
unsigned char keynum = 0; //按鍵碼
while(func == 0)
{
if(key0 == 0)
{
keynum = 1;
led0 = 0;
}
else if(key1 == 0)
{
keynum = 2;
led1 = 0;
}
else if(key2 == 0)
{
keynum = 3;
led2 = 0;
}
else if(key3 == 0)
{
led3 = 0;
keynum = 4;
}
else if(key4 == 0)
{
led4 = 0;
keynum = 5;
}
else if(key5 == 0)
{
led5 = 0;
keynum = 6;
}
else if(key6 == 0)
{
led6 = 0;
keynum = 7;
}
else if(key7 == 0)
{
led7 = 0;
keynum = 8;
}
else //包含沒有鍵按下的情況
{
keynum = 88;
ledDB = 0xFF;
}
if((keynum>=0)&&(keynum<=8)) //為有效琴鍵
{
T0TH = chuzhi[keynum*2];
T0TL = chuzhi[keynum*2+1];
TR0 = 1;
ET1 = 0;
Delay1ms(300);
ET1 = 1;
ledDB = 0xFF;
}
else
{
TR0 = 0;
ledDB = 0xFF;
}
}
}
void Delay1ms(int cnt) //延時1ms,12T,11059200Hz
{
unsigned int i = 0;
for( ; cnt>0; cnt--)
for(i=0; i<123; i++);
}
void Delay125ms(unsigned char x) //延時125MS,即十六分音符
{
unsigned int i, j;
for( ; x>0; x--)
{
for(i=0; i<120; i++)
{
for(j=0; j<123; j++);
if((key6==0)||(key7==0)||keyF==0) //如果在延時過程中有鍵按下
{
TR0 = 0;
ET1 = 1; //馬上打開定時器1,掃描按鍵
}
}
}
}
// 開機流水燈
void StartLedShow()
{
unsigned int ledshow = 0x01;
unsigned int stop = 0;
bit dirt = 0; //方向
unsigned int n = 0; //延時時長控制
unsigned int ledchar[] = {
0x81, 0xC3, 0xE7, 0xFF,
0xFF, 0xE7, 0xC3, 0x81
};
while(!stop)
{
ledDB = ~ledshow;
Delay1ms(n);
if(dirt == 0) //流水燈效果
{
ledshow <<= 1;
if(ledshow == 0x80)
dirt = 1;
}
else
{
ledshow >>= 1;
if(ledshow == 0x01)
dirt = 0;
}
n += 2;
if((n>100)&&(ledshow==0x01))
stop = 1;
}
for(n=0;n<8;n++)
{
ledDB = ~ledchar[n];
Delay125ms(1);
}
ledDB = 0xFF;
}
#endif
#ifndef _SINGING_H_
#define _SINGING_H_
void Singing() //播放
{
int jiepai = 0; //節拍
unsigned char yindiao = 0; //音調
unsigned char yinmatemp = 0; //要處理的音碼
while(func == 1) //循環播放
{
switch(thesong)
{
case 0: yinmatemp = song0[yinma]; break;
case 1: yinmatemp = song1[yinma]; break;
case 2: yinmatemp = song2[yinma]; break;
case 3: yinmatemp = song3[yinma]; break;
case 4: yinmatemp = song4[yinma]; break;
case 5: yinmatemp = song5[yinma]; break;
case 6: yinmatemp = song6[yinma]; break;
case 7: yinmatemp = song7[yinma]; break;
case 8: yinmatemp = song8[yinma]; break;
default: break;
}
if(yinmatemp != 0xFF) //不是歌曲結尾
{
yindiao = yinmatemp >> 4; //取高四位,音調
if(yindiao != 0) //不是休止符
{
T0TH = chuzhi[yindiao*2];
T0TL = chuzhi[yindiao*2+1];
TR0 = 1;
LedShowJiePai();
}
else //是休止符
{
TR0 = 0;
ledDB = 0xFF;
}
jiepai = yinmatemp & 0x0F; //取低四位,節拍
ET1 = 0;
Delay125ms(jiepai);
ET1 = 1;
TR0 = 0;
Delay1ms(10);
yinma++;
}
else //是歌曲結尾
{
TR0 = 0;
Delay1ms(1000);
yinma = 0;
thesong++;
if(thesong > thesongMAX)
thesong = 0;
}
}
TR0 = 0;
}
void LedShowJiePai() //LED流水燈顯示節拍
{
static unsigned char ledshow = 0x01; //顯示值
static char dirt = 0; //方向
ledDB = ~ledshow;
if(dirt != 0)
{
ledshow >>= 1;
if(ledshow == 0x01)
dirt = 0;
}
else
{
ledshow <<= 1;
if(ledshow == 0x80)
dirt = 1;
}
}
#endif
void main()
{
InitSys();
StartLedShow();
while(1)
{
if(func != 0)
Singing();
else
Playing();
}
}
void InitSys()
{
TMOD = 0x11; //T0和T1都打開,T0控制頻率,T1作按鍵掃描
TH0 = 0xFC;
TL0 = 0x66; //定時1ms
ET0 = 1;
TR0 = 0; //暫不啟動
TH1 = 0xFC;
TL1 = 0x66;
ET1 = 1;
TR1 = 1; //馬上啟動
EA = 1;
ledF = func; //當前模式顯示燈
}
void T0_interr() interrupt 1
{
TH0 = T0TH;
TL0 = T0TL;
BUZZ =~BUZZ;
}
void T1_interr() interrupt 3 //用作按鍵掃描
{
static unsigned char keytemp[] = {0xFF, 0xFF, 0xFF};
static unsigned char staBF[] = {1, 1, 1};
static char keysta[] = {0, 0, 0};
char flagKey = 0; //按鍵值
unsigned char i = 0;
TH1 = 0xFC;
TL1 = 0x66;
keytemp[0] = (keytemp[0] << 1) | keyF;
if(keytemp[0] == 0x00) //作模式切換鍵
{
keysta[0] = 0;
}
else
keysta[0] = 1;
if(keysta[0] != staBF[0])
{
if(staBF[0] == 1)
{
EA = 0; //暫時關閉中斷
func = ~func;
ledF = func;
if(func == 1) //如果進入播放模式
yinma = 0; //音碼值歸0
EA = 1;
}
staBF[0] = keysta[0];
}
if(func == 1) //如果是在播放模式下,才有上一曲和下一曲
{
keytemp[1] = (keytemp[1] << 1) | key6; //作上一曲
keytemp[2] = (keytemp[2] << 1) | key7; //作下一曲
for(i=1; i<3; i++)
{
if(keytemp[i] == 0x00)
keysta[i] = 0;
else
keysta[i] = 1;
}
for(i=1; i<3; i++)
{
if(keysta[i] != staBF[i])
{
if(staBF[i] == 1)
{
flagKey = i;
}
staBF[i] = keysta[i];
}
}
if(flagKey != 0) //有按鍵動作
{
EA = 0;
yinma = 0;
if(flagKey == 2) //下一曲
{
thesong++;
if(thesong > thesongMAX)
thesong = 0;
}
else //上一曲
{
thesong--;
if(thesong < 0)
thesong = thesongMAX;
}
flagKey = 0; //按鍵值歸0
Delay1ms(500);
EA = 1;
}
}
} |