随机弹奏曲子时,可以实时记忆,并可复读(重复播放)。这一步用数组实现不了请大神给看看
#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();
}
}
|