隨機彈奏曲子時,可以實時記憶,并可復讀(重復播放)。這一步用數組實現不了請大神給看看
#include<reg51.h>
#define SMG P0
#define KEY P1 //定義數碼管段碼輸出
sbit LED =P2^1 ;
sbit SPK =P2^0;
sbit K1= P3^2;
sbit K2= P3^3;
sbit K3= P3^0; //定義方波輸出口
unsigned int tone1,tone2,i;
/*****標準音符表*****/
//用于使定時器初值變化以產生相應頻率的定時
unsigned char code yinfu[]={0xfb,0xe9, //Do
0xfc,0x5c, //Re
0xfc,0xc1, //Mi
0xfc,0xef, //Fa
0xfd,0x45, //So
0xfd,0x92, //La
0xfd,0xd0, //Si
0xfd,0xee, //Do#
0x00,0x00 //音符之間的間隔,只要間隔時間小于65ms時,
//喇叭不會發出聲音,用作拍子之間的短暫停頓
};
unsigned char code shengri_tone[]={ 1,0,1,2,1,4,3,0,
1,0,1,2,1,5,4,0,
1,0,1,8,6,4,3,2,0,
7,0,7,6,4,5,4,0 //0代表不發聲,即停頓;數字即為音調
};
unsigned char code shengri_beat[]={ 24,1,24,48,48,48,72,5,
24,1,24,48,48,48,72,5,
24,1,24,48,48,48,48,72,5,
24,1,24,48,48,48,72,5
}; //節拍,即tone表各音調的延時
unsigned char code button[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned char code dis[]={0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0xff};
unsigned char code yindiao[]={1,2,3,4,5,6,7,8};
unsigned char tanzou_tone[30];
unsigned char tanzou_beat[30];
/*****15ms延時子程序,用于節拍*****/
void delay(void)
{
unsigned char n=15;
while(n--)
{
unsigned char i;
for(i=0;i<125;i++);
}
}
/*****定時器0初始化*****/
void initTimer(void)
{
TMOD=0x01; //定時器0,工作方式1;定時器1,工作方式1
TH0=tone1;
TL0=tone2;
}
/*****定時器0中斷服務程序*****/
void timer0(void) interrupt 1
{
TH0=tone1;
TL0=tone2;
SPK=~SPK; //取反,以產生方波
}
/*****演奏子程序1*****/
void play1(void)
{
unsigned char m=0;
unsigned char s;
unsigned char a=1;
while(1)
{
EA=0;
LED=0;
a=shengri_tone[m]; //取音符
SMG=dis[a-1];
s=shengri_beat[m]; //取節拍
tone1=yinfu[2*a-2];
tone2=yinfu[2*a-1];
EA=1;
while(s--)
{
delay();
}
if((!K1)||(!K2)) //發現按鍵,立即退出播放
{
EA=0;
SPK=0;
SMG=0xff;
m=34; //改過已
return;
}
else
LED=1;
m++;
if(m>=33) return; //數值是shengri相關表中的元素數量
}
}
void play2(void)
{
unsigned char m=0;
unsigned char s;
unsigned char a=1;
while(1)
{
EA=0;
LED=0;
a=tanzou_tone[m]; //取音符
SMG=dis[a-1];
s=tanzou_beat[m]; //取節拍
tone1=yinfu[2*a-2];
tone2=yinfu[2*a-1];
EA=1;
while(s--)
{
delay();
}
if(P1!=0xff) //發現按鍵,立即退出播放
{
EA=0;
SPK=0;
SMG=0xff; //改過已
return;
}
else
{
LED=1;
m++;
if(m>=29) return;
}
}
}
void Delay_xMs (unsigned int x)//延時函數
{
unsigned int i,j;
for(i=0;i<x;i++)
{
for(j=0;j<3;j++);
}
}
void Button_Scan(void)
{
i=0;
P1=0xff;
P3=0xff;
if(KEY==button[0])
{
Delay_xMs(10);
if(KEY==button[0])
{
tone1=0xfb;
tone2=0xe9;
SMG=dis[0];
EA=1;
}
}
if(KEY==button[1])
{
Delay_xMs(10);
if(KEY==button[1])
{
tone1=0xfc;
tone2=0x5c;
SMG=dis[1];
EA=1;
}
}
if(KEY==button[2])
{
Delay_xMs(10);
if(KEY==button[2])
{
tone1=0xfc;
tone2=0xc1;
SMG=dis[2];
EA=1;
}
}
if(KEY==button[3])
{
Delay_xMs(10);
if(KEY==button[3])
{
tone1=0xfc;
tone2=0xef;
SMG=dis[3];
EA=1;
}
}
if(KEY==button[4])
{
Delay_xMs(10);
if(KEY==button[4])
{
tone1=0xfd;
tone2=0x45;
SMG=dis[4];
EA=1;
}
}
if(KEY==button[5])
{
Delay_xMs(10);
if(KEY==button[5])
{
tone1=0xfd;
tone2=0x92;
SMG=dis[5];
EA=1;
}
}
if(KEY==button[6])
{
Delay_xMs(10);
if(KEY==button[6])
{
tone1=0xfd;
tone2=0xd0;
SMG=dis[6];
EA=1;
}
}
if(KEY==button[7])
{
Delay_xMs(10);
if(KEY==button[7])
{
tone1=0xfd;
tone2=0xee;
SMG=dis[7];
EA=1;
}
}
if(KEY==0xff)
{
Delay_xMs(10);
if(KEY==0xff)
{
EA=0;
SPK=0;
SMG=0xff;
}
}
switch(P1)
{
case 0xfe:
while(KEY!=0xfe);
tanzou_tone[i++]=yindiao[0];
tanzou_beat[i++]=25;
break;
case 0xfd:
while(KEY!=0xfd);
tanzou_tone[i++]=yindiao[1];
tanzou_beat[i++]=25;
break;
case 0xfb:
while(KEY!=0xfb);
tanzou_tone[i++]=yindiao[2];
tanzou_beat[i++]=25;
break;
case 0xf7:
while(KEY!=0xf7);
tanzou_tone[i++]=yindiao[3];
tanzou_beat[i++]=25;
break;
case 0xef:
while(KEY!=0xef);
tanzou_tone[i++]=yindiao[4];
tanzou_beat[i++]=25;
break;
case 0xdf:
while(KEY!=0xdf);
tanzou_tone[i++]=yindiao[5];
tanzou_beat[i++]=25;
break;
case 0xbf:
while(KEY!=0xbf);
tanzou_tone[i++]=yindiao[6];
tanzou_beat[i++]=25;
break;
case 0x7f:
while(KEY!=0x7f);
tanzou_tone[i++]=yindiao[7];
tanzou_beat[i++]=25;
break;
}
switch(P3)
{
case 0xfb:play1();break;
case 0xfe:play2();break;
}
}
void main(void)
{
initTimer();
SMG=dis[8];
TR0=1;
ET0=1;
SPK=0;
while(1)
{
Button_Scan();
}
}
|