马上注册,结交更多好友,享用更多功能,让你轻松玩转社区
您需要 登录 才可以下载或查看,没有账号?立即注册
×
#include<reg52.h>
sbit beep=P2^0;
unsigned char song,a,tone,toneh,tonel,ttt,tt,a,beat,
basekey,p,pp,speed,beat,k;
char temp;
unsigned char code tonehtable[]={ //音高频率设置高八位
0xE4,0xE6,0xE7,0xE8,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,
0xF2,0xF3,0xF3,0xF4,0xF5,0xF5,0xF6,0xF6,0xF7,0xF7,0xF8,0xF8,
0xF9,0xF9,0xF9,0xFA,0xFA,0xFA,0xFB,0xFB,0xFB,0xFB,0xFC,0xFC,
0xFC,0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFE,0xFE,
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF};
unsigned char code toneltable[]={ //音高频率设置低八位
0x7A,0x06,0x7B,0xDB,0x28,0x62,0x8A,0xA1,0xA9,0xA2,0x8E,0x6B,
0x3D,0x03,0xBD,0x6D,0x14,0xB1,0x45,0xD0,0x54,0xD1,0x47,0xB5,
0x1E,0x81,0xDE,0x36,0x8A,0xD8,0x22,0x68,0xAA,0xE8,0x23,0x5A,
0x8F,0xC0,0xEF,0x1B,0x45,0x6C,0x91,0xB4,0xD5,0xF4,0x11,0x2D,
0x47,0x60,0x77,0x8D,0xA2,0xB6,0xC8,0xDA,0xEA,0xFA,0x08,0x16};
char code tonetone[]={ //音阶转化为半音差值
0,5,7,9,10,12,14,16,17,19,21,22,24,0,2,4};
//从左到右,16进制0-F分别对应简谱的
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
// 0 1 2 3 4 5 6 7 1 2 3 4 5 5 6 7
//休止 ----中音----- ---高音-- -低音-
unsigned char code music0[]={
0x54,0x52,0x62,0x28, 0x14,0x12,0xe2,0x28,
0x54,0x54,0x62,0x82,0x62,0x52,0x14,0x12,0xe2,0x28,
0x54,0x24,0x14,0xf2,0xe2,0xd4,0x54,0x24,
0x32,0x22,0x14,0x12,0xe2,
0x22,0x32,0x22,0x12,0x22,0x12,0xf2,0xe2,0xdb,0x04,0x00};
//乐谱,第一位表示音高,第二位表示音长为几个16分音符(1/4拍子)。
// 如1为16分音符,2为8分音符,3为附点8分音符,
// 4为4分音符...... 另外为了方便,F定为全音符
void delayms(unsigned int ms) //N毫秒延迟函数
{
unsigned int ms1; unsigned char ms2;
for(ms1=ms;ms1>0;ms1--)
for(ms2=110;ms2>0;ms2--);
}
void settone(unsigned char tone) //音调设置函数
{
toneh=tonehtable[tone];
tonel=toneltable[tone];
TH1=toneh;
TL1=tonel;
EA=1;
ET1=1;
TR1=1;
}
void onekey() //发出单个音
{
unsigned char al,ah;
beat=0;
do
{
switch(song)
{
case 0:ah=music0[a]>>4;al=music0[a]&0x0F;break;
*/
}
if(al==0) //末位为0用于特殊功能
switch(ah)
{
case 0:a=0;break; //0x00音乐结束,从头演奏
case 1:basekey++;a++;break; //0x10后面全部升半音
case 2:basekey--;a++;break; //0x20后面全部降半音
case 3:basekey+=12;a++;break; //0x30后面全部升八度
case 4:basekey-=12;a++;break; //0x40后面全部降八度
case 5:beat+=8;a++;break; //0x50下个音长延长2分音符时长
case 6:beat+=16;a++;break; //0x60下个音长延长全音符时长
}
}
while(al==0);
al+=(al==15); //末位为F(15)时,加1变成全音符
beat+=al; //加长音
if(ah==0)
{
p=0;
}
else
{
p=0; //p=0不发声
delayms(20); //延时20ms,使两个音之间有一点间隙
settone(tonetone[ah]+basekey);
p=1; //p=1发声
}
}
void Init_Timer() //初始化时钟设置
{
TMOD=0x11;
EA=1;
ET0=1;
TR0=1;
}
void main() //主程序
{
beep=0;
song=0;
ttt=0;
tt=0;
basekey=19; //定调值,C调19,每半音相差1,每八度相差12
speed=5; //速度,数字越大越慢
a=0;
Init_Timer();
}
void int3() interrupt 3 //音高方波产生中断程序
{
TH1=toneh; //存入1号定时器的高8位值
TL1=tonel; //存入1号定时器的高8位值
if(p!=0) //p=0不执行程序,使两个音之间有间隙
beep=~beep; //蜂鸣器定时将电位取反,产生方波
}
void int1() interrupt 1 //音长控制中断程序
{
TH0=76; //50毫秒定时
TL0=0;
ttt++; //每隔50毫秒,ttt计数器加一
if(ttt==speed) //ttt计数器与速度值相等时
{
ttt=0;
tt++; //tt计数器加1,即已演奏完1个16分音符时长
}
if(tt==beat) //tt计数器与音长相等时
{
tt=0;
onekey(); //执行下一个音符程序
a++;
}
} |