视频讲解
简介
红外线接收管是将红外线光信号变成电信号的半导体器件,它的核心部件是一个特殊材料的PN结,和普通二极管相比,在结构上采取了大的改变,红外线接收管为了更多更大面积的接受入射光线,PN结面积尽量做的比较大,电极面积尽量减小,而且PN结的结深很浅,一般小于1微米。红外线接收二极管是在反向电压作用之下工作的。没有光照时,反向电流很小(一般小于0.1微安),称为暗电流。当有红外线光照时,携带能量的红外线光子进入PN结后,把能量传给共价键上的束缚电子,使部分电子挣脱共价键,从而产生电子---空穴对(简称:光生载流子)。它们在反向电压作用下参加漂移运动,使反向电流明显变大,光的强度越大,反向电流也越大。这种特性称为“光电导”。红外线接收二极管在一般照度的光线照射下,所产生的电流叫光电流。如果在外电路上接上负载,负载上就获得了电信号,而且这个电信号随着光的变化而相应变化。
我们一般使用的红外接收头,是跟成品的红外遥控器搭配使用,有些遥控器的外观有所不同,但其原理一致,如下图所示:
红外遥控采用的是NEC通信协议,所以我们只需要根据NEC协议在单片机当中写出接收部分的程序即可跟红外遥控进行通信。
NEC红外传输协议详解
NEC红外传输协议是一种广泛应用于家电遥控器的通信协议。它使用38KHz的红外载波频率,通过编码每一位数据的脉冲间隔来表示不同的逻辑位,这种编码方式与许多单总线IC的通信方式相似。NEC协议的特点是简洁且易于实现,使其成为红外遥控领域的常用标准之一。
NEC协议的编码方式
NEC协议采用脉冲间隔编码,其中逻辑"0"由562.5µs的有效脉冲加上562.5µs的空闲间隔组成,总时长为1.125ms。逻辑"1"则由562.5µs的有效脉冲加上1.6875ms的空闲间隔组成,总时长为2.25ms。这种编码方式确保了信号的清晰传输和高效解码。
协议格式
NEC协议的数据帧由起始位、地址码、地址码反码、命令码和命令码反码组成。起始位由9ms的脉冲(AGC脉冲)和4.5ms的空闲间隔组成,用作每一帧的起始标志。地址码和命令码各占8位,最低有效位(LSB)先发送。地址码反码和命令码反码用于验证接收信息的准确性,其值与相应的地址码和命令码相反。
重复码
当遥控器上的按键持续被按下时,NEC协议不会重复发送命令码,而是每隔110ms发送一次重复码。重复码由9ms的AGC脉冲、2.25ms的空闲间隔和560µs的脉冲组成。
通信流程
红外接收管先接收到9ms的低电平,再空闲4.5ms由上拉电阻上拉至高电平,称为引导码,接下来接收4个八位的数据,地址码、地址反码、命令码、命令反码,最后接收结束码来标志此次通信的结束。
因为有反码的形式存在,所以我们可以通过计算对比地码与地反码、命令码与命令反码的方式来进行数据校验,防止通信错误。
软件流程图
程序分析
IR.c
#include "IR.h"
uint IrTime; //红外接收计时变量
uchar IrValue[4]; //红外接收数组
uchar ir_value;
//初始化红外线接收(外部中断0)
void IrInit()
{
EA = 1;
EX0 = 1;
IT0 = 1;
}
//延时函数
void delay(uint i)
{
while(i--);
}
/*
*******红外信号解析(外部中断)
45 46 47
44 40 43
07 15 09
16 19 0D
0C 18 5E
08 1C 5A
42 52 4A
*/
void ReadIr() interrupt 0
{
uchar j,k;
uint err;
IrTime=0;
delay(700); //7ms
if(IRIN==0) //确认是否真的接收到正确的信号
{
err=1000; //1000*10us=10ms,超过说明接收到错误的信号
/*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
侯,程序死在这里*/
while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去
{
delay(1);
err--;
}
if(IRIN==1) //如果正确等到9ms低电平
{
err=500;
while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去
{
delay(1);
err--;
}
for(k=0;k<4;k++) //共有4组数据
{
for(j=0;j<8;j++) //接收一组数据
{
err=60;
while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
{
delay(1);
err--;
}
err=500;
while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
{
delay(10); //0.1ms
IrTime++;
err--;
if(IrTime>30)
{
return;
}
}
IrValue[k]>>=1; //k表示第几组数据
if(IrTime>=8) //如果高电平出现大于565us,那么是1
{
IrValue[k]|=0x80;
}
IrTime=0; //用完时间要重新赋值
}
}
}
if(IrValue[2]!=~IrValue[3]) //数据接收错误
{
return;
}
if(IrValue[2] == 0x0c) //数字1
{
ir_value = 1;
}
if(IrValue[2] == 0x18) //数字2
{
ir_value = 2;
}
if(IrValue[2] == 0x5e) //数字3
{
ir_value = 3;
}
if(IrValue[2] == 0x08) //数字4
{
ir_value = 4;
}
if(IrValue[2] == 0x1c) //数字5
{
ir_value = 5;
}
if(IrValue[2] == 0x5a) //数字6
{
ir_value = 6;
}
if(IrValue[2] == 0x42) //数字7
{
ir_value = 7;
}
if(IrValue[2] == 0x52) //数字8
{
ir_value = 8;
}
if(IrValue[2] == 0x4a) //数字9
{
ir_value = 9;
}
}
}
IR.h
#ifndef __IR_H__
#define __IR_H__
/**********************************
包含头文件
**********************************/
#include "main.h"
/**********************************
PIN口定义
**********************************/
sbit IRIN = P3^2; //红外发射引脚
/**********************************
变量定义
**********************************/
extern uchar IrValue[4]; //红外接收数组
extern uchar ir_value;
/**********************************
函数声明
**********************************/
void IrInit(); //初始化红外线接收(外部中断0)
void delay(uint i); //延时函数
#endif