红外解码程序详解
红外遥控原理及解码程序

红外遥控系统原理及单片机红外线遥控是目前使用最广泛的一种通信和遥控手段。
由于红外线遥控装置具有体积小、功耗低、功能强、成本低等特点,因而,继彩电、录像机之后,在录音机、音响设备、空凋机以及玩具等其它小型电器装置上也纷纷采用红外线遥控。
工业设备中,在高压、辐射、有毒气体、粉尘等环境下,采用红外线遥控不仅完全可靠而且能有效地隔离电气干扰。
1红外遥控系统通用红外遥控系统由发射和接收两大部分组成。
应用编/解码专用集成电路芯片来进行控制操作,如图1所示。
发射部分包括键盘矩阵、编码调制、LED红外发送器;接收部分包括光、电转换放大器、解调、解码电路。
图1红外线遥控系统框图2遥控发射器及其编码遥控发射器专用芯片很多,根据编码格式可以分成两大类,这里我们以运用比较广泛,解码比较容易的一类来加以说明,现以日本NEC 的UPD6121G组成发射电路为例说明编码原理(一般家庭用的DVD VCD 音响都使用这种编码方式)。
当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。
这种遥控码具有以下特征:采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms 的组合表示二进制的0” 以脉宽为0.565ms 、间隔1.685ms 、周期为2.25ms 的组合表示二进制的1 ”,其波形如图2所示。
图2遥控码的0”和1 ” (注:所有波形为接收端的与发射相反)上述0”和1 ”组成的32位二进制码经38kHz 的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。
然后再通过红外发射二极 管产生红外线向空间发射,如图3示。
图3遥控信号编码波形图UPD6121G 产生的遥控编 码是连续 的32位二进制 码组,其中前16 位为用户识别码,能区别不同的电器设备,防止不同机种遥控码互相干 扰。
该芯片的用户识别码固定为十六进制01H ;后16位为8位操作码(功 能码)及 其反 码。
UPD6121G 最多额128种不同组 合的编码。
最简单详细的红外解码程序

#include<reg52.h> //包含头文件名sbit IRIN=P3^2; //定义红外接收头的外部接口,即外部中断0sbit BEEP=P1^5; //定义蜂鸣器接口,我的在P1^5unsigned char IRCOM[7]; //定义数组,用来存储红外接收到的数据void delay(unsigned char x){ //延时子程序unsigned char i; //延时约x*0.14mswhile(x--) //不同遥控器应设置不同的参数{for(i=0;i<13;i++){}} //参数的选择咱们先不管,先看这个}void beep(){unsigned char i; //蜂鸣器发声子程序for(i=0;i<100;i++){delay(4); //这个得看你的蜂鸣器内部是否有振荡源BEEP=~BEEP;} //如果没有振荡源就应该输入脉冲信号BEEP=1;}void IR_IN() interrupt 0 using 0 //外部中断0程序{unsigned char j,k,n=0; //先定义变量,记住n=0EX0=0; //禁止中断,以免再次进入中断delay(15); //延时0.14ms*15=2.1msif(IRIN==1) //如果在这期间有高电平说明{ //信号不是来自遥控的,返回主程序EX0=1;return;}while(!IRIN){delay(1);} //死循环,等待9ms前导低电平信号的结束for(j=0;j<4;j++) //一共有4组数据{for(k=0;k<8;k++) //每组数据有8位{while(IRIN){delay(1);} //死循环,等待4.5ms前导高电平的结束while(!IRIN){delay(1);} //等待0.56ms低电平的结束,准备采集数据,while(IRIN) //开始采集数据{delay(1); //延时0.14ms,每过0.14ms时n就加1n++; //用n记录一共有多少个0.14msif(n>=30) //如果超过0.14ms*30=4.2ms{ //说明是乱码,放弃不要EX0=1;return;}}IRCOM[j]=IRCOM[j]>>1; //右移1位,xxxx xxxx变成0xxx xxx//我们先认为这一位数据是0,现在已经送入一位数据了/*你肯定知道_cror_(x,1)和x>>1的区别吧*/if(n>=8){IRCOM[j]=IRCOM[j]|0x80;}//但是如果不是0呢,//0xxx xxxx和0x80相或后变成了1xxx xxxx//这样这一们数据就被记录为1了/*想一下这里为什么是8呢,0.14ms*8=1.12ms,知道了吧*//*这样反复执行8次,8位数据就存在IRCOM[j]中了*//*外层再循环4次,4*8=32位数据码全都在IRCOM[0],IRCOM[1],IRCOM[2],IRCO M[3]中了*/n=0; //n计数后一定要记得清0,否则下一次就不能准确计数了}}if(IRCOM[2]!=~IRCOM[3]) //这里我们判断数据码和数据反码是不是相反{ //因为相反才是正确的,否则就放弃EX0=1;return;}beep();EX0=1; //记得开中断,你可以去掉这句话试一试}void main(){IE=0x81;TCON=0X01;BEEP=1;IRIN=1;while(1);}怎么样,你看懂了吗?作者:任杰。
红外解码方法简述

