12.1  红外接收管的简单分析

红外接收是一种技术,用于接收和解码红外线信号。红外线是一种电磁辐射,位于可见光谱的红色端之外,具有较长的波长。红外接收器通常由红外光电二极管或红外光电三极管组成,用于将红外线信号转换为电信号。这些接收器可以用于许多应用,如遥控器、红外传感器和红外通信等。当红外线信号被接收器接收后,它可以被解码并用于执行特定的操作,比如控制电子设备或检测物体的存在。

由上图所示,VS1838是一种常用的红外线接收器模块,用于接收和解码红外线信号。它是一种低成本、高性能的红外接收器,广泛应用于遥控器、红外传感器和红外通信等领域。

VS1838模块采用了集成红外接收器、预放大器、信号解码电路等功能于一体的设计。它能够接收38kHz调制频率的红外线信号,并将其转换为电信号输出。VS1838模块具有高灵敏度和良好的抗干扰能力,能够在较长距离内接收到红外线信号,并且对光照强度变化的抗干扰能力较强。

VS1838模块通常由三个引脚组成,分别是VCC(电源正极)、GND(电源负极)和OUT(信号输出)。它可以通过连接到微控制器或其他电子设备上来实现红外信号的接收和解码。

在使用VS1838模块时,通常需要结合相应的红外遥控器来发送红外信号。当红外信号由遥控器发射并被VS1838模块接收到后,模块会将信号解码,并将解码后的数据通过OUT引脚输出给微控制器或其他电子设备进行处理。

12.2  VS1838的详细分析

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低。红外遥控不具有穿过障碍物去控制对象的能力。VS1838/BHS0038红外接收头,内部集成了监测,放大,滤波,解调等一系列电路处理输出基带信号。其实HS0038 和VS1838B 没什么区别,只是相比0038的性能更好

原理介绍

原始信号就是我们要发送的一个数据“0”位或者一位数据“1”位,而所谓 38K 载波就是频率为 38K 的方波信号,调制后信号就是最终我们发射出去的波形。我们使用原始信号来控制 38K 载波,当信号是数据“0”的时候,38K 载波毫无保留的全部发送出去,当信号是数据“1”的时候,不发送任何载波信号。

要想让 VS1838识别到 38K的红外信号,那么这个 38K 的载波必须要大于 10 个周期,这就限定了红外通信的基带信号的比特率必须不能高于 3800,那如果把串口输出的信号直接用 38K 调制的话,波特率也就不能高于 3800。

我们所学的是NEC协议的,其特征有:

  1. 8位地址和8位指令长度
  2. 地址和命令2次传输(确保可靠性)
  3. PWM脉冲位置调制,以发射红外载波的占空比代表“0”和“1”
  4. 载波频率为38KHZ
  5. 位时间为1.125ms或2.25ms

NEC码的位定义:一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms(560us脉冲+1680us低电平),一个逻辑0的传输需要1.125ms(560us的脉冲+560us低电平)。

NEC遥控指令的数据格式为:同步码头、地址码、地址反码、控制码、控制反码。同步码由一个9ms的低电平和一个4.5ms的高电平组成,地址码、地址反码、控制码、控制反码都是8位数据格式。按照低位在前,高位在后的顺序发送。采用反码是为了增加传输的可靠性。

电路设计

注意:红外传感器输出需要接上拉电阻,防止空载时外部干扰

 

外观尺寸

12.3  红外接收的驱动程序

#include "infrared.h"
uchar gired_data[4];//存储4个字节接收码(地址码+地址反码+控制码+控制反码)
/*******************************************************************************
* 函 数 名         : ired_init
* 函数功能		   : 红外端口初始化函数,外部中断0配置 
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void ired_init(void)
{
	IT0=1;	//下降沿触发
	EX0=1;	//打开中断0允许
	EA=1;	//打开总中断
	IRED=1;	//初始化端口
}
void infrared() interrupt 0	//外部中断0服务函数
{
	uchar ired_high_time=0;
	uint time_cnt=0;
	uchar i=0,j=0;
	if(IRED==0)
	{
		time_cnt=1000;
		while((!IRED)&&(time_cnt))//等待引导信号9ms低电平结束,若超过10ms强制退出
		{
			usleep(1);//延时约10us
			time_cnt--;
			if(time_cnt==0)return;		
		}
		if(IRED)//引导信号9ms低电平已过,进入4.5ms高电平
		{
			time_cnt=500;
			while(IRED&&time_cnt)//等待引导信号4.5ms高电平结束,若超过5ms强制退出
			{
				usleep(1);
				time_cnt--;
				if(time_cnt==0)return;	
			}
			for(i=0;i<4;i++)//循环4次,读取4个字节数据
			{
				for(j=0;j<8;j++)//循环8次读取每位数据即一个字节
				{
					time_cnt=600;
					while((IRED==0)&&time_cnt)//等待数据1或0前面的0.56ms结束,若超过6ms强制退出
					{
						usleep(1);
						time_cnt--;
						if(time_cnt==0)return;	
					}
					time_cnt=20;
					while(IRED)//等待数据1或0后面的高电平结束,若超过2ms强制退出
					{
						usleep(10);//约0.1ms
						ired_high_time++;
						if(ired_high_time>20)return;	
					}
					gired_data[i]>>=1;//先读取的为低位,然后是高位
					if(ired_high_time>=8)//如果高电平时间大于0.8ms,数据则为1,否则为0
						gired_data[i]|=0x80;
					ired_high_time=0;//重新清零,等待下一次计算时间
				}
			}
		}
		if(gired_data[2]!=~gired_data[3])//校验控制码与反码,错误则返回
		{
			for(i=0;i<4;i++)
				gired_data[i]=0;
			return;	
		}
	}		
}

 

发表回复

后才能评论