#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define allsong 4 //歌曲總數 按實際寫
sbit P1_0 = P1^0;
sbit P1_1 = P1^1;
sbit P1_2 = P1^2;
sbit P1_3 = P1^3;
sbit P1_4 = P1^4;
sbit P1_5 = P1^5;
sbit P1_6 = P1^6;
sbit P1_7 = P1^7;
sbit beep = P3^0;
sbit key_play = P3^1;
uchar x = 0; /*矩陣鍵盤橫坐標 從1開始 0為未按下的標志 */
uchar y = 0; /*矩陣鍵盤縱坐標 從1開始 0為未按下的標志 */
uchar flash = 0; //控制led燈顯示 的變量 */
uchar f_l; /*按鍵發出音調的初值(低位)*/
uchar f_h; //高位
uchar song_l; /*歌曲音調的初值(低位)*/
uchar song_h; //高位
uchar out = 0; /*聲音輸出變量 1表示有輸出 0表示無輸出 */
uchar yindiao; /*音調 定義為全局變量 為了在播放時數碼管能顯示當前音調*/
uchar yindiao_h; //音調的高四位
uchar yindiao_l; //音調的低四位
uchar jiepai; /*節拍(簡而言之就是一個音調響的時間長度)*/
uchar song_id = 1; //歌曲序號變量
uchar temp_id = 1; //歌曲臨時序號
uint which = 2; /*簡譜表里的第幾個音 從第2個開始 第0個用來存曲速,第1個占位*/
uchar same = 0; /*在暫停時選了同一首歌曲,用于跳出暫停循環*/
uchar key_x(); //獲取鍵盤橫坐標 函數
uchar key_y(); //獲取鍵盤縱坐標 函數
void play(); //播放歌曲 函數
void delayms(uint ms);//延時xx ms 函數
void delay(uint pai);//節拍延時 函數
void key_check(); //檢查按鍵狀態 函數
void display(); //數碼管顯示對應音調 函數
void speak(); /*按鍵后 給定時器0賦對應音調的初值 從而發出聲音*/
uchar choose(); /*播放狀態下 選歌函數 釋放按鍵后才跳出函數,返回歌曲序號*/
uchar choose2(); /*暫停狀態下 選歌函數 不用釋放按鍵即可跳出函數,返回歌曲序號 */
void play(); //播放歌曲 函數
uchar code num[]={0x00, //數碼管段選碼
0x77,0x7c,0x39,0x5e,0x79,0x71,0x3d, //a - g
0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, //1 - 7
0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87 //1. - 7.
};
uchar code led_table[]={0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01,0x00};/*發光二極管閃爍表*/
uchar code chuzhi[]={ //音調對應的計數初值
0xff,0xff,//占0位
0xf8,0x8c,//低1 (0x01) a -數碼管顯示方式
0xf9,0x5b,// 2 b
0xfa,0x15,// 3 c
0xfa,0x67,// 4 d
0xfb,0x04,// 5 e
0xfb,0x90,// 6 f
0xfc,0x0c,//低7(0x07)g
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /*占位 0x08 - 0x0b (8 - 11)*/
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,/*占位 0x0c - 0x10 (12 - 16)*/
0xfc,0x44,//中1 (0x11) (17)
0xfc,0xac,// 2
0xfd,0x09,// 3
0xfd,0x34,// 4
0xfd,0x82,// 5
0xfd,0xc8,// 6
0xfe,0x06,//中7 (0x17) (23)
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /*占位 0x18 - 0x1b (24 - 27)*/
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /*占位 0x1c - 0x20 (28 - 32)*/
0xfe,0x22,//高1 (0x21)1. (33)
0xfe,0x56,// 2 2.
0xfe,0x85,// 3 3.
0xfe,0x9a,// 4 4.
0xfe,0xc1,// 5 5.
0xfe,0xe4,// 6 6.
0xff,0x03 //高7 (0x27)7. (39)
};
uchar code ymt[]={//玉滿堂
0x96,0x00, //曲速 0x96表示 150拍/分
0x00,0x0a,0x05,0x02,0x15,0x02,0x12,0x02,
0x13,0x04,0x13,0x02,0x15,0x02,0x12,0x04,0x12,0x02,0x13,0x02,
0x12,0x10,
0x13,0x04,0x13,0x02,0x12,0x02,0x13,0x04,0x15,0x02,0x16,0x02,
0x15,0x0c,0x13,0x02,0x15,0x02,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x04,0x15,0x02,0x13,0x02,
0x15,0x0c,0x15,0x02,0x16,0x02,
0x21,0x04,0x21,0x02,0x22,0x02,0x23,0x04,0x22,0x02,0x21,0x02,
0x22,0x10,
0x23,0x08,0x15,0x02,0x16,0x02,0x21,0x02,0x22,0x02,
0x23,0x04,0x23,0x02,0x22,0x02,0x21,0x06,0x21,0x02,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x04,0x13,0x04,
0x15,0x10,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x04,0x21,0x02,0x22,0x02,
0x23,0x04,0x23,0x02,0x22,0x02,0x21,0x06,0x21,0x02,
0x16,0x02,0x21,0x02,0x16,0x02,0x21,0x02,0x22,0x02,0x23,0x02,0x25,0x02,0x23,0x02,
0x22,0x0c,0x21,0x02,0x22,0x02,
0x23,0x06,0x15,0x02,0x16,0x02,0x21,0x02,0x22,0x02,
0x23,0x04,0x23,0x02,0x22,0x02,0x21,0x06,0x21,0x02,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x02,0x21,0x02,0x15,0x02,0x13,0x02,
0x15,0x0c,0x13,0x02,0x15,0x02,
0x16,0x04,0x16,0x02,0x21,0x02,0x16,0x04,0x16,0x02,0x21,0x02,
0x22,0x04,0x22,0x02,0x23,0x02,0x22,0x04,0x22,0x02,0x23,0x02,
0x25,0x02,0x26,0x02,0x23,0x02,0x25,0x02,0x22,0x02,0x23,0x02,0x21,0x02,0x16,0x02,
0x21,0x10,
0xff
};
uchar code dl[]={ //蝶戀
0x82,0x00, //曲速 0x82表示 130拍/分
0x13,0x04,0x13,0x04,0x13,0x04,0x12,0x04,0x13,0x08,
0x12,0x04,0x13,0x04,0x12,0x04,0x12,0x04,0x06,0x08,
0x06,0x04,0x07,0x04,0x11,0x08,0x12,0x04,0x11,0x04,0x07,0x08,0x06,0x04,0x05,0x04,0x06,0x0f,
0x13,0x04,0x13,0x04,0x13,0x04,0x12,0x04,0x13,0x0c,
0x16,0x04,0x15,0x04,0x16,0x04,0x15,0x04,0x15,0x04,0x12,0x04,
0x12,0x04,0x13,0x04,0x14,0x08,0x15,0x04,0x14,0x04,0x13,0x04,0x12,0x04,0x11,0x04,0x13,0x0f,0x13,0x0c,
0x13,0x04,0x16,0x08,0x17,0x04,0x16,0x04,0x15,0x0c,0x13,0x04,0x15,0x0f,
0x13,0x04,0x15,0x04,0x12,0x08,0x16,0x04,0x15,0x04,0x13,0x08,0x12,0x04,0x12,0x04,0x13,0x0c,
0x12,0x08,0x16,0x04,0x16,0x0c,
0x11,0x08,0x16,0x04,0x16,0x08,
0x16,0x04,0x17,0x04,0x21,0x08,0x17,0x04,0x16,0x04,0x17,0x08,0x16,0x04,0x17,0x04,0x13,0x08,0x13,0x0c,
0x13,0x04,0x16,0x08,0x17,0x08,0x16,0x04,0x15,0x0c,0x13,0x04,0x15,0x0f,
0x14,0x04,0x15,0x04,0x16,0x08,0x17,0x04,0x16,0x04,0x17,0x08,
0x16,0x04,0x17,0x04,0x13,0x0f,0x13,0x0f,
0x12,0x08,0x16,0x04,0x16,0x02,0x16,0x0f,
0x11,0x04,0x16,0x04,0x16,0x02,0x16,0x08,
0x16,0x04,0x17,0x04,0x21,0x08,0x17,0x04,0x16,0x04,0x17,0x08,0x15,0x08,0x16,0x0f,
0x23,0x04,0x22,0x04,0x22,0x04,0x21,0x04,0x21,0x04,0x17,0x04,0x17,0x04,0x16,0x04,
0x21,0x04,0x17,0x04,0x17,0x04,0x16,0x04,0x16,0x04,0x15,0x04,0x15,0x04,0x14,0x04,
0x16,0x04,0x15,0x04,0x15,0x04,0x14,0x04,0x14,0x04,0x13,0x04,0x13,0x04,0x12,0x0,
0x13,0x0f,0x13,0x0f,
0xff
};
uchar code srkl[]={//生日快樂
0x78,0x00, //曲速 120
0x15,0x02,0x15,0x02,
0x16,0x04,0x15,0x04,0x21,0x04,
0x17,0x04,0x00,0x04,0x15,0x02,0x15,0x02,
0x16,0x04,0x15,0x04,0x22,0x04,
0x21,0x08,0x15,0x02,0x15,0x02,
0x25,0x04,0x23,0x04,0x21,0x04,
0x17,0x04,0x16,0x08,
0x16,0x04,0x00,0x04,0x24,0x02,0x24,0x02,
0x23,0x04,0x21,0x04,0x22,0x04,
0x21,0x08,
0x21,0x08,0x00,0x08,
0x15,0x02,0x15,0x02,//第二遍
0x16,0x04,0x15,0x04,0x21,0x04,
0x17,0x04,0x00,0x04,0x15,0x02,0x15,0x02,
0x16,0x04,0x15,0x04,0x22,0x04,
0x21,0x08,0x15,0x02,0x15,0x02,
0x25,0x04,0x23,0x04,0x21,0x04,
0x17,0x04,0x16,0x08,
0x16,0x04,0x00,0x04,0x24,0x02,0x24,0x02,
0x23,0x04,0x21,0x04,0x22,0x04,
0x21,0x08,
0x21,0x08,0x00,0x04,
0xff
};
uchar code test[]={//測試
0x78,0x00, //曲速 0x78表示 120拍/分
0x21,0x04,0x22,0x04,0x23,0x04,0x24,0x04,0x25,0x04,0x26,0x04,0x27,0x04,0x00,0x04,
0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x00,0x08,
0x11,0x08,0x12,0x07,0x13,0x06,0x14,0x05,0x15,0x04,0x16,0x03,0x17,0x02,0x00,0x01,
0xff,
};
void delayms(uint ms) /*ms 等于1時,延時1ms 等于2時,延時2ms,以此類推*/
{
uchar a,b,c; //+3
while(ms--)
{
for(c=1;c>0;c--) // 1+2 = 3
for(b=142;b>0;b--) // 1*( 1+142*2)) = 285
for(a=2;a>0;a--); // 142*(1+2*2) = 710
}
}
void delay(uint pai) /*pai 是節拍 pai若定義成uchar類型,當節拍>0x0c時,會造成數據溢出,產生失真。*/
{
uchar a,b,c;
while(pai--) //延遲pai 個 6.25ms
{
for(c=1;c>0;c--) // 1+2=3
for(b=28;b>0;b--) // 1*(1+28*2) =57
for(a=110;a>0;a--); // 28*(1+110*2) = 6188
}
}
uchar key_x() /*P1口高位接縱坐標(P1.7 - P1.4) 低位接橫坐標(P1.3 - P1.0)*/
{
uchar i;
P1 = 0x0f; /*有按鍵按下后 對應按鍵的橫坐標電位被拉低( 注意低電位引腳不能被高電位引腳抬高,只能是低電位拉低高電位)*/
if(P1_0 == 0)
{ delayms(5); //延時5ms 去抖動
if(P1_0 == 0)
i = 1;
}
else if(P1_1 == 0)
{ delayms(5);
if(P1_1 == 0)
i = 2;
}
else if(P1_2 == 0)
{ delayms(5);
if(P1_2 == 0)
i = 3;
}
else if(P1_3 == 0)
{ delayms(5);
if(P1_3 == 0)
i = 4;
}
else
i = 0;
return (i); //0表示按鍵未按下
}
uchar key_y()
{
uchar j;
P1 = 0xf0;
if(P1_4 == 0)
{ delayms(5);
if(P1_4 == 0)
j = 1;
}
else if(P1_5 == 0)
{ delayms(5);
if(P1_5 == 0)
j = 2;
}
else if(P1_6 == 0)
{ delayms(5);
if(P1_6 == 0)
j = 3;
}
else if(P1_7 == 0)
{ delayms(5);
if(P1_7 == 0)
j = 4;
}
else
j = 0;
return (j);
}
void key_check() /*檢查矩陣按鍵坐標、播放鍵的狀態及播放鍵狀態設置*/
{
x = key_x();
y = key_y();
if(key_play == 0)
key_play = 0; /*保持播放鍵引腳低電平,讓其作為歌曲正在播放的標志*/
else
key_play = 1; /*保持播放鍵引腳高電平,讓其作為歌曲未播放的標志*/
}
void display() /*數碼管顯示相應的音調*/
{
if(key_play == 1) //按鍵彈奏時
{ if(x != 0 && y != 0 )
{
if(x == 1)
P0 = num[3 + y] ; //低音4 - 7
else if(x == 2)
P0 = num[7 + y]; //中音1 - 4
else if(x == 3)
P0 = num[11 + y]; //中音5 - 7 和 高音 1
else if(x == 4)
P0 = num[15 + y]; //高音2 - 5
}
else
P0 = 0x00;
}
else //播放音樂時
{ if(yindiao_h == 0) /* yindiao變量的高四位表示 低(0) 中(1) 高(2) 音 */
P0 = num[yindiao_l];/*yindiao變量的低四位表示“調”, 數碼管顯示當前音調*/
else if(yindiao_h == 1) // 中音
P0 = num[yindiao_l + 7];
else if(yindiao_h == 2) //高音
P0 = num[yindiao_l + 14];
}
}
void speak() /* 按鍵 ,為定時器0 T0 賦計數初值,讓 T0函數驅動蜂鳴器發出對應的音調 */
{
if(x == 1)
{
f_h = chuzhi[2*y + 6]; //低音4 - 7
f_l = chuzhi[2*y + 6 + 1];
}
else if(x == 2)
{
f_h = chuzhi[(16+y)*2]; //中音 1 -4
f_l = chuzhi[(16+y)*2 +1];
}
else if(x == 3)
{
if(y <= 3)
{
f_h = chuzhi[(20+y)*2]; //中音 5 - 7
f_l = chuzhi[(20+y)*2 + 1];
}
else
{
f_h = chuzhi[66]; //高音1
f_l = chuzhi[67];
}
}
else if(x == 4)
{
f_h = chuzhi[(33+y)*2]; //高音2 -5
f_l = chuzhi[(33+y)*2 + 1];
}
}
void timer0() interrupt 1 //定時器0
{
if(key_play == 0)
{
TL0 = song_l;
TH0 = song_h;
beep = ~beep;
}
else
if(x != 0 && y != 0 && key_play == 1)/*當有矩陣按鍵按下,并且不播放歌曲時 */
{
TL0 = f_l; //賦初值
TH0 = f_h; //
beep = ~beep; /*蜂鳴器引腳電平取反,定時器每溢出一次電平取反一次,不同的計數初值對應不同的溢出時間,對應不同的方波頻率 */
}
}
void timer1() interrupt 3 //定時器1 led燈起落
{
TL1 = 0x00;
TH1 = 0x39;/*定時器1 高8位初值。控制led燈的起落快慢(數值不嚴格)*/
if(key_play == 1) //不播放歌曲時
{
if(x != 0 && y != 0 && flash < 8 ) //最大加到8
++flash;
else if(x == 0 && y == 0 && flash >0 ) //最小減到0
--flash;
P2 = led_table[flash];
}
else if(key_play == 0 ) //播放歌曲時
{
if(out == 1 && flash < 8 && flash < jiepai) /*out ==1 表示有歌曲發聲時,(flash<jiepai)使 led燈剛好指示節拍*/
++flash;
else if(out == 0 && flash > 0)
--flash;
P2 = led_table[flash];
}
}
uchar choose() //播放狀態下 選歌
{
uchar i = 0; //第i首歌 初值0表示未選歌
uchar j;
x = key_x();
y = key_y();
if(x == 1 && y == 1)
i = 1; //選第一首
else if(x == 1 && y == 2)
i = 2; //選第二首
else if(x == 1 && y == 3)
i = 3;
else if(x == 1 && y == 4)
i = 4;
else if(x == 2 && y == 1)
i = 5;
else if(x == 4 && y == 1)// 上一首
i = 13;
else if(x == 4 && y == 2)//用作暫停播放
i = 14;
else if(x == 4 && y == 3) //下一首
i = 15;
else if(x == 4 && y == 4)
i = 16; //用作停止播放
if(i == song_id)
{
which = 2; //選同一首歌時,重播這首歌
}
else if(i > allsong && i < 13) /*如果按鍵號 在 最大歌曲序號 和 功能鍵 之間,返回原歌曲序號*/
i = song_id; //
else if(i == 0) //i等于初值 說明未按鍵
i = song_id; //不按鍵選歌時,返回原歌曲的序號
while(1) //釋放按鍵時才進行下一步
{
x = key_x();
y = key_y();
if(x == 1)
j = y;
else if(x == 2)
j = 4 + y;
else if(x == 3)
j = 8 + y;
else if(x == 4)
j = 12 + y;
if(x == 0 || (j > allsong && j < 13)) /*釋放按鍵 或者按鍵號 在 最大歌曲序號 和 功能鍵 之間時 跳出循環*/
break;
}
return(i);
}
uchar choose2() /*選歌 不用放開按鍵 在暫停的狀態下使用 */
{
uchar i = 0;
x = key_x();
y = key_y();
if(x == 1 && y == 1) //選第一首
i = 1;
else if(x == 1 && y == 2) //選第二首
i = 2;
else if(x == 1 && y == 3)
i = 3;
else if(x == 1 && y == 4)
i = 4;
else if(x == 2 && y == 1)
i = 5;
else if(x == 4 && y == 1) // 上一首
i = 13;
else if(x == 4 && y == 2) //用作暫停播放
i = 14;
else if(x == 4 && y == 3) //下一首
i = 15;
else if(x == 4 && y == 4)
i = 16; //用作停止播放
if(i == song_id)
{
same = 1;
which = 2; /*選了同一首歌時,重播這首歌 (0,1用來存曲速了 故從2開始) */
}
else if(i > allsong && i < 13) /*如果按鍵號 在 最大歌曲序號 和 功能鍵 之間,返回原歌曲序號*/
i = song_id;
else if(i == 0) //i等于初值 說明未按鍵
i = song_id; /*不按鍵選歌時,返回原歌曲的序號*/
return(i);
}
void play() //播放歌曲
{
uint qusu;//歌曲播放速度 (拍/分)
uint pai2; /* pai2 = (2400/qusu)*jiepai; 送到delay()函數*/
while(1)
{
while(1)
{
choose_id:
temp_id = choose(); //選歌
/****************************↓↓↓↓↓暫停↓↓↓↓↓*****************************************/
if(temp_id == 14) //如果按下暫停鍵
{
delayms(500); //延時500ms
while(1)
{
temp_id = choose2();/*choose2 按下就起作用 不必等到放開按鍵才起作用*/
if(temp_id == 14) /*再次按下“暫停鍵” 表示繼續播放*/
{
break;
}
else if(temp_id == 16)/*按下停止鍵 ,功能表現為:暫停播放時也能停止播放,回到播放前狀態*/
{
song_id = 16;
break;
}
else if(temp_id == 13) //上一首
{
which = 2;
if(song_id == 1)
song_id = allsong ;//播放最后一首
else
--song_id;
break;
}
else if(temp_id == 15) //下一首
{
which = 2;
if(song_id == allsong)
song_id = 1; //播放第一首
else
++song_id;
break;
}
else if(temp_id != song_id && temp_id <= allsong)/*選了另一首歌曲 屏蔽掉了未定義的按鍵 */
{
which = 2; /*從歌曲的第一個音播放 (0,1用來存曲速了 故從2開始) */
song_id = temp_id;
break;
}
else if(same == 1)
break;
}
same = 0; //跳出循環后 需重置為0
}
/****************************↑↑↑↑↑暫停↑↑↑↑↑***************************************/
else if(temp_id == 13) //上一首
{
which = 2;
if(song_id == 1)
song_id = allsong ;//播放最后一首
else
--song_id;
}
else if(temp_id == 15) //下一首
{
which = 2;
if(song_id == allsong)
song_id = 1; //播放第一首
else
++song_id;
}
else if(temp_id == 16)
{
song_id = 16;
}
else if(temp_id != song_id && temp_id <= allsong) //選了另一首歌曲
{
which = 2; //從歌曲的第一個音播放
song_id = temp_id;
}
/**************************************************************************************/
nochoose: //不用選歌 當正常放完一首歌時,跳到這里
if(song_id == 4)
{ key_play = 0;
if(srkl[which] == 0xff) /* 遇到結束符 跳出循環(內循環) 停止播放 */
break;
qusu = srkl[0];
yindiao = srkl[which]; //音調
jiepai = srkl[which+1]; //節拍
}
else
if(song_id == 3)
{ key_play = 0;
if(ymt[which] == 0xff) /* 遇到結束符 跳出循環(內循環) 停止播放 */
break;
qusu = ymt[0];
yindiao = ymt[which]; //音調
jiepai = ymt[which+1]; //節拍
}
else
if(song_id == 2)
{ key_play = 0;
if(dl[which] == 0xff) /* 遇到結束符 跳出循環 停止播放 */
break;
qusu = dl[0];
yindiao = dl[which]; //
jiepai = dl[which+1]; //
}
else if(song_id == 1)
{
key_play = 0;
if(test[which] == 0xff) /* 遇到結束符 跳出循環 停止播放*/
break;
qusu = test[0];
yindiao = test[which];
jiepai = test[which+1];
}
/******************************************************************************/
else if(song_id == 16 )
{
which = 2;
break;
}
else
{
key_play = 1;
goto choose_id; /*如果既沒有選歌 又沒有停止 返回去做選擇*/
}
/********************************************************************************************/
yindiao_l = yindiao % 16; // 低四位 調
yindiao_h = yindiao /16; /* 高四位 。。是低音0 中音1 還是 高音2 */
if(yindiao != 0) /*音調不為0。(當音調為0時表示這個音不響 但依舊要占這個音的播放時間)*/
{
song_h = chuzhi[yindiao*2];
song_l = chuzhi[yindiao*2+1];
TR0 = 1; /*給初值賦值后,開啟定時器0 蜂鳴器開始發聲 */
TR1 = 1; /*開啟定時器1 ,led開始閃動*/
display(); //數碼管顯示音調
out = 1; /*正在發聲的標志,定時器1得以控制led燈按一定的時間間隔 逐個點亮,表現為 —— 沖 */
}
else
{
TR0 = 0;
out = 0;
TR1 = 0;
P0 = 0x00;
flash = 0;
P2 = led_table[0];
}
pai2 = (2400/qusu)*jiepai;
delay(pai2); /*延時 = 節拍數 x 125ms (決定著1個音的發聲時間) */
TR0 = 0; //蜂鳴器停止發聲
P0 = 0x00;
out = 0;
delayms(50); /*唱完一個音停xx ms(決定每個音調之間的時間間隔 根據個人喜好節奏來定 */
TR1 = 0; //led停止閃動
flash = 0;
P2 = led_table[0];
which = which + 2; //下一個音
} /*已經放完一首歌,或者停止播放 ,接下來判斷是停止播放還是播放下一首 */
TR0 = 0;
P0 = 0x00;
out = 0;
flash = 0;
P2 = led_table[0];
if(song_id == 16) /*坐標(4,4)的鍵盤作為停止播放鍵*/
{
while(1)
{
x = key_x();
if(x == 0)
break;/*松開按鍵 才結束 避免觸發其他程序 比如電子琴發聲、led顯示等 */
}
key_play = 1; /*播放鍵引腳置高電平,播放結束的標志 */
song_id = 1; // 第一首歌開始
which = 2; // 每首歌的最開始的一個音
break; /*跳出第二個循環(即結束play函數)*/
}
else if(song_id == allsong)/*當放到最后一首時,從第一首開始 (當前共3首) */
{
song_id = 1;
which = 2;
delayms(1000); //一秒后從第一首開始播放
goto nochoose;
}
else
{
++song_id; /*歌曲序號自動+1 自動播放下一首歌*/
which = 2;
delayms(1000);
goto nochoose;//不用選歌 播放下一首
}
}
}
void main()
{
P0 = 0x00;
P2 = 0xff;
TMOD = 0x11; /*定時器0 定時器1 都采用方式1(16位定時器方式) */
IE = 0x8a;
PT0 = 1; /*設置定時器0為高優先級,避免被定時器1干擾,造成聲音失真 */
while(1)
{
key_check();
if(key_play == 1 && x != 0 && y != 0)
{
TR1 = 1;
display();
speak();
TR0 = 1;
}
else if(key_play == 0)
{
key_play = 0;
play(); /*play函數有循環語句,當按下停止鍵(16鍵)時才能跳出 */
}
else
{
if(flash == 0)/*當flash 減到0時 再關閉定時器1,即 讓led燈全部熄滅再關閉T1 */
TR1 = 0;
TR0 = 0;
P0 = 0x00;
}
}
}
|