红外解码方法简述1 引言低速的红外无线传输是一种廉价的无线通讯/控制方案,在家电领域已经广泛使用。
在嵌入式领域,只要工作环境比较优良,数据量小,传输距离较近(5米以内),同样可以采用红外无线传输。
本站的A Tmega16学习板上设计了红外发射管与接收管,配合站长家中闲置的“HITACHI VM101”型电视遥控器,详细分析一下此遥控器的红外编解码原理与单片机解码方法。
2 红外数据序列采集“HITACHI VM101”型电视遥控器结构非常简单,主芯片是M50560-123FP ,外围配有455kHZ 晶体做为主时钟源,一个红外发射管,一个发射管的驱动三极管以及若干阻容器件。
考虑到此芯片为专用芯片,就算找到芯片资料去啃E 文也对以后没有多大帮助,所以站长采用了最直接的方法——软件采集输出电平变化时间间隔。
按照学习板的红外接收管连接方法,当接收到红外数据时,在A Tmega16的INT0脚上电平为高,电平的上升沿变化可以做为数据接收的开始。
普通使用的红外管载波频率为38kHz-40kHz 之间,这样可以先设计一个n 倍于载波频率的定时器计时,在中断触发以后对INT0脚上的高低电平计时,就可以得到一个完整的红外数据序列。
站长首先采用了110kHz 的定时器来采集数据,计时用了一个16位的变量,得到的一个数据序列如下:922 1384 1440 1498 1555 1613 1669 1727 1784 1842 1899 2072 2129 2187 2243 2416 2473 2531 2588 2761 2818 2991 3047 3221 3277 3451 3507 3565 3622 3795 3852 3910 3966 4140 4196 4369 4426 4484 4541 4714 4771 4944 5000 5058 5115 5173 5230 5288 5344 5402 5459 5517 5573 5747 5803 5861 5918 5976 6033 6206 6262 6436 6492 6666 6722 6895 6952 序列一 110kHz 定时采集序列其中相邻两个数的差值即为电平维持时间。
一文教会你红外线遥控器软件解码程序

一文教会你红外线遥控器软件解码程序
红外线一开始发送一段13.5ms的引导码,引导码由9ms的高电平和4.5ms的低电平组成,跟着引导码是系统码,系统反码,按键码,按键反码,如果按着键不放,则遥控器则发送一段重复码,重复码由9ms的高电平,2.25ms的低电平,跟着是一个短脉冲。
#includeat89x52.h
#defineNULL0x00//数据无效
#defineRESET0X01//程序复位
#defineREQUEST0X02//请求信号
#defineACK0x03//应答信号,在接收数据后发送ACK信号表示数据接收正确,
也位请求信号的应答信号
#defineNACK0x04//应答信号,表示接收数据错误
#defineBUSY0x05//忙信号,表示正在忙
#defineFREE0x06//空闲信号,表示处于空闲状态
#defineREAD_IR0x0b//读取红外
#defineSTORE_IR0x0c//保存数据
#defineREAD_KEY0x0d//读取键值
#defineRECEIVE0Xf400//接收缓冲开始地址
#defineSEND0xfa00//发送缓冲开始地址
#defineIR0x50//红外接收缓冲开始地址
#defineHEAD0xaa//数据帧头
#defineTAIL0x55//数据帧尾
#defineSDAP1_7
#defineSCLP1_6
unsigned char xdata *buf1;//接受数据缓冲。
红外解码及超声测距程序

