#include"reg51.h"
#define uchar unsigned char
#define uint unsigned int
//--------------------------------------
uchar code row[] ={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//行扫描数组row0--row7.硬件定义为P2口uchar code word[][8]={
{0xd7,0x81,0x77,0xf7,0x00,0xf7,0xf7,0xf7},//硬件定义为P0口。暂停
{0x1F,0xBF,0xBF,0xBF,0xBD,0x98,0xBD,0xFF},//硬件定义为P0口。'1'
{0xF,0xEF,0xDF,0xBF,0x7D,0x68,0x9D,0xFF},//硬件定义为P0口。'2'
{0x9F,0x6F,0x7F,0x9F,0x7D,0x68,0x9D,0xFF},//硬件定义为P0口。'3'
{0xBF,0xBF,0x7,0xB7,0xAD,0x98,0xBD,0xFF},//硬件定义为P0口。'4'
};
//单片机晶振采用11.0592MHz
// 频率-半周期数据表 高八位 本软件共保存了四个八度的28个频率数据
uchar code FREQH[] = {0x01, //0的时候没有音符
0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音1234567
0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC,//1,2,3,4,5,6,7
0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 1234567
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567
//-----------------------------------------
// 频率-半周期数据表 低八位
uchar code FREQL[] = {0x01, //0的时候没有音符
0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音1234567
0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, //1,2,3,4,5,6,7
0x8F, 0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 1234567
0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音 1234567
//--------------------------------------
//一个音符有三个数字。前为第几个音、中为第几个八度、后为时长(以1/4拍为单位)。
//6, 2, 6 分别代表:6, 中音, 6个1/4拍;
//5, 2, 2 分别代表:5, 中音, 2个1/4拍;
//5, 2, 4 分别代表:5, 中音, 4个1/4拍;
//1, 3, 4 分别代表:1, 高音, 4个1/4拍;
//低音为1,中音为2,高音为3,超高音为4;
//////////////////////////////////////////////////////////
/********************世上只有妈妈好*********************/
uchar code sszymmh[] = {
6,2,6, 5,2,2, 3,2,4, 5,2,4,
1,3,4, 6,2,2, 5,2,2, 6,2,8,
3,2,4, 5,2,2, 6,2,2, 5,2,4,
3,2,4, 1,2,2, 6,1,2, 5,2,2,
3,2,2, 2,2,8, 2,2,6, 3,2,2,
5,2,4, 5,2,2, 6,2,2, 3,2,4,
2,2,4, 1,2,8, 5,2,6, 3,2,2,
2,2,2, 1,2,2, 6,1,2, 1,2,2,
5,1,16, 0,0,0};
/**********************两只老虎**********************/
uchar code Twotiger[]={
1,2,4, 2,2,4, 3,2,4, 1,2,4,
1,2,4, 2,2,4, 3,2,4, 1,2,4,
3,2,4, 4,2,4, 5,2,8,
3,2,4, 4,2,4, 5,2,8,
5,2,3, 6,2,1, 5,2,3, 4,2,1, 3,2,4, 1,2,4,
5,2,3, 6,2,1, 5,2,3, 4,2,1, 3,2,4, 1,2,4,
1,2,4, 5,2,4, 1,2,8, 1,2,4, 5,2,4, 1,2,8,
0,0,0};
/***********************小毛驴**********************/
uchar code Xiaomaolu[]={
1,2,2, 1,2,2, 1,2,2, 3,2,2, 5,2,2, 5,2,2,
5,2,2, 5,2,2, 6,2,2, 6,2,2, 6,2,2, 1,3,2,
5,2,4, 4,2,2, 4,2,2, 6,2,2, 6,2,2, 3,2,2,
3,2,2, 3,2,2, 3,2,2, 2,2,2, 2,2,2, 5,1,4,
5,2,2, 1,2,2, 1,2,2, 1,2,2, 3,2,2, 5,2,2,
5,2,2, 5,2,2, 5,2,2, 6,2,2, 6,2,2, 6,2,2,
1,3,2, 5,2,4, 4,2,2, 4,2,2, 4,2,2, 6,2,2,
3,2,2, 3,2,1, 3,2,1, 3,2,2, 3,2,2, 2,2,2,
2,2,2, 2,2,2, 3,2,2, 1,2,4, 0,0,0};
/*****************happy birthday***********************/
uchar code Birthday[]={
5,1,2, 5,1,2, 6,1,4, 5,1,4,
1,2,4, 7,1,8, 5,1,2, 5,1,2, 6,1,4, 5,1,4,
2,2,4, 1,2,8, 5,1,2, 5,1,2, 5,2,4, 3,2,4,
1,2,4, 7,1,4, 6,1,4, 4,2,2, 4,2,2, 3,2,4,
1,2,4, 2,2,4, 1,2,4, 0,0,0};
////////////////////////////////////////////////////////
//-----------------------------------------------------
sbit RC5=P3^2;
sbit speaker = P1^0;
uchar t0h,t0l,time;
uchar start=0;
uchar turn=0;
uchar address=0;
uchar command=0;
char num=0;
char in;
void dalay_1(uint x) //点阵
{
uint a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
void display(uchar word_num)
{
uchar i;
for(i=0;i<8;i++)
{
P2=row[i];
P0=word[word_num][i];
dalay_1(1);
P2=0xff;
P0=0xff;
}
}
void t0int() interrupt 1 //T0中断程序,控制发音的音调
{
TR0 = 0; //先关闭T0
speaker = ~speaker; //输出方波, 发音
TH0 = t0h; //下次的中断时间, 这个时间, 控制音调高低
TL0 = t0l;
TR0 = 1; //启动T0
}
//--------------------------------------
void delay(uchar t) //延时程序,控制发音的时间长度120ms(1/4拍)
{
uchar c,i;
while(t--) //四重循环, 共延时t个1/4拍
{
for(c=15;c>0;c--)
for(i=0;i<8;i++)
{
P2=row[i];
P0=word[num][i];
dalay_1(1);
P2=0xff;
P0=0xff;
}
}
//延时期间, 可进入T0中断去发音
TR0 = 0; //关闭T0, 停止发音
}
//--------------------------------------
void singachar() //演奏一个音符 定时器0中断产生频率
{
TR0=0;
TH0 = t0h; //控制音调
TL0 = t0l;
TR0 = 1; //启动T0, 由T0输出方波去发音
delay(time); //控制时间长度即 节拍
}
//--------------------------------------
//**************演奏一首歌***********************************//
void song(uchar *str)
{
uchar k,i;
i = 0;
time = 1;
in=0;
while(time)
{
k = str[i] + 7 * (str[i + 1]-1);//第i个是音符, 第i+1个是第几个八度
t0h = FREQH[k]; //从数据表中读出频率数值
t0l = FREQL[k]; //实际上, 是定时的时间长度
time = str[i + 2]; //读出时间长度数值 节拍时间
i += 3;
singachar();
if(in)//In判断是否进入过中断、进入中断则立即停止歌曲播放
time=0;
in=0;
speaker=1;
}
}
//*************红外接收程序*****************************//
void RC5_INT() interrupt 0 //读取红外编码的中断程序 P3.2
{ //遥控码(一帧14位), 0,1为start bits, 2 为control bit
//3~7为address bits
//8~13为command bits
char i=0;
start=0; //起始位
address=0;//地址位
command=0;//控制位
ET0=0;//关闭定时器0中断
EX0=0; //关外部中断
TH1=0xFE; //定时器440us
TL1=0x6A;
TR1=1;
while(TF1==0);
TF1=0;
start=start<<1; //将数据左移一位, 以便将一下位数据并于最低位
if(RC5==0)
start|=0x01;
TH1=0xF9; //定时器1780us
TL1=0x97;
while(TF1==0);
TF1=0;
start=start<<1;
if(RC5==0)
start|=0x01;
if(start==0x03) //判断是否为起始位
{
//读取控制码
TH1=0xF9; //定时器1780us
TL1=0x97;
while(TF1==0);
TF1=0;
if(RC5==0)
turn=1;
else
turn=0;
for(i=0;i<5;i++) //读取address
{
TH1=0xF9; //定时器1780us
TL1=0x97;
while(TF1==0);
TF1=0;
address=address<<1;
if(RC5==0)
address|=0x01;
}
for(i=0;i<6;i++) //读取command
{
TH1=0xF9; //定时器1780us
TL1=0x97;
while(TF1==0);
TF1=0;
command=command<<1;
if(RC5==0)
command|=0x01;
}
}
in=1;//进入中断后停止歌曲播放
ET0=1;
TR1=0;
IE0=0; //清除外部中断请求标志
EX0=1;
}
void main()
{
IT0=1; //边沿触发方式
EX0=1; //外部中断使能
//----------------------------------
TMOD=0x11;//T0,T1 工作方式1
ET0 = 0; //T0关中断
EA=1; //总中断开
while(1)
{
switch(command)
{
case 0x01:
num=1;
break;
case 0x02:
num=2;
break;
case 0x03:
num=3;
break;
case 0x04:
num=4;
break;
case 0x20:
{
if(num==4)
{num=1;}
else
{num=num+1;}
break;
}
case 0x21:
{
if(num==1)
{num=4;}
else
{num=num-1;}
break;
}
default:
num=0;
display(0); break;
}
//------------------------------------
if(num==1)
{song(sszymmh); }
else if(num==2)
{ song(Twotiger);}
else if(num==3)
{ song(Xiaomaolu);}
else if(num==4)
{ song(Birthday);}
else
{
display(0);
}
}
}