一、遥控原理:(NEC)电视遥控器使用的是专用集成发射芯片来实现遥控码的发射,如东芝、飞利浦、NEC等,相互之间采用的遥控编码格式互不兼容,所以各机型的遥控器通常只能针对各自的遥控对象而无法通用为了使信号能更好的被传输,发送端将基带二进制信号调制为脉冲串信号,通过红外发射管发射常用的有通过脉冲宽度来实现信号调制的脉宽调制(PWM)和通过脉冲串之间的时间间隔来实现信号调制的脉时调制(PPM)两种方式 NEC标准:遥控载波的频率为38KHz(占空比为1:3);当某个按键按下时,系统首先发射一个完整的全码,然后经延时再发射一系列简码,直到按键松开即停止发射简码重复延时108ms,每两个引导脉冲上升沿之间的间隔都是108ms 其中,引导码高电平9ms,低电平4.5ms;系统码16位,数据码16位,共32位;数据0用“高电平0.56ms+低电平0.565ms”表示,数据1用“高电平0.56ms+低电平1.6875ms”表示,一个简码=引导码+系统码位0的反码+结束位(0.5625ms)高电平 各部分码的作用:引导码用来通知接收器其后为遥控数据系统码用来区分是哪一机型的数据,接收端依此来判断后续的数据是否为须执行的指令。
数据码用来区分是哪一个键被按下,接收端根据数据码做出应该执行什么动作的判断简码是在持续按键时发送的码它告知接收端,某键是在被连续地按着遥控数据传输系统的关键是数据传输的可靠性为了提高编码的可靠性,NEC标准规定系统码、数据码后分别接着传送一个同样的码或者反码,供误码校验用1、载波波形:使用455KHZ晶体,经内部分频电路,信号被调制在37.91KHZ,占空比是1\3 调制频率(晶体使用455KHZ时)F=1\T=Fosc\12=38KHZ (Fosc是晶振频率)2、数据格式: 数据格式包括引导码、用户码、数据码和数据反码,编码总占32位数据反码是数据码反相后的编码,编码时可用于对数据的纠错注意:第二个用户码也可以在遥控应用电路中被设置成第一个用户码的反码使用455KHZ晶体时各代码所占用的时间3、位定义:用户码和数据码中的每一个位可以是位“1”,也可以是位“0”区分0、1是利用脉冲的时间间隔来区分,这种编码方式称为脉冲位置调制方式(ppm).4、按键输出波形:一般按键输出有二种方式:一种是每次按键都输出完整的一帧数据;另一种是按下相同的按键后每发送完整的一帧数据后,再发送重复码,再到按键被松开。
重复码:单一按键波形:连续按键波形:二、程序设计思路:我们在写遥控接收程序时,可以有两种方法来实现:一、一个外部中断加上一个定时器,当有外部信号输入INT脚时就执行摇控接收程序二、用一个I\O口(设置为高电平)和一个定时器,设置一个时间T,在每过一个时间T后就对I\O口进行扫描一次,如果I\O口有下降沿,那么就去执行遥控接收程序 在这里我选择了第一种方法下面就是遥控接收程序的流程图:注意:1、接收引导码是利用定时器来计时,以达到9ms和4.5ms的准确接收不过在接收9ms时要确保是INT脚输入的是低电平,在接收4.5ms时要确保INT脚输入的是高电平也就是说在INT输入9ms的低电平后马上输入4.5ms的高电平,说明引导码是正确的,否则是错误的不过在判断时间时,可以有一个充许误差,此误差值一般取:引导码*2% 2、在接收用户码和数据码时,判断0、1是通过高电平的时间来判断的如果高电平的时间是1.687,那么说明传输的值是1,如果高电平的时间是0.565,那说明传输的值是0可以有充许误差,取值上同三、红外接收主程序:#include "Common.h"#include "system.h"#include "KEYPAD.H"#include "OSDDraw.h"#include "TwoWire.h"#include "Remote.h"#define __GLOBAL_H__#include "Global.h"_Bool Filter13(_Bool le){ _Bool r; r=INT0; if(le==1) { asm("NOP\nNOP\nNOP\nNOP"); r&=INT0; asm("NOP\nNOP\nNOP\nNOP"); r&=INT0; } else { asm("NOP\nNOP\nNOP\nNOP"); r|=INT0; asm("NOP\nNOP\nNOP\nNOP"); r|=INT0; } if(r==le) return 1; else return 0;}/*遥控接收在此中断程序内完成 数据放在ir_data内*//************************************//* Interrupt for IR subroutine *//* external interrupt source INT0 *//************************************/#pragma interrupt INT0Remote();void INT0Remote(void){ register BYTE i; unsigned int count; /*计时变量*/ unsigned int temp0,temp1,temp2,ir_code=0; ir_enable=TRUE; msttrc=1; tstart_trcmr=0; trcic = 0x00; tck0_trccr1=0; tck1_trccr1=0; tck2_trccr1=1; trc=0; tstart_trcmr=1; /************************************/ /* Detect IR Head */ /************************************/ do /*Detect IR head 9mS*/ { count=trc; /*count :us unit */ if(Filter13(1)==1) break; }while(count<=(IR_HEAD+DELTA)); tstart_trcmr=0; /*停止计时*/ if(Filter13(0)==1||count<(IR_HEAD-DELTA*25)) /*for some noise disturb IR*/ { ir_enable=FALSE; /* no IR head or not suitable for Ir head*/ int0en=1; tstart_trcmr=1; return; } /************************************/ /* Detect OFF CODE 4.5mS */ /************************************/ while(Filter13(0)==1); tstart_trcmr=0; trc=0; tstart_trcmr=1; do /*Detect IR OFF CODE*/ { // count=0; count=trc; /*count :us unit */ if(Filter13(0)==1) break; }while(count<(OFF_CODE+DELTA)); tstart_trcmr=0; count=trc; /*count :us unit */ if(count<=(OFF_CODE-DELTA*2)) { if((count>(OFF_REP-DELTA)&&count<(OFF_REP+DELTA))) { tstart_trcmr=0; trc=0; tstart_trcmr=1; do { count=trc; /*count :us unit */ if(Filter13(1)==1) break; }while(count<=(REP_CODE+DELTA)); tstart_trcmr=0; count=trc; /*count :us unit */ if(INT0==1) { tstart_trcmr=0; if(ir_data==REMOTE_KEY_DECR||ir_data==REMOTE_KEY_INCR) { ir_enable=TRUE; int0en=0; } else { ir_data=0; ir_enable=FALSE; int0en=1; tstart_trcmr=1; } return; } } else { ir_enable=FALSE; /*not suitable for off code*/ int0en=1; tstart_trcmr=1; return; } } /************************************/ /* Detect 16 bit address code */ /************************************/ if(ir_enable==TRUE) { ir_code=0; /*初始化变量*/ for(i=0;i<16;i++) { while(INT0==0); trc=0; tstart_trcmr=1; do { count=trc; /*count :us unit */ if(Filter13(0)==1) break; }while(count<=(CODE_1_TIME+DELTA)); /*INT0为高电平时计时*/ tstart_trcmr=0; ir_code<<=1; if((count>(CODE_1_TIME-DELTA))&&(count<=(CODE_1_TIME+DELTA))); /*detect1code 2.24mS-0.56mS=1.68mS*/ ir_code++; else if((count>(CODE_0_TIME-DELTA))&&(count<=(CODE_0_TIME+DELTA))); /*detect 0 code 1.12mS-0.56mS=0.56mS*/ else { ir_enable=FALSE; tstart_trcmr=1; break; /*not suitable for address code */ } } 。