51单片机实现NEC红外通讯协议的解码

NEC协议中一、0电平的表示

数据格式:
数据格式包括了引导码、用户码、数据码和数据码反码,编码总占32位。数据反码是数据码反相后的编码,编码时可用于对数据的纠错。注意:第二段的用户码也能够在遥控应用电路中被设置成第一段用户码的反码。
在这里插入图片描述
代码实现:
头文件NEC.hweb

#ifndef NEC
#define NEC

#include <reg52.h>

sbit INIR=P3^2;							//红外端口,同时是EX0中断口
void init();						//初始化函数
void delayus();						//延时函数
unsigned char time;					//计算电平长度
unsigned char rec[4];				//存放数据
#endif

主函数main.csvg

#include "NEC.h "
void main()
{
	init();
	while(1);
}
void delayus(unsigned char i)									//延时,单位约10us
{
	while(i--);
}

void init()
{
	EA=1;										//总中断
	EX0=1;									//外部中断0
	IT0=1;									//降低沿触发
	
	INIR=1;									//红外接收端口置1
}

void Read() interrupt 0
{
	unsigned char k,j;
	unsigned int err;
	time=0;
	delayus(700);    //延时7ms
	if(INIR==0)
	{
		err=1000;				 //设置err,规定某一时长循环结束,防止程序陷入死循环
		while((err>0)&&(INIR==0))							//检测起始码9ms低电平
		{
			delayus(1);
			err--;
		}
		if(INIR==1)
		{
			err=500;
			while((INIR==1)&&(err>0))						//检测起始码4.5ms高电平
			{
				delayus(1);
				err--;
			}
			for(k=0;k<4;k++)									//四段数据
			{
				for(j=0;j<8;j++)								//每段中的八位bit数据 
				{
					err=60;
					if((INIR==0)&&(err>0))						//检测0.56us低电平
					{
						delayus(1);
						err--;
					}
					err=300;
					if((INIR==1)&&(err>0))						//计算高电平时长
					{
						delayus(1);
						err--;
						time++;
						if(time>250)							//若是长度大于2.5ms
							return;							//信号错误,提早结束read()函数
					}
					rec[k]>>=1;                 //右移一位,留空以存放一位bit
					if(time>80)
						rec[k]|=0x80;							//最高位赋1
					
					time=0;											//time归零
				}
			}
		}
		if(rec[2]!=~rec[3])								//校验数据是否正确
			return;
	}
}
//rec[0],rec[1]:用户码 rec[2]:数据码 rec[3]:数据反码

考虑硬件实际运行过程当中的偏差,时间没法准确卡点,因此采起一个时间段来估计判断的方法函数