红外解码讲解

  • 格式:pdf
  • 大小:259.25 KB
  • 文档页数:5

红外解码一直是单片机中应用较多的,需要设备加装专用解码芯片,这就大大减轻了单片机

的负担。需要单片机样例使用延时做红外解码,比较容易理解,但是由于在主程序中使用,

当存在许多中断时就可能造成误码,很多时候误码率较高,成品中则一般使用中断方式。

下面通过TC9012和uPD6121芯片为例大致讲解解码原理:

先看一些遥控器发射波形图

从上图可以看出 4.5ms高电平+4.5ms低电平称为头码,用于识别是否遥控码开始,uPD6121

的头码是9ms+4.5ms,其他的一样,一些datasheet会提及连续发射码的波形图(就是一直

按下某一遥控器按键),这里我们不做分析,仅分析单次按键发射的正个码的波形图。

头码过后可以看到4个8位的数据,我们最终目的就是要把这个 32位(4x8)从一体化红

外接收头提取出来,并转换成16进制数,用于区分不同按键按下得出的不同数值。

在遥控器发射波形中,可以看出,8位数中的0或者1不是用高低电平表示,而是用不同的

低电平的宽度表示,0.565ms表示0,1.69ms表示1,2个位中间还会有一个0.56ms的高电

平(上图阴影部分)。

这个是红外遥控器发射的波形,图中看到的阴影高电平表示载波,一般使用38KHz,遥控器

发射出去的含有载波的红外信号通过一体化红外

接收头处理后得到的是含有载波的反向的波形,也就是没有上图中的阴影部分。大致如下图

一体化红外接收头内部集成了 选频放大(38KHz左右频率增益最大),检波(把38KHz的

载波滤除),放大整形(变成容易检测的矩形波)。

看到如上图波形,表示单片机引脚可以接收到的波形,我们只要通过单片机读取波形

并分析波形的宽度,然后分辨出是头码,还是0或者1,最后整理出这组码的16进制组合。

正确的解码结果是按同一个按键得出的16进制数值是不变化的。通过这个原理,我们可以

分辨出每个按键的键值。

mini80/mini80e样例程序中使用的红外解码程序,应用了外部中断,平时从书上或者网络

上看到的解码一般是单纯解码,整个程序不做其他工作,这种方式可以使用普通io口,用

延时等待的方法判断接收到的是高电平还是低电平,从而判断码值。

这里使用中断方式,外部中断0和定时器,外部中断主要用于接收红外波形下降沿触发,定

时器用于计时(测量2个下降沿的宽度)。由于51单片机外部中断只能用电平触发和下降

沿触发(AVR或PIC等都可以用双向边沿),所以我们选择下降沿触发。

基本原理分析如下,如接收到头码是4.5ms低电平+4.5ms高电平,我们分析 第一个下降沿

到第二个下降沿的宽度是 9ms,我们判断这个头码可以给定一个范围,只要数据在这个范围

内则认为头码是正确的,检测头码正确后接着检测剩下的32位数值,复制一个样例:

/******************************************************************/

0

/* 外部中断0函数 */

/******************************************************************/

void ex0_isr (void) interrupt 0 using 0//外部中断0服务函数

{

static unsigned char i; //接收红外信号处理

static bit startflag; //是否开始处理标志位

if(startflag)

{

if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms

i=0;

irdata=irtime;//存储每个电平的持续时间,用于以后判断

是0还是1

irtime=0;

i++;

if(i==33)

{

irok=1;// 红外接收完毕标志位

i=0;

}

}

else

{irtime=0;startflag=1;}

}

从图上可以看出,1或者0的波形中都包含一个0.56ms的低电平,从图上分析得知,低电

平下降沿到下一个下降沿的宽度是0.56+0.565=1.125ms,高电平则是0.56+1.69=2.25ms,

同样我们也给出一个范围用于区分它们,可以这样识别 (1.125ms + 2.25ms )/ 2=1.68ms

这样可以用1.68ms时长为界区分,如果大于1.68ms,表示高电平1,反之为0。

假设使用12M晶振 定时器的单位数值时1us,使用8位定时器自动重装,将得到每个定时

周期0.256ms的时长, 1.68/0.256=6.59,也就是 定时器0计数次数。

看程序的主要接收部分 startflag 标志位用于测试是不是有触发信号,如果是第一次触发,

执行

else

{irtime=0;startflag=1;}

把定时器的时间数清零,把起始标志置1,下一个下降沿到来 如上图的 4.5ms+4.5ms 后的

下降沿到来执行

if(startflag)

{

if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms

i=0;

判断是否头码,这个范围越大识别率越高,现在的值可以识别 4.5ms+4.5ms 也能识别

9ms+4.5ms,同时抗扰能力越差,可以自行调整测试。如果检测到是头码发出,则把存储区

的值irdata 的地址复位到首地址 即 irdata[0],同时把头码的长度数据 irtime存储到

irdata[0],

然后进接着就是剩下的32位数据了,长度自动存储到数组,数组共33个字节,头码占一个。

k=1;

for(i=0;i<4;i++) //处理4个字节

{

for(j=1;j<=8;j++) //处理1个字节8位

{

cord=irdata[k];

if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值

可以有一定误差

{

value=value|0x80;

}

else

{

value=value;

}

if(j<8)

{

value=value>>1;

}

k++;

}

通过存储的时间长度判断数值时0还是1,k=1,表示从irdata[1] 开始处理,因为第一位

是头码,不是数据,所以跳过去从第二位处理。

程序中这一句就是根据时间长度判断,假设使用12M晶振 定时器的单位数值时1us,使用8

位定时器自动重装,将得到每个定时周期0.256ms的时长, 1.68/0.256=6.59,也就是 定

时器0计数次数。 这里取接近整数值 7

if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定

误差

0

这个程序没有采用严格抗扰。主要是头码部分,我们分析一下

if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms

0

i=0;

假设上一句判断结果是假,表示干扰信号,程序不执行i=0,直接执行下面的存储,因为只有存储到33次后,红外接收完毕的标志位 irok=1;

如果没有 irok=1;主程序中不会处理这些数据,虽然irdata[] 数组中有数据存储,而且这

个时候的数据时混乱的。这里就是这个程序的不足之处,没有进行严格的抗扰,大家可以根

据这个程序进行思考更改,以达到更好的效果,实际测试中,外部的杂波刚才对误码的影响

很小,如果使用2种不同的遥控器同时遥控,则误码的几率会很高。

0

这个程序用中断的优点是主程序可以做很多其他的事情,而不会干扰到红外接收。

这种思路可以借鉴,但算法未必优秀,希望用户跟帖发表意见或者建议。