#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char   
sbit ir=P3^2;     //红外接收头位定义
sbit relay=P0^6;  //继电器控帽口位定义
sbit fm=P2^3;   //蜂鸣器控制口位定义
uchar irtime;
bit irprosok,irok;
uchar ircode[4];
uchar irdata[33];
uchar startflag;
uchar bitnum;

void delay()	 //延时函数
{	
	uchar i;					
	uint ms=1000;
	while(ms--)                             
	{
		for(i=0;i<120;i++);
	}
}

void timer0init(void)  //定时器0初始化 256*(1/12m)*12=0.256ms
{
  TMOD=0x02;   //定时器0工作方式2，TH0是重装值，TL0是初值
  TH0=0x00;    //重载值
  TL0=0x00;   //初始化值
  ET0=1;     //开中断
  TR0=1;    
}

void tim0_isr (void) interrupt 1 using 1  //定时器0中断服务函数
{
  irtime++;   //用于计数2个下降沿之间的时间
}

void int0init(void)  //外部中断0初始化
{
 IT0 = 1;    //指定外部中断0下降沿触发，INT0 (P3.2)
 EX0 = 1;   //使能外部中断
 EA = 1;    //开总中断
}

void int0 () interrupt 0   //外部中断0服务函数
{
if(startflag)
 {
  if(irtime>32&&irtime<63)  
	{
	   bitnum=0;
	}
	irdata[bitnum]=irtime;
	irtime=0;
	bitnum++;
	if(bitnum==33)
	  {
	   bitnum=0;
	   irok=1;
	  }
 }
else
 {
 irtime=0;
 startflag=1;
 }
}

void irpros(void)   //红外码值处函数
{
	uchar mun,k,i,j;
	k=1;
	for(j=0;j<4;j++)
	{
		for(i=0;i<8;i++)
		{
			mun=mun>>1;
			if(irdata[k]>6)
			{
				mun=mun | 0x80;
			}
				k++;
		}
		ircode[j]=mun;
	}
	irprosok=1;
}

void ir_work(void)   //红外键值处理函数
{
	switch(ircode[2])   //判断操作码(第三个数码值）
	         {
			 case 0x0c:relay=!relay;fm=0;delay();fm=1;break;  //继电器取反一次
             default:break;
			 }
		  irprosok=0;  //处理完成标志
  }

void main(void)  //主函数
{
 int0init();    //外部中断初始化
 timer0init();  //定时器初始化
 relay=0;
 while(1)   //主循环
   {
    if(irok==1)    //如果红外编码接收好了
	  {   
	   irpros();   //进行红外码值处理
 	   irok=0;
	  }
    if(irprosok==1)  //如果红外码值处理好后
	  {
	   ir_work();   //进行工作处理
  	  }
   }
}