51单片机外设篇:红外通信

红外遥控

人机界面
当面操作的:按键、旋钮 / 触摸按键、触摸屏
遥控操作的:红外遥控、433M-2.4G无线通信、蓝牙-WIFI-Zigbee-4G-LoRa等无线网络

红外遥控是利用红外光进行通信的设备,由红外LED将调制后的信号发出,由专用的红外接收头进行解调输出。

通信方式:单工,异步;

红外LED波长:940nm;

通信协议标准:NEC标准(常用)

接收端原理图:

一体集成式接收头内部已经内置了红外载波解调功能,从IRD引脚出来的就是通信的二进制信号。所以单片机的IO可以直接接IRD引脚来读取红外信号中的通信信息。所以38KHz的载波的调制和解调过程对编程是透明的。
红外接收头内部本身是有个反相的,意思就是:平时发送方无发送信号时接收到的是1,发送方有发送载波时接收头IRD引脚输出的是0,这对我们写代码有影响,后面在看协议时序图时刚好是反的。

原理概述

红外通信由发送端和接收端两部分组成,发送端对数据进行编码,然后调制成一系列的脉冲信号,然后通过带有红外发射管的发射电路发送脉冲信号,即红外信号。接收端完成对脉冲信号的接收、放大、检波、整形,然后解调出编码信号,对其解码获取到发送的数据。具体的如下图所示:

NEC协议

NEC协议逻辑1与逻辑0的表示如下图所示:

– 逻辑1为2.25ms,脉冲时间560us。
– 逻辑0为1.12ms,脉冲时间560us。根据脉冲时间长短来解码。推荐载波占空比为1/3至1/4。

NEC协议格式如下图所示:

NEC协议中,首次是9ms的高电平脉冲,其后是4.5ms的低电平,接下来就是8bit的地址码(从低有效位开始发),而后是8bit的地址码的反码(主要是用于校验是否出错)。然后是8bit 的命令码(也是从低有效位开始发),而后也是8bit 的命令码的反码。

以上是一个指令码的序列,但当您长时间按住遥控按钮,在这这种情况下,使用NEC协议的红外遥控器将会发射一个以110ms为周期的重复码。也就是说,每一次用户按下遥控器按钮,遥控器在发送一次指令码后,就不会再发送指令码了,而是发送一段重复码。如下图:

重复码由9ms高电平和2.25ms的低电平以及560us的高电平组成,如下图所示:

需要注意的是:1838红外接收器为了提高接受灵敏度。输入高电平,其输出的是相反的低电平。

代码实现

        

#include "ir.h"

// 全局变量在哪个C文件中用就在哪个C文件中定义
// 不能放在头文件中定义
// 如果在多个C文件中都要用到同一个全局变量,应该在一个主要的C文件中定义
// 然后其他C文件中extern声明即可
sbit IRIN = P3^2;
unsigned char IrValue[5];  // IrValue的0-3用来放原始数据,4用来放经过校验确认无误的键值
unsigned char Time;


void DelayMs(unsigned int x)   //0.14ms误差 0us
{
	unsigned char i;
	while(x--)
	{
		for (i = 0; i<13; i++)
		{}
	}
}

void IrInit(void)
{
	IT0=1;//下降沿触发
	EX0=1;//打开中断0允许
	EA=1;	//打开总中断

	IRIN=1;//初始化端口
}


void ReadIr() interrupt 0
{
	unsigned char j,k;
	unsigned int err;
	Time = 0;					 
	DelayMs(40);			// 136us*40


	if (IRIN == 0)		//确认是否真的接收到正确的信号
	{	 		
		err = 1000;				//1000*10us=10ms,超过说明接收到错误的信号
		/*当两个条件都为真时循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
		侯,程序死在这里*/	
		while ((IRIN==0) && (err>0))	//等待前面9ms的低电平过去  		
		{			
			DelayMs(1);			// 136us
			err--;
		} 
		if (IRIN == 1)			//如果正确等到9ms低电平
		{
			err = 500;
			while ((IRIN==1) && (err>0))		 //等待4.5ms的起始高电平过去
			{
				DelayMs(1);
				err--;
			}
			for (k=0; k<4; k++)		//共有4组数据
			{			
				for (j=0; j<8; j++)	//接收一组数据
				{
					err = 60;		
					while ((IRIN==0) && (err>0))//等待信号前面的560us低电平过去
					{
						DelayMs(1);
						err--;
					}
					err = 500;
					while ((IRIN==1) && (err>0))	 //计算高电平的时间长度。
					{
						DelayMs(1);//0.14ms
						Time++;
						err--;
						if (Time > 30)
						{
							EX0 = 1;
							return;
						}
					}
					IrValue[k] >>= 1;	 //k表示第几组数据
					if (Time >= 8)			//如果高电平出现大于565us,那么是1
					{
						IrValue[k] |= 0x80;
					}
					Time = 0;		//用完时间要重新赋值							
				}
			}
		}
		if (IrValue[2] == ~IrValue[3])
		{
			IrValue[4] = IrValue[2];
			return;
		}
	}			
}
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值