红外解码程序详解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

红外遥控解码程序设计

——————基于uPD6121红外编码制式

红外传感系统是目前应用最为广泛的遥控系统,一个红外遥控系统可分为发射和接收两部分组成,发射端称之为红外遥控器,一般由矩阵键盘,红外编码调制芯片和红外发射管组成;接收端用一体化红外接收头即可,这个东东内置光电放大器和解调部分,信号接收之后一般很微弱须放大后才可解码,为有效发射出去得先托付在载波上所以需经历调制、解调的过程,其实对于发射部分主要工作在于编码,而对于编码方式只有几种主流方式,而目前国内大部分均为uPD6121编码方式(日本NEC公司搞出来的。。),所以我们只须弄清楚这种编码的时序,即可写出万能的红外解码程序,只要是基于这种编码方式的遥控器(家里的电视、空调、电扇遥控器)都可以用该程序来解码(这点也充分证明了C语言的高移植性啊。。)

这种编码的格式其实很简单,开头是一个引导码,人家芯片在编码时将其设计成9ms的高电平和4.5ms的低电平,也就是说你必须跳过这段引导码之后才会接收到数据,第一个问题来了:为什么要加这段引导码?因为红外传感是非常容易受到干扰的,如果直接传送数据很可能并非发送端的信号,很可能来自其他辐射,后面设计程序时会遇到这个问题。所以我们在写程序时在引导码时可以加入检测代码,如果是引导码则继续接收,否则跳出。第二个问题就是:接收数据时我们用外部中断接收,这是考虑到CPU 的执行效率,如果你在主函数里接收数据,就好比CPU一直在问:你接收到数据没?

你接收到没?..很明显不靠谱,和串口通信一样,接收数据用中断这是经验,有利于单片机的执行效率。第三个要注意的就是红外接收端和编码发送的数据是反向的!这点很重要,我看很多资料没有写明这点,让很多童鞋疑惑不解,也就是说引导码编码时确实是9ms高电平和4.5ms 的低电平,但是到了接收端是9ms的低电平和4.5ms的高电平,所以我们在解码时就得注意引导码高电平出现的顺序。对于编码格式,引导码后接了4个字节的数据,前两个字节为用户码和用户反码,简单点说就是器件地址;后两字节为操作码和操作反码,就是我们真正需要的数据。图为发送端编码格式,注意接收到的已反向!

说到这里,可能会想到既然第三个字节才是我们真正的操作数据,那么我设置一个4字节数组ircode[4] 把四字节数据依次装进去,那么ircode[2]就是数据码,ircode[3]就是其反码,这样我们可以通过判断ircode[2]是否等于ircode[3]的求反?如果是,则说明接收的数据是对的!这样可以作为接收是否正确的检测代码。最关键的问题来了:如何判断接收的是‘1’还是‘0’? uPD6121编码中说明:一个逻辑单位前0.565ms 为低电平,接着为高电平,如果高电平持续时间为0.565Ms则说明为逻辑‘1’,如果高电平持续超过0.565ms 则说明为逻辑‘0’(接收端反向后的结果,实际编码时相反)。图为编码格式,解码应反向。

所以理清红外解码的整体流程如下:

跳过引导码9ms————跳过引导码4.5ms——循环接收四字节数据(每个字节八位,每位都须判断高还是低电平)

好了,思路有了,开始写程序,代码如下:

#include

#include"delay.h"

#include"lcd.h"

#define uint unsigned int

#define uchar unsigned char

sbit irin=P3^2;

sbit BEEP=P1^5;

sbit lcdrw=P2^5;

sbit lcdrs=P2^6;

sbit lcden=P2^7;

uchar ircode[4];

uchar send_da;

uchar table[]="IR_test:";

uint k,i,j;

void ir_ini();

void write_da(uchar da);

void write_comd(uchar comd);

void beep();

void delay(unsigned char x) //x*0.14MS

{

unsigned char i;

while(x--)

{

for (i = 0; i<13; i++) {;}

}

}

void main()

{

uint i;

ir_ini();

serial_ini();

lcd_ini();

for(i=0;i<8;i++)

{

write_da(table[i]);

msdelay(1);

}

while(1);

}

void ir_ini()

{

EA=1;

EX0=1;

IT0=1;

}

void ir() interrupt 0

{

EX0=0; //关闭外部中断

while(!irin) //跳过9ms低电平

{

delay(1);

}

while(irin) //跳过4.5ms高电平

{

delay(1);

}

for(i=0;i<4;i++) //4个字节的数据,前16位为用户码和其反码,后16位为操作码和其反码

{

for(j=0;j<8;j++) //每字节八位

{

while(!irin); //等待irin出现高电平

msdelay(1); //短暂延时一下再判断

if(irin) //irin为logic '1'

相关文档
最新文档