1. 红外接收1.1 说明1.2 NEC协议1.3 关于红外接收的波形1.4 解码1.4 红外对射思考2. 红外发射2.1 红外发射管参数2.2 红外发射电路搭建2.3 程序设计2.5 实验结果2.4 红外发射电路目前遇到的问题3. 总结
我们采用的是 HS0038B 这个红外一体化接收头 ,所以在使用时需要按照具体协议来进行解析。
当连接好设备后就可以进行数据分析了,首先看一段数据
HS0038B 这个红外一体化接收头,当收到有载波的信号的时候,会输出一个低电平,空闲的时候会输出高电平,我们用逻辑分析仪抓出来一个红外按键通过HS0038B 解码后的图形来了解一下。
NEC 协议的数据格式包括了引导码、用户码、用户码(或者用户码反码)、按键键码和键码反码,最后一个停止位。停止位主要起隔离作用,一般不进行判断,编程时我们也不予理会。其中数据编码总共是 4 个字节 32 位。
第一个字节是用户码,第二个字节可能也是用户码,或者是用户码的反码,具体由生产商决定,第三个字节就是当前按键的键数据码,而第四个字节是键数据码的反码,可用于对数据的纠错。
这个 NEC 协议,表示数据的方式不像我们之前学过的比如 UART 那样直观,而是每一位数据本身也需要进行编码,编码后再进行载波调制。
通过逻辑分析仪对红外接收管上的数据采集,基本上可以对数据的采集进行一个比较准确的时序图。
关于红外接收管的电路连接其实很简单,就是接电源和数据引脚即可
以下就是我们通过逻辑分析仪采集到的波形
通过对数据的采集,我们可以对其进行解码。
一般来说,解码放在中断中,这里的中断一般是GPIO的上升沿或者下降沿中断。对于一般的程序而言,这样的设计是没有问题的。其原理可以描述如下:
(1)当来一个一个下降沿中断时,进入中断处理函数,处理事件
(2)当延时6ms后检测到该电平依然为低电平,该事件有效
(3)收集四组数据:用户码,用户反码,按键码,按键反码,存到数组中
(4)校验数据,一般而言,都是可以先校验按键码与按键反码是否正确,若正确表示解码正确
(5)处理按键码
以上是处理该问题的基本办法,编码如下:
//NEC 红外0数据格式 解析
int IR0_IN(void)
{
unsigned char j,k,N=;
// EX0 = 0;
//第一步:判断红外是否有效
if (IR0IN == )
{
//信号无效
return -1;
}
//第二步:信号有效,延时检测,确认IR信号出现
ET0 = ;
IRdelay();
if (IR0IN == )
{
//不是有效的电平
ET0 = ;
return -2;
}
//第三步:等IR变为高电平,跳过9ms的前导低电平信号。
while (!IR0IN)
{
IRdelay();
}
//收集四组数据:用户码,用户反码,按键码,按键反码
for (j=;j<;j++)
{
for (k=;k<;k++) //每组数据有8位
{
//等 IR 变为低电平,跳过4.5ms的前导高电平信号。
while (IR0IN)
{
IRdelay();
}
//等 IR 变为高电平
while (!IR0IN)
{
IRdelay();
}
//计算IR高电平时长
while (IR0IN)
{
//0.14ms计数过长自动离开。
IRdelay();
N++;
if (N>=)
{
ET0=;
return -3;
}
}
IR0COM[j]=IR0COM[j] >> ; //数据最高位补“0”
if (N>=) {IR0COM[j] = IR0COM[j] | 0x80;} //数据最高位补“1”
N=;
}//end for k
}//end for j
//按键码是否正确
if (IR0COM[]!=~IR0COM[])
{
ET0 = ;
return -4;
}
ET0 = ;
return ;
}
但是如果需要检测两个红外光,该方法就有缺陷,因为要用到两个中断引脚,这对于单片机来说,是比较困难的。
为了解决这个问题,我们可以采用定时器定时去查询引脚状态的方式进行。
比如我们可以采用定时器0去定时读取电平状态。如果信号有效则保存下来。
所以我们可以采用100us的定时器Timer0进行
void Timer0Init(void) //100微秒@22.1184MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x9A; //设置定时初值
TH0 = 0xA9; //设置定时初值
TF0 = ; //清除TF0标志
TR0 = ; //定时器0开始计时
ET0 = ; //允许T0中断
EA = ;
TR0 = ;
}
定时器开启后,不断的查询两个引脚的状态即可实现该过程。
如果要实现红外对射的功能
目前采用的红外发射管为TSAL6200
通过对红外发射管的研究发现,当红外发射管发出38Khz的波形时,接收管上输出的是低电平,其他情况下,红外接收管上接收的电平为高电平,所以要让红外接收管上的电平为特定的波形,需要采用26us的定时器。
目前由于我手上只有S8550三极管,所以当引脚输出高电平时,三极管不导通,低电平时三极管导通。
根据定时器计算26us的定时器中断
void Timer_Routine(void) interrupt 1
{
TL0 = 0xE8; //设置定时初值
TH0 = 0xFD; //设置定时初值
count++;
if(flag == )
{
OP = ~OP;
}
else
{
OP = ;
}
if(send_ir_flag == )
{
IR1_SEND = OP;
}else
{
IR2_SEND = OP;
}
}
然后主要是按照协议发送数据即可
//红外发射函数
void SendIRdata(char user_data,char key_data)
{
//1.发送开始码 9ms
send_code(,);
//2.发送4.5ms结果码
send_code(,);
//3.发送用户码
send_data(user_data);
//send_code(0,4279);
//4.发送用户反码
send_data(~user_data);
//send_code(0,4279);
//5.发送按键码
send_data(key_data);
//send_code(0,4279);
//6.发送按键反码
send_data(~key_data);
//7.发送结束码
send_code(,);
}
以上就是红外发射的基本情况。
通过逻辑分析仪对数据的采集,我们得到如下的数据
通过放大,可以看到波形的基本情况
该信号基本上是我们发射出来的信号。
调试手段:由于红外发射管发射出来的光线人眼是看不到的,所以可以打开手机摄像头拍红外摄像头,可以看到当红外发射管发射数据时,是有颜色的。
红外发射管发射的距离达不到要求,只能在1m的范围之内数据有效,其他的情况下数据无效。对于该问题,有两点猜测
(1)红外发射与红外接收头不匹配,造成数据没办法很好接收到
(2)红外发射管功率不够
对于以上的测试及调节手段,遇到了一些问题,主要是对硬件部分的不熟悉带来了一些麻烦。其实对于红外接收部分的调试还是很顺利的,只是到了红外接收部分,却遇到了一些问题,其中有一个问题就是由于没有发送结束码,导致数据始终接收不到,后来通过对红外遥控的数据采集,才发现了问题的原因。后来又遇到红外发射管发射距离太短的问题,目前尝试各种办法,无果,所以该问题目前先放一放。