lcden= 0; lcdrs = 1; lcdwr = 0; P0 = date; delay(5); lcden = 1; delay(5); lcden = 0; }
//使能 //选择发送命令 //选择写入 //放入命令 //等待数据稳定 //写入时序 //保持时间
void LCD1602_init() { write_com(0x38);//设置 16X2 显示,5X7 点阵,8 位数据接口 write_com(0x0c);//设置开显示,不显示光标 write_com(0x06);//写一个字符后地址指针加 1 write_com(0x01);//显示清零,数据指针清零 } void ShowString(uchar line,uchar * str) { uchar addr; if(line==0) addr=0x80; if(line==1) addr==0xc0; write_com(addr); while(*str!=’\0’) { write_data(*str++); } } /*-----------------------------------------------主函数-----------------------------------------------*/ main() {
IT0 = 1; EX0 = 1; EA = 1; }
//指定外部中断 0 下降沿触发,INT0 (P3.2)
/*------------------------------------------红外码值处理-----------------------------------------------*/ void Ircordpro(void) { uchar i, j, k; uchar cord,value; k=1; for(i=0;i<4;i++) { for(j=1;j<=8;j++) { cord=irdata[k]; value>>=1; if(cord>7) value|=0x80; k++; } IRcord[i]=value; value=0; } irpro_ok=1; } uint Get_KeyValue() { uint KeyValue; TIM0init(); EX0init(); Ircordpro(); If(irpro_ok) { KeyValue=(IRcode[2]/100)*100+(IRcode[2]%100/10)*10+IRcode[2]%10; //处理完毕标志位置 1 //大于某值为 1,这个和晶振有绝对关系,这里使用 12M 计算,此值可以有一定误差 //处理 1 个字节 8 位 //处理 4 个字节
红外解码程序详解

红外遥控解码程序设计——————基于uPD6121红外编码制式红外传感系统是目前应用最为广泛的遥控系统,一个红外遥控系统可分为发射和接收两部分组成,发射端称之为红外遥控器,一般由矩阵键盘,红外编码调制芯片和红外发射管组成;接收端用一体化红外接收头即可,这个东东内置光电放大器和解调部分,信号接收之后一般很微弱须放大后才可解码,为有效发射出去得先托付在载波上所以需经历调制、解调的过程,其实对于发射部分主要工作在于编码,而对于编码方式只有几种主流方式,而目前国内大部分均为uPD6121编码方式(日本NEC公司搞出来的。
),所以我们只须弄清楚这种编码的时序,即可写出万能的红外解码程序,只要是基于这种编码方式的遥控器(家里的电视、空调、电扇遥控器)都可以用该程序来解码(这点也充分证明了C语言的高移植性啊。
)这种编码的格式其实很简单,开头是一个引导码,人家芯片在编码时将其设计成9ms的高电平和4.5ms的低电平,也就是说你必须跳过这段引导码之后才会接收到数据,第一个问题来了:为什么要加这段引导码?因为红外传感是非常容易受到干扰的,如果直接传送数据很可能并非发送端的信号,很可能来自其他辐射,后面设计程序时会遇到这个问题。
所以我们在写程序时在引导码时可以加入检测代码,如果是引导码则继续接收,否则跳出。
第二个问题就是:接收数据时我们用外部中断接收,这是考虑到CPU 的执行效率,如果你在主函数里接收数据,就好比CPU一直在问:你接收到数据没?你接收到没?..很明显不靠谱,和串口通信一样,接收数据用中断这是经验,有利于单片机的执行效率。
第三个要注意的就是红外接收端和编码发送的数据是反向的!这点很重要,我看很多资料没有写明这点,让很多童鞋疑惑不解,也就是说引导码编码时确实是9ms高电平和4.5ms 的低电平,但是到了接收端是9ms的低电平和4.5ms的高电平,所以我们在解码时就得注意引导码高电平出现的顺序。
对于编码格式,引导码后接了4个字节的数据,前两个字节为用户码和用户反码,简单点说就是器件地址;后两字节为操作码和操作反码,就是我们真正需要的数据。
红外遥控解码程序

红外遥控解码程序红外接收头的型号有很多HS0038 VS838等功能⼤致相同,只是引脚封装不同。
红外接收有⼏种统⼀的编码⽅式,采样哪种编码⽅式取决于遥控器使⽤的芯⽚,接收头收到的都是⼀样的。
电视遥控器使⽤的是专⽤集成发射芯⽚来实现遥控码的发射,如东芝TC9012,飞利浦AA3010T等,通常彩电遥控信号的发射,就是将某个按键所对应的控制指令和系统码(由0和1组成的序列),调制在38KHz的载波上,然后经放⼤、驱动红外发射管将信号发射出去。
不同公司的遥控芯⽚,采样的遥控码格式也不⼀样,较普遍的有两种,⼀种NEC标准,⼀种是PHILIPS标准。
NEC标准:遥控载波的频率为38KHz(占空⽐1:3)当某个键按下时,系统⾸先发射⼀个完整的全码,如果按键超过108ms仍未松开,接下来发射的代码(连发代码)将由起始码(9ms)和结束码(2.5ms)组成。
⼀个完整的全码 = 引导码 +⽤户码 +⽤户码 + 数据码 + 数据码 + 数据反码。
其中,引导码⾼电平9ms,低电平4.5ms;系统码8位,数据码8位,共32位;其中前16位为⽤户识别码,能区别不同的红外遥控设备,以防⽌不同的机种遥控码互相⼲扰。
后16位为8位的操作码和8位的操作反码,⽤于核对数据是否接收准确。
收端根据数据码做出应该执⾏上⾯动作的判断。
连发代码是在持续按键时发送的码。
它告知接收端。
某键是在被连续的按着。
NEC标准下的发射码表⽰发射数据0时⽤”0.56ms⾼电平 + 0.565ms低电平 = 1.125ms”表⽰;数据1⽤”⾼电平0.56ms + 1.69ms = 2.25ms”表⽰。
遥控器发射信号:需要注意的是:当⼀体化接收头收到38kHz红外信号时,输出端输出低电平,否则为⾼电平。
所以⼀体化接收头输出的波形和发射波形是反向的PHILIPS标准:载波频率38KHz:没有筒,点按键时,控制码1和0之间切换,若持续按键,则控制码不变。
⼀个全码 = 起始码’11’ +控制码 + ⽤户码 + ⽤户码数据0⽤“低电平1.778ms + ⾼电平1.778ms”表⽰;数据1⽤“⾼电平1.778ms + 低电平1.778ms”表⽰。
红外解码程序

红外解码程序本篇介绍红外解码的原理和程序的写法。
下面来看一下,红外线是如何编码的。
下面来具体说一下,解码的原理,每按一下遥控器的一个按键,遥控器就会发出32个“0”“1”代码(当然是通过高低电平的占空比来判断是0还是1的),具体是0,1是如何编码的上面图片中有介绍,和一个引导码,引导码的作用是告诉处理器,接下来将要开始发送代码,我们在编写程序时,当检测到引导码时,就应该准备接受数据了。
32位代码中的前16位是用户识别码,不同的遥控器不相同,防止互相干扰的,后16是8为数据码,和8位数据反码。
接下来开始介绍如何解码程序的编写。
程序中用到了两个中断,一个是定时器中断,一个是外部中断。
定时器中断用来准确计时,判断接受的代码是0还是1,外部中断用来准确确定定电平到来的时刻,然后开始计时。
/*********************************************************函数功能:红外解码,用八位数码管显示红外线的按键码,便于红外控制测试环境:hot 51学习板编译环境:keil4整理人:张家越QQ:435835181整理时间:2011-04-03************************************************************/#include<reg51.h>#define uchar unsigned char#define uint unsigned intuchar code seg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0 x6f,0x77,0x7c,0x39,0x5E,0x79,0x71 };//0-f的段选码unsigned char code seg_we[]={0,1,2,3,4,5,6,7};uchar irtime,startflag,bitnum,irreceok;uchar irdata[33];uchar irprosok;uchar display[8];uchar ircode[8] ;sbit led1=P0^1;sbit led2=P0^2;/******************************************************************** ****函数功能:延时函数,在数码管显示时使用,不需要很精确********************************************************************* ****/void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}/******************************************************************** ******函数的功能:定时器0的初始化********************************************************************* *****/void timer0init(){TMOD=0x02; //设置定时器工作在方式2TH0=0x00; //TL0=0x00; //设置定时器的初值ET0=1; //开定时器中断TR0=1; // 打开定时器EA=1; //开总中断}/******************************************************************** ****外部中断1的初始化********************************************************************* **/void int1init(){IT1=1; //设置触发方式为上升沿EX1=1; //开外部中断1EA=1; //开总中断}/******************************************************************** **定时器0的功能函数,每中断一次irtime++,用于计时********************************************************************* **/void timer0() interrupt 1{irtime++; //定时器中断一次irtime++,用于计时}/******************************************************************** ***外部中断0的处理函数,每当有低电平数据过来时,中断一次,(使用次中断的前提是,信号线必需接在外部中断0上面,也就是P3^2口),函数功能是,把信号从高低电平变成时间的代码放入irdata【】中********************************************************************* ***/void int1() interrupt 2{if(startflag){if(irtime>32) //一组代码检测完毕{bitnum=0;}irdata[bitnum]=irtime; //把检测到的时间送到数组irdata【】中去irtime=0;bitnum++;if(bitnum==33) //如果检测到bitnum=33,说明32位用户码已经检测完毕{bitnum=0; //将bitnum清零以便重新计数irreceok=1; //接收完毕标志位置一}}else //(此函数先进入else语句,跳过引导码的检测){startflag=1; //将开始标志位置一irtime=0; //设置时间初值为零irreceok=1; //接收完毕标志位置一}}/******************************************************************** *****函数功能:把irdata【】中的时间代码转换成二进制代码存放在ircode【】中********************************************************************* *****/void irpros(){uchar k=1,value,j,i;for(j=0;j<4;j++){for(i=0;i<8;i++){value=value>>1; //右移7次(第一次是00,相当于没有移位)if(irdata[k]>6) //循环8次{value=value|0x80;}k++;}ircode[j]=value;}irprosok=1;}/******************************************************************** ********函数的功能是:将ircode【】中的二进制代码转换成为16进制代码便于在数码管上显示******************************************************************* ********/void irwork(){display[0]=ircode[0]/16;display[1]=ircode[0]%16;display[2]=ircode[1]/16;display[3]=ircode[1]%16;display[4]=ircode[2]/16;display[5]=ircode[2]%16;display[6]=ircode[3]/16;display[7]=ircode[3]%16;}/******************************************************************** ****函数功能:用数码管显示解码结果********************************************************************* ***/void display1(){uchar i;for(i=0;i<8;i++){P2=seg_we[i];P0=seg_du[display[i]];delay_50us(40);}}void main(){timer0init(); //定时器初始化int1init(); //外部中断初始化while(1){if(irreceok) //判断数据接收完毕(数组中存储的是高低电平的时间){irpros(); //执行处理函数,将高低电平时间转化成16进制的0,1代码,存放在数组中irreceok=0; //标志清零}if(irprosok) //处理函数执行完毕,{irwork(); //将存储的16进制代码分离,便于数码管显示irprosok=0; //标志清零}display1();}}//在最后我再分析一下程序的编写思路,便于大家理解,一旦有按键按下,接受管接收到引导码,进入外部中断,并将高低电平的时间放入irdata【】数组中,接受完毕标志位置一,判断接受标志位,为1,进行处理函数,将高低电平转换成16进制数,处理标志位置一,判断处理标志位,为1,执行分离函数,将16进制数分离,便于数码管显示,分离完毕后显示。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//此程序为网上下载后修改,要弄懂的话,可以去看看HT6221的时序图。
当然也欢迎在这里留言。
///C51的红外解码程序,可以根据需要自己修改:
//11.0592Mhz
#include<reg51.h>
//根据自己的接线来改
sbit IRIN = P3^2; //红外接收器数据线
sbit led = P3^7; //指示灯
////////////////////////////////////////////
//定义数组IRCOM,分别装解码后得到的数据
//IRCOM[0] 低8位地址码
//IRCOM[1] 高8位地址码
//IRCOM[2] 8位数据码
//IRCOM[3] 8位数据码的反码
/////////////////////////////////////////////
#define uchar unsigned char
#define uint unsigned int
uchar IRCOM[4]=0;
bit flag=0;
/********************/
void delay014ms(unsigned char x); //x*0.14MS
void IR_init(void);
void delay014ms(unsigned char x) //x*0.14MS STC10F04延时约0.15MS {
unsigned char i;
while(x--)
{
for (i = 0; i<125; i++) //13
{;}
}
}
///////////////
//初始化
////////////
void IR_init(void)
{
EA=1;
EX0=1; //允许总中断中断,使能 INT0 外部中断
IT0=1; //触发方式为脉冲负边沿触发
IRIN=1; //I/O口初始化
}
//////////
//解码过程
//////////////
void IR_CODE(void) interrupt 0 //在外部中断子程序中解码
{
unsigned char j,k,N=0;
EX0 = 0;
delay014ms(15);
if (IRIN==1)
{ EX0 =1;
return;
} //确认IR信号出现
while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。
{delay014ms(1);}
for (j=0;j<4;j++) //收集四组数据
{
for (k=0;k<8;k++) //每组数据有8位
{
while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{delay014ms(1);}
while (!IRIN) //等 IR 变为高电平
{delay014ms(1);}
while (IRIN) //计算IR高电平时长
{
delay014ms(1);
N++;
if (N>=30)
{ EX0=1;
return;} //0.14ms计数过长自动离开。
} //高电平计数完毕
IRCOM[j]=IRCOM[j] >> 1; //数据最高位补"0"
if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补"1"
N=0;
}
}
if (IRCOM[2]!=~IRCOM[3]) //不等的话表示解码失败
{
IRCOM[4]=0;
EX0=1;
return;
}
flag = !flag;//pro();//解码成功后运行的程序
//如果解码成功,flag就取一次,在主程序中,就根据flag的值来闪灯,EX0=1;
return;
}
//主程序
void main(void)
{
IR_init( ); //初始化外部中断0
flag = 0;
while(1)
{
led=flag; //正确接收后的led闪灯的现像。
//if(flag)
// {
// led =!led;
// delay014ms(1);
// }
// else led=1;
}
}。