51单片机NEC红外遥控器解码

【前言】
红外遥控器常用的调制制式主要分为两种,这里主要讲解以NEC调制方式的遥控器解码过程。

废话不多说,直接上时序图!( 更多详细资料自行查询)

总时序图:


前导码:


' 0 ' 和 ' 1 ' 编码表示:



【解码思路】
-----1、 使用定时器计算高低电平的时间
-----2、 使用数组存放一组完整的电平时间编码
-----3、 计算电平的时长
-----4、 组合数据,获得编码值,存放于数组
-----5、 LCD1602管显示

【编写程序】

/*--------------------------------------------------------
程序功能: 51红外遥控器解码程序
功能详情: 遥控解码后送数码管依次显示,共4字节	.( 12MHz晶振 )
编写时间: 2017/9/7
编写人:	吴**
--------------------------------------------------------*/

#include<reg52.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
#define display_data P0

sbit LCD_RS=P1^0;
sbit LCD_RW=P1^1;
sbit LCD_EN=P1^2;					   

uchar irtime = 0;
uchar startflag = 0;	// 起始标志位
uchar ir_rc_ok = 0;		// 红外高/低电平时间接收完成标志位 
uchar bitnum = 0;
uchar ir_change_ok = 0;		// 转码完成标志位

uchar irdata[33];		// 电平时间数组
uchar ircode[4];	// 遥控解码数组

// 字符编码
uchar str[17]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',' '};

/********* 延时函数 **********/
void delayms(uint xms)
{
	uint i,j;
	for(i=xms;i>0;i--)
		for(j=110;j>0;j--);
}	  

/********** 系统初始化 ********/
void sysinit()
{
	// 初始化定时器
	TMOD = 0x02;	// 设置定时器0为工作方式2 (0~255)
	TH0 = 0x00;		// 赋初值
	TL0 = 0x00;
	TR0 = 1;	// 启动定时器0
	ET0 = 1;	// 使能定时器0

	// 初始换外部中断1
	IT1 = 1;	//	下降沿触发
	EX1 = 1;		// 开外部中断0
	EA = 1;		// 开总中断
}

/************ 转换编码 *************/
void changecode()
{
	uchar k = 1;
	uchar i,j;
	uchar value;
	if(ir_rc_ok ==1)		// 如果ir接收完成就进行转码
	{
		for(i=0;i<4;i++)	// 获取前导码后的4个字节数据
		{
			for(j=0;j<8;j++)
			{
				value = value>>1;	// 因低位在前,所以需右移 
				if(irdata[k]>6&&irdata[k]<10)		// 判断数据是否为" 1 ",从第2位开始接收
				{
					value |= 0x80;
				}
				k++;
			}
			ircode[i] = value;		// 存储1个字节数据 
		}
		ir_change_ok = 1;		// 编码转换完成标志位
		ir_rc_ok = 0;		// ir接收标志复位	
	}
}
/********** 1602写指令 ***********/
void write_com(uchar com)	  
{
	LCD_RS=0;		   //RS =‘low’为写指令
	LCD_RW=0;
	display_data=com;
	delayms(5);
	LCD_EN=1;
	delayms(5);
	LCD_EN=0;			
}

/*********** 1602写数据 ***********/
void write_data(uchar wdata)	
{
	LCD_RS=1;			//RS ='high'为写数据
	LCD_RW=0;
	display_data=wdata;
	delayms(3);
	LCD_EN=1;
	delayms(5);
	LCD_EN=0;			
}

/*********** 1602显示屏初始化 ***********/
void disinit()
{
	LCD_EN=0;			 		 //初始化使能
	write_com(0x38);	 		 //设置显示模式
	write_com(0x0f);	 		 //设置显示开/关及光标
	write_com(0x06);	  		//设置指针位置及移屏
	write_com(0x80); 	  //数据指针初始化( +0x10 指针移至显示区外)
}

/************* 1602显示解码结果 *****************/
void display()
{
	uchar num,high,low;
	if(ir_change_ok == 1)		// 判断编码是否转换完毕
	{
		ir_change_ok = 0;
		write_com(0x80);		// 重复调用时,显示指针复位
		for(num=0;num<4;num++)
		{
			high = ircode[num]/16;
			low = ircode[num]%16;
			write_data(str[high]);
			write_data(str[low]);
			write_data(str[16]);	// 显示空格
		}
	}
}

/********** 主函数 *************/
void main()
{
	sysinit();		// 初始化
	disinit();		// 显示屏初始化
	while(1)
	{
		changecode();	// 获取编码
		display();		// 显示解码后的编码
	}
}

/********* 定时器0中断服务函数 ***********/
void t0()interrupt 1
{
	irtime++;
}

/********* 外部中断1服务函数 ***********/
void exint1() interrupt 2
{
	if(startflag)	
	{
		if(irtime>32) 		// 检测前导码	
		{
			bitnum=0;			
		}			
		
		irdata[bitnum]=irtime;		// 从前导码开始接收数据
		irtime=0;
		bitnum++;
		
		if(bitnum==33)		// 前导码+4字节数据,共 33 比特 
		{
			bitnum=0;
			ir_rc_ok = 1;
		}		

	}
	else
	{
		startflag = 1;
		irtime = 0;
	}
}


评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值