红外解码讲解
- 格式: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
这个程序用中断的优点是主程序可以做很多其他的事情,而不会干扰到红外接收。
这种思路可以借鉴,但算法未必优秀,希望用户跟帖发表意见或者建议。