⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.h

📁 51单片机红外遥控解码程序
💻 H
字号:
//*********************************************
 //MCU:AT89C2051 ,晶振频率:6 MHz
 //用到定时器:T0,T1
 //T1:供串口通讯使用
 //T0:定时器产生mS延时
 //制作人:平顶山工学院计算机系,郭猛
//**********************************************
uchar ComSendStr[11]={'R','e','c',':','K','e','y','0','0','\r','\n',};		//给PC发送接收码的数据缓冲区
uchar code HEX[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',};//16进制字符
//uchar RECS80_Start=0;
///////红外线发射接收接口部分//////////
sbit RF_IR=P1^7;		//红外遥控 or 无线遥控
sbit IR_RXD=P3^2;		//红外接收端口,INT0
sbit REC_LED=P3^7;		//红外接收指示灯,低电平亮

/**********************RECS80编码************************************/
uchar Value=0;			//得到的一个编码值.
uchar Cnt256;			//Timer0定时器计数器
uchar IRbit;
uchar UserID,rUserID,OprCode,rOprCode;	//用户识别码、用户识别码反码、操作码、操作码反码

/*********************RC-5编码****************************************/
uchar YKDatas[3];   //遥控码(一帧14位),YKDatas[0]: 0,1为start bits, 2 为control bit, YKtype=0
                    //YKDatas[1]: 3~7为system bits, YKtype=1
                    //YKDatas[2]: 8~13为command bits, YKtype=2
uchar YKcount, YKtype;            //遥控已接收位数, 一帧的各段标志

void EnableINT0(bit En)	;

//重置所有数据
void YKReset()
{
    Delay(100);  //去重复
    YKDatas[0] = YKDatas[1] = YKDatas[2] = 0;
    YKcount = 0;
    YKtype = 0;
	EnableINT0(1);
}

void YKInit()                  //遥控接收初始化
{
    TMOD |= 0x01;              //T0选用方式1(16位定时)
    IE |= 0x82;                //开总中断, 开定时器0中断 
    IR_RXD = 1;
    YKReset();  			   //重置数据,开外部中断0. EX0.
}

void YKSuccess()  //接收到数据后会自动被调用
{
    uchar i,j;
	i=YKDatas[2]/16;
	j=YKDatas[2]%16;   
	Send_String_Com("H",1);
	Send_Char_Com(0x30);Send_Char_Com(0x30);	//第一个字节:0
	Send_Char_Com(0x30);Send_Char_Com(0x30);	//第二个字节:0
	Send_Char_Com(0x30);Send_Char_Com(0x30);	//第三个字节:0
	Send_Char_Com(HEX[i]);Send_Char_Com(HEX[j]);//第四个字节:0xij
	Send_String_Com("\r\n",2);
	REC_LED=1;Delay(200);REC_LED=0;	//灯闪
	EnableINT0(1);			//恢复INT0中断
    YKReset();
}

//0.256ms中断
void Init_Timer0()			//由定时器T0产生0.256mS中断
{   
	TMOD |= 0x01;       	//递增计数器 
	TH0=0xFF;				// Init msb_value
	TL0=0x14;				// Init lsb_value
	TF0=0;                  // 清TF0标志
	ET0=1;                  // Enable timer0 interrupt 
	TR0=1;					//16bit重装定时器
}


/////定时器T0的中断服务子程序
void Timer0() interrupt 1	//T0中断
{
	if(IRMode)		//RECS80编码
	{
		EA=0;
		TH0=0xFF;TL0=0x14;		//FSC=11.0592MHZ,定时0.256mS
		Cnt256++;
		/*
		if(IRbit==1)
		{	
			if((Cnt256<=15) && IR_RXD)		//9ms内仍是低电平,9ms外是高电平
			{
				RECS80_Start=0;
				TR0=0;	//暂停T0
				EA=1;
				return;	
			}
			RECS80_Start=1;		
		}
		*/
		EA=1;
	}else 	//RC5编码
	{
		//第一次进入中断前, 定时1/4位的时间:445us, 以后则定时一位时间1.778ms
	    //即在3/4位时间时, 判断该位是1还是0
	    //实际测试中, 位时间只在1.651ms(+- 1ms), 定时1/4位的时间:413us
	    bit in = ~IR_RXD; //一体化解码后, 有载频部分变为低电平, 即低电平实际为1, 高电平实际为0
	    //设置定时器初值
	    //模式1: TH0 = (2^16 - (1651/1.085)) / 2^8 = (65536 - 1651/1.085) / 256 =  250;
	    //TL0 = (65536 - 1651/1.085) % 256 = 14
	    TH0 = 250;
	    TL0 = 14;
	    
	    YKDatas[YKtype] = YKDatas[YKtype] | in; //将数据放入最低位
	    YKcount++;
	    if(YKcount == 1 || YKcount == 2)
	    {
	        if(in == 0)  //起始两位必须都为1
	        {
	            TR0 = 0;
	            //EnableINT0(1);
				/*调试使用,发送错误提示信息.
				Send_String_Com("Error:",6);Send_Char_Com(HEX[YKcount]);
				Send_String_Com("\r\n",2);
				*/
				YKReset();
	            return;
	        }
	    }
	    if(YKcount == 3) //获取完Start bits 和control bit, 共3位
	    {
	        YKtype = 1;
	    }
	    else if((YKcount>=4) && (YKcount<=8)) //获取完system bits, 共5位
	    {
	        if(YKDatas[1] != 0) //系统码全为0才是正确的
	        {
	            TR0 = 0;
	            //EnableINT0(1);
				/*调试使用,发送错误提示信息.
				Send_String_Com("Error:",6);Send_Char_Com(HEX[YKcount]);
				Send_String_Com("\r\n",2);
				*/
				YKReset();
	            return;
	        }
	        YKtype = 2;
	    }
	    else if(YKcount == 14) //获取完commond bits, 共6位
	    {
	        YKtype = 3;
	    }
	    else if(YKtype == 3) //等待最后1/4位时间结束, 实际延时1位时间
	    {
	        TR0 = 0; //接收结束, 停止定时器0
	        YKSuccess();
	        return; 
	    }
	    else   //将数据左移一位, 以便将一下位数据并于最低位
	    {
	        YKDatas[YKtype] = YKDatas[YKtype] << 1;
	    }
	}	
}

void INT0Count() interrupt 0		//INT0中断,接收并解码
{
	EX1=0;		//红外接收时,屏蔽掉INT1中断
	if(~IRMode)		//RC5编码
	{
	    EnableINT0(0);  //关闭外部中断0
	    //模式1: TH0 = (2^16 - (413/1.085)) / 2^8 = (65536 - 381) / 256 =  255;
	    //TL0 = (65536 - 381) % 256 = 131
	    TH0 = 255;
	    TL0 = 131;
	    TR0 = 1;  //启动定时器0, 定时1/4位周期
	}
	else			//RECS80编码
	{
		EA=0;
		IRbit++;
		IE0=0;				//清除INT0中断标志IE0
	
		if(IRbit==1)		//红外引导码
		{
			Cnt256=0;		//开始计时
			TR0=1;
		}
		else if(IRbit==2)
		{
			TR0=0;
			if(Cnt256>=20) //正确的引导码
			{
				Cnt256=0;Value=0;			
				TR0=1;
			}else 	//错误的引导码
			{
				Cnt256=0;IRbit=0;Value=0;
				Delay(100);
				EA=1;EX1=0;		//恢复INT1中断
				return;
			}
		}else if(IRbit<=10)
		{
			TR0=0;
			if(Cnt256<6) Value=Value & 0x7F;
			else if(Cnt256>=6) Value=Value | 0x80;
			Value=Value>>1;
			if(IRbit==10)
			{
				UserID=Value;
				Value=0;
			}
			Cnt256=0;
			TR0=1;
		}else if(IRbit<=18)
		{
			TR0=0;
			if(Cnt256<6) Value=Value & 0x7F;
			else if(Cnt256>=6) Value=Value | 0x80;
			Value=Value>>1;
			if(IRbit==18)
			{
				rUserID=Value;
				Value=0;
			}
			Cnt256=0;
			TR0=1;
		}else if(IRbit<=26)
		{
			TR0=0;
			if(Cnt256<6) Value=Value & 0x7F;
			else if(Cnt256>=6) Value=Value | 0x80;
			Value=Value>>1;
			if(IRbit==26)
			{
				OprCode=Value;
				Value=0;
			}
			Cnt256=0;
			TR0=1;
		}else if(IRbit<=33)
		{
			TR0=0;
			if(Cnt256<6) Value=Value & 0x7F;
			else if(Cnt256>=6) Value=Value | 0x80;
			Value=Value>>1;
			if(IRbit==33)
			{
				rOprCode=Value;
				Value=0;IRbit=0;
				//***************************************************************
				Send_String_Com("H",1);
				Send_Char_Com(HEX[UserID/16]);Send_Char_Com(HEX[UserID%16]);
				Send_Char_Com(HEX[rUserID/16]);Send_Char_Com(HEX[rUserID%16]);
				Send_Char_Com(HEX[OprCode/16]);Send_Char_Com(HEX[OprCode%16]);
				Send_Char_Com(HEX[rOprCode/16]);Send_Char_Com(HEX[rOprCode%16]);
				Send_String_Com("\r\n",2);
				REC_LED=1;Delay(200);REC_LED=0;	//灯闪
				TR0=0;Cnt256=0;EA=1;EX1=0;		//恢复INT1中断
				return ;
				//****************************************************************
			}
			Cnt256=0;
			TR0=1;
		}
		EA=1;
	}
	EX1=0;		//恢复INT1中断
}

void EnableINT0(bit En)				//设置INT0工作模式
{
//	EA=0;
	if(~IRMode) IT0=0;else IT0=1;	//RC5编码采用INT0采用低电平触发中断;RECS80采用后沿触发.
	EX0=En;							//开/关INT0中断
//	EA=1;
}

void EnableINT1(bit En)				//使能INT1中断.
{
	IT1=1;							//INT1采用后沿触发.
	if (En)	EX1=1;else 	EX1=0;		//开启/关闭INT1中断
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -