红外遥控编解码全攻略
红外遥控解码流程图

pic12f1822接收红外信号解码流程图单片机初始化
高电平 1.125 2.25低电平表示还在引导码高电平
高电平表示还在引导码9mS高电平结束,4.5mS低电平
高电平上,
高电平表示信号没来继续等待,高电位是红外接收头的电平
解码的关键是如何识别“0”和“1”,从位的定义我们可以
发现“0”、“1”均以0.56ms的低电平开始,不同的是高电
据高电平的宽度区别“0”和“1”。
如果从0.56ms低电平过
后,开始延时,0.56ms以后,若读到 的电平为低,说明该位为“0”,反之则为“1”,为了可靠起见,延时必须比
0.56ms长些,但又不能超过1.12ms,否则如果该位为“0”,
读到的已 是下一位的高电平,因此取(1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.88ms左右均可。
头的电平
mS。
任务5.4红外遥控解码.

* 函数名称: InfraredInit()
* 功能 :定时器测量脉宽功能初始化 * 入口参数:无
* 出口参数:无
* 说明 : ***************************************************************************/
void InfraredInit()
{
uint PulseWidth=0;
//
uchar OriginalCode=0;
//
脉宽 操作码原码
6
5.4 红外遥控器解码
uchar AntiCode=0;
//
按键码反码
static bit FlagStart=0;
//
捕获结果码标志位
static uchar IntrNum=0;
//
中断次数
IntrNum++;
}
if(IntrNum>=32)
//
{
IntrNum=0;
AntiCode=InfraredDecode&0xff; // OriginalCode=(InfraredDecode>>8)&0xff;//
if(AntiCode+ OriginalCode==0xff) //
{
FlagInfraredGet=1;
5.4.3 任务实施
图 5.4.8 是本程序的工程结构图:
图 5.4.8 工程结构框图
4
5.4 红外遥控器解码
( 1)主函数 main.c:
#include<reg52.h>
#include"Infrered.h"
红外解码

细说红外编解码现有的红外遥控包括两种方式:PWM(脉冲宽度调制)和PPM(脉冲位置调制)。
两种形式编码的代表分别为NEC、CX6122和PHILIPS的RC-5、RC-6以及将来的RC-7。
PWM(脉冲宽度调制):以发射红外载波的占空比代表“0”和“1”。
引导码为载波发射9ms,关断4.5ms。
“0”为载波发射0.56ms,关断时间0.565ms;“1”为载波发射0.56ms,关断时间1.685ms;调制频率fCAR=1/Tc=fOSC/12=37.91K,fOSC是晶振频率(455K陶瓷晶体);占空比=T1/Tc=1/3。
使用38kHz载波频率头码间隔为9ms + 4.5ms使用16位客户代码使用8位数据代码和8位取反的数据代码数据格式包括引导码、用户码、数据码及数据码反码,编码一共是32位。
红外遥控信号从引导码开始,接下来是16位客户代码,然后是8位数据代码和取反的二进制8位代码,最后的是1位结束位。
此种编码方式可以使用MCU的捕获功能实现,通过比较两次捕获的时间,来判断发射码,参考程序:/s/blog_51f1a4130100azwv.html但并不是所有的编码器都是如此,比如TOSHIBA的TC9012,其引导码为载波发射4.5ms,关断时间4.5ms,其“0”为载波发射0.52ms,关断0.52ms,其“1”为载波发射0.52ms,关断1.04ms。
另一种编码方式是PPM(脉冲位置调制):以发射载波的位置表示“0”和“1”。
用从发射载波到关断载波为“0”,从关断载波到发射载波为“1”。
其发射载波和不发射载波的时间相同,都为0.889ms,也就是每位的时间是固定的。
调制频率fCAR=1/Tc=fOSC/12=36K,fOSC是晶振频率(432K陶瓷晶体);占空比=T1/Tc=1/3。
使用36 kHz载波频率双相编码(又名曼彻斯特编码)5位地址码,6位数据码1.778ms的恒定的位时间(即在36K载波下占64时钟周期)数据格式包括一个开始位(Start bit)、一个扩展位(Enlarge bit)、一个触发位(Toggle bit)、五个系统位和六个数据位。
遥控器解码操作方法

遥控器解码操作方法
遥控器解码操作方法通常包括以下几个步骤:
1. 确认解码器类型:首先要确定遥控器所使用的编码类型,例如NEC、RC5、SONY等。
2. 获取遥控器编码:使用红外线接收器将遥控器对准解码器,按下任意按钮,解码器会接收到红外信号。
3. 解码红外信号:将接收到的红外信号输入解码器,解码器会将信号转换成数字编码。
4. 进行处理:根据不同的解码器类型,可以进行不同的处理操作,例如将数字编码转换成对应的功能,或者将解码器输出的数字编码发送给其他设备。
总体而言,遥控器解码操作方法是通过红外接收器将遥控器信号转换成数字编码,并进行相应处理,以实现对其他设备的控制。
关于用PIC单片机红外遥控的编码与解码

关于用PIC单片机红外遥控的编码与解码一般常用的红外遥控器编码规则都差不多,基本上都同6221原理一样(可在网上找到)接收时:如果用54,57这类片子做的话有一定的难度(假如要做成实时控制的;比如说你还要驱动显示,驱动步进电机,在加上几个按键)原因就是这类片子没有中断例程如下(用来解6221;分频比为256)RF:BTFSC PORTB,2;;B2口用做接收口GOTO RF1BTFSS DOWNBIT;;检测下降沿标制CLRF RTCCOUNTBSF DOWNBIT;制下降沿标制BTFSS UPBIT;;检测上升沿标制RETLW 0BTFSC IDBIT;;检测码头标制GOTO RF3MOVLW 2AHSUBWF RTCCOUNT,0BTFSS STATUS,0GOTO RF2MOVLW 36HSUBWF RTCCOUNT,0 BTFSC STATUS,0 GOTO RF2BTFSC IDBITGOTO RF3MOVLW .8MOVWF LOOP MOVLW .3MOVWF LOOPCOUNT CLRF DATACOUNT BSF IDBITBSF DOWNBITBCF UPBITCLRF RTCCOUNT RETLW 0RF1:BTFSS DOWNBIT RETLW 0BSF UPBITRETLW 0RF2:BCF DOWNBITBCF IDBITCLRF RTCCOUNT RETLW 0 ;遥控接收RF3:MOVLW 02HSUBWF RTCCOUNT,0 BTFSS STATUS,0 GOTO RF4MOVLW 0CH SUBWF RTCCOUNT,0 BTFSS STATUS,0 GOTO RF4GOTO RF2RF4:MOVLW 08HSUBWF RTCCOUNT,0 BTFSC STATUS,0 BSF 3H,0MOVLW 07HSUBWF RTCCOUNT,0 BTFSS STATUS,0RLF DATACOUNT,1BSF DOWNBITBCF UPBITCLRF RTCCOUNTDECFSZ LOOP,1RETLW 0MOVLW .8MOVWF LOOPDECFSZ LOOPCOUNTRETLW 0BSF RFBIT;;制接收完标制BCF DOWNBITBCF UPBITBCF IDBITCLRF RTCCOUNTRETLW 0////////////////////////////////////////////////////////// TIME:BTFSC TIMEPD1GOTO TIME1MOVF RTCC,0;;(MOVWF TIMEONEBSF TIMEPD1RETLW 0 ;定时查寻TIME1:MOVF RTCC,0SUBWF TIMEONE,0BTFSC STATUS,2RETLW 0BCF TIMEPD1INCF RTCCOUNT,1RETLW 0////////////////////////////////////////////////在这里我是用查询的方式来定时的(RTCCOUNT)只是在解码时不需要去追求时间精度;我是去查RTCC 有没有发生跳变如有则表示时间过了256US---RTCCOUNT加一;这样做有一个好处---你不必去管RTCC 具体的值是多少,(RTCC去做精确的时钟定时;在这个查询的子程序中你可以去判断键扫,显示刷新,驱动步进电机等等)相应的C代码如下:unsigned char rfcount,loop,rftime,//查询定时器k;bit rfbit, //接收完标制lowbit1,lowbit2,downbit,rfgobit;unsigned char dispcount[5];//结果#define rfin RC6//////////////////////////////////////////////////////////////////////////////// rf( )//遥控接收{if(rfbit==0){if((lowbit1==0)&&(rfin==0)){downbit=1;rftime=0;lowbit1=1;return;if((lowbit1==1)&&(rfin==1)){lowbit2=1;return;}if((lowbit1==1)&&(lowbit2==1)&&(RC6==0)) {lowbit1=0;lowbit2=0;if((rftime>=40)&&(downbit==1))//遥控接收;{rfgobit=1;loop=0;rfcount=0;k=1;rftime=0;return;}rfcount=rfcount+1;loop=loop+1;if(rfcount>=31)rfgobit=0;downbit=0;rfcount=0;rfbit=1;loop=0;return;}if((rftime>=7)&&(rfgobit==1)) {dispcount[k]=dispcount[k]|0x80; rftime=0;if(loop==8){k=k+1;loop=0;return;}dispcount[k]=dispcount[k]>>1; return;}if((rftime<5)&&(rfgobit==1))dispcount[k]=dispcount[k]&0x7f;rftime=0;if(loop==8){k=k+1;loop=0;return;}dispcount[k]=dispcount[k]>>1;return;}}}}(查询子程序同汇编)假如用中断的话也可用时间查询的方法,只是接收口改用带中断的口线;RB4--RB7,CCP1,CCP2,都可以。
红外遥控解码完全资料LCD1602

红外遥控解码完全资料(LCD1602显示)本帖被一线工人执行置顶操作(2009-06-18)红外遥控解码实验一.实验目的1. 了解红外遥控编码并用单片机捕捉信号及解码2. 熟悉LCD1602的驱动二.红外遥控器编码遥控器编码分好几种,常见的32位编码码和42位编码码,目前我手中遥控器就是42位编码,如图1所示,当有按键时就会产一个9.12ms低电平和4.5ms高电平的起始码,紧接着是26位系统码,此系统码能区别不同的电器设备,防止不同机种遥控码互相干扰,接下来是8位数据码和8位数据反码,间隔23ms的高电平后,再发一个与启始码完全一样的结束码以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”,其波形如图2所示。
图2再回头看图1,大家不难看出,图1是遥控器按键1的一串编码三.硬件连接接收电咱我们使用一化红外接红外接收管1838,不需要任何外接无件,就能完成从红外线接收到输出与TTL电平信号兼容的所有工作,实物如图所示电路图如下:四.解码以上我们了解了红外遥控的编码及硬件连接,现在就对其进行解码,所谓解码就是能用单片机把以不同宽度的脉冲区别开来,一种比较好思路就是计算两次下降沿间隔时间,当单片机外部中断1口有下降沿时中断一次,并启动定时器,定时器定50us,当下次下降沿到来时我们计算定时器中断的次数,这样我们就能很好的区分不同宽度的脉冲了。
大家可能已经迫不急待的要开始解码了,别急,我们先把注意事项先讲一下,实际上,我们红外接收头收到的信号的是有毛刺的,放大后就如下图,所以在下降沿中断触发后,要做延时去抖处理*************************************以下是完整解码程序********************************/***********************************************项目:红外遥控解码(EE01学习板演示程序)**作者:一线工人**网站:电子工程师之家**本程序适合42位码遥控器,即26位系统码,16位数据码,如:57L5,55K2,54B4,KD-29,55K8,5Z26A,等型号的遥控器,转贴请保持代码的完整性*********************************************/#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit ir=P3^3;//红外端口sbit dm=P1^4;//数码管段码控制位sbit wm=P1^5;//数码管位码控制位sbit led_cs=P1^6;//LED控制位sbit rs=P3^5;//1602数据命令选择端sbit en=P3^4;//1602使能信号uchar num;uchar key_code=0;//遥控键值uchar new_code=0;//有无新按键uint buf_key_code=0;//键值暂存uchar key_bit_count=0;//键编码脉冲计数uint count=0;//定时中断次数计数uint buf_count=0;//定时中断计数暂存uchar common_code_count=0;//前导码脉冲计数uchar ir_status=0;//脉冲接收器所处的状态,0:无信号,1:系统码接收区,2:数据编码接收区uchar code table[]="EE01 DEMO:IR";uchar code table1[]="code:";uchar code table2[]={'0','1','2','3','4','5','6','7','8','9',};void delay_10us(unsigned char y)///延时子程序10us{unsigned char x;for(x=y;x>0;x--);}void delay_ms(uint z)//延时子程序1ms{uint x,y;for(x=z;x>0;x--)for(y=113;y>0;y--);}void init(void)/////初始化{ir=1; //红外端口写1led_cs=0; //关闭LEDEA=1; //开总中断TMOD=0x02; //定时器0,模式2,8位自动装载模式TH0=0Xd1; //定时50usTL0=0Xd1;IT1=1; //INT1下降沿触发ET0=1; //允许定时器中断EX1=1; //允许外部中断}/***********************************************定时器中断***********************************************/void time0() interrupt 1///定时器中断{count++;//定时器中断次数累加}/**********************************************外部中断,红外解码程序**********************************************/void int1() interrupt 2///外部中断{TR0=1;//开定时器中断if(count>12&&count<270)//如果信号合法,则放入buf_count,count清0,对下一个脉冲信号计时{buf_count=count;count=0;}delay_10us(10);//延时100us以消除下降沿跳变抖动if(ir==0)//INT1引脚稳定为低电平,则表法确实是信号,count重新计时,因上面延时了50us,故要补偿1次TO中断{count=2;}if(buf_count>12&&buf_count<270)//若收到的信号合法,则再进行信号分析{if(ir_status==0)//如果之前未收到引导码{if(buf_count>210&&buf_count<270)//判断是否引导码13.5ms{ir_status=1;//系统标记buf_count=0;//}}else if(ir_status==1)///收到引导码{if(common_code_count>=25)//若收完26个脉冲{ir_status=2;//数据解码标记common_code_count=0;//系统码计算清零buf_count=0;//中断计数暂存清0}else if((buf_count>40&&buf_count<70)||(buf_count>12&&buf_count<32)){buf_count=0;common_code_count++;//每收到一个信号自加1}}else if(ir_status==2)//进入数据编码接收{if(key_bit_count<8)//收到数据少于8位,则将收到的数据写入buf_key_code {if(buf_count>40&&buf_count<70){buf_count=0;buf_key_code>>=1;buf_key_code|=0x80;//收到1key_bit_count++;//数据脉冲累加}else if(buf_count>12&&buf_count<32)//收到0{buf_count=0;buf_key_code>>=1;//收到0key_bit_count++;}}else //若收完8位数据则做以下处理{ir_status=0;//接收状态返回到空闲key_code=buf_key_code;key_bit_count=0;buf_key_code=0;buf_count=0;TR0=0;new_code=1;}}}}/**********************************************1062驱动程序**********************************************/void wirte_cmd(uchar cmd)//写命令{rs=0;P0=cmd;en=1;delay_ms(5);en=0;}void wirte_data(uchar dat)//写数据{rs=1;P0=dat;en=1;delay_ms(5);en=0;}void wirte_string(const unsigned char *s)//在第二行第5个字开始写字符串{wirte_cmd(0x80+0x40+0x05);while(*s){wirte_data(*s);s++;}}void init_1602()///1602初始化{dm=0;wm=0;led_cs=0;wirte_cmd(0x38);delay_ms(5);wirte_cmd(0x0c);delay_ms(5);wirte_cmd(0x06);}/*************************************主程序*************************************/void main(){init(); ///初始化init_1602(); //1602初始化while(!new_code);//判断是否有新按键,如果有则执行下面程序,没有则一直循环wirte_cmd(0x01);//1602清屏delay_ms(5);wirte_cmd(0x80);//在第一行写入EE01 DEMO:IRfor(num=0;num<12;num++){wirte_data(table[num]);delay_ms(1);}wirte_cmd(0x80+0x40);//在第二行写入code:for(num=0;num<5;num++){wirte_data(table1[num]);delay_ms(1);}if(key_code<10)//如果按鍵小于10则写入相应的数字{wirte_data(table2[key_code]);delay_ms(2);}else if(key_code<50)//大于10则写入字符,与遥控器对应{switch(key_code){case 21:wirte_string("mute");break;case 28:wirte_string("power");break;case 10:wirte_string("-/--");break;case 14:wirte_cmd(0x80+0x40+0x05);wirte_data(0x7f);wirte_data(0x7e);break;//先写字符位置,然后写字符,case 25:wirte_string("SLEEP");break;case 19:wirte_string("P.P");break;case 15:wirte_string("TV/A V");break;case 30:wirte_string("VOL-");break;case 31:wirte_string("VOL+");break;case 27:wirte_string("P+");break;case 26:wirte_string("P-");break;case 16:wirte_string("MENU");break;case 24:wirte_string("A-MODE");break;case 13:wirte_string("SYS");break;case 12:wirte_string("GAME");break;case 20:wirte_string("DISP");break;delay_ms(2);}new_code=0;}}。
红外线遥控编码解码控制

红外遥控具有结构简单,制作方便,成本低廉,抗干扰能力强,工作可靠性高等一系列优点。
同时,由于红外遥控器件,工作电压低,功耗小,外围电路简单,因此,在日常生活中广泛应用,如彩电,录像机,音响空调,风扇,即其它的小型电器上。
遥控距离在几米到十几米。
波长在0.76um~1000um的光波为红外光(线),红外光为不可见光。
红外光按波长范围分为近红外、中红外、远红外、极红外4类。
红外线遥控是利用近红外光传送遥控指令的,波长为0.76um~1.5um。
用近红外作为遥控光源,是因为目前红外发射器件(红外发光管)与红外接收器件(光敏二极管、三极管及光电池)的发光与受光峰值波长一般为0.8um~0.94um,在近红外光波段内,二者的光谱正好重合,能够很好地匹配,可以获得较高的传输效率及较高的可靠性。
一、红外遥控系统的构成:主要由两大部分构成: 红外编码发射部分,红外解码接收部分。
红外发射部分主要由,键盘,红外编码芯片(sc6122/ht6122),电源,红外发射管组成。
红外解码部分:由红外接收电路、红外解码、电源和应用电路组成。
红外遥控接收器的主要作用是将遥控发射器发来的红外光信好转换成电信号,再放大、限幅、检波、整形,形成遥控指令脉冲,输出至遥控微处理器。
其中红外接收电路主要是接收部分的红外接收管是一种光敏二极管(现在常用一体化红外接收头)。
三、红外遥控的编码与解码常用的编码芯片HT6122,遥控器的按键信息由编码芯片编码后,以38KHZ的载频,经红外发射管,向外发射。
有引导码,16为用户编码,按键编码,按键反码构成。
引导码:引导码,也称引导脉冲,一般由高电平1和低电平0的脉冲组成,高电平9ms,低电平4.5ms用来标志遥控编码脉冲信号的开始,使遥控接收器能由此判断出所接收的信号是干扰还是系统的遥控代码。
用户码:通常由8位原码和8位反码组成。
它用来指示遥控系统的种类,以区别其它遥控系统,防止各遥控系统的误动作。
红外解码程序

红外解码程序本篇介绍红外解码的原理和程序的写法。
下面来看一下,红外线是如何编码的。
下面来具体说一下,解码的原理,每按一下遥控器的一个按键,遥控器就会发出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)。
-DYDIY-红外遥控编解码全攻略作者:杜洋2005-9-26红外遥控器的解码并对电器进行遥控一直是广大单片机爱好者的一个心愿。
自己动手实现红外遥控电器也是大家单片机学习提高的一个重要的实验。
现在网上关于红外线遥控器的解码的资料和文章很多,可是我在半年前学习红外遥控的解码时可是费了不少的力气。
因为网上大部分资料和源程序都是针对某一种的红外遥控进行说明,只有买了和文章中一样的遥控器才可以继续实验。
而且网上很少有遥控器的编码资料(用单片机模拟红外遥控器),经过了半年的学习与实践现在终于对红外遥控信号的编解码有了一个微薄的认识,在止写成文章希望对初学红外遥控的朋友有一定的帮助,更渴望有深入了解这方面的高手批评指正,谈谈自己的理解与看法,我就算是抛砖引玉了。
呵呵!红外遥控器的解码:大部分的红外遥控的解码资料都是采用串口或是利用一个专用的单片机解码电路取码,前者的制作麻烦而且还要有专用的软件支持。
后者则必须单独做一块解码板,而且一般只对某一种或一类的红外遥控器有效。
而我有一种方法,只用一条不需要电路板的接线,用声卡测出红外遥控的波型。
经过了长时间的使用效果很好,而且不仅对各种红外遥控的解码,还可以对无线通信或各种低波特率的编码进行分析,相当一个高级的试波器。
红外遥控器声卡波形解码一法:采用我的解码方法需要以下的条件:1,一台有MIC输入的声卡的电脑。
2,一条制作好的红外转换线(自己制作,以下有介绍)3,安装高级音频编辑软件COOL EDIT PRO 2.0(各大下载网均有破解版下载)红外遥控协议说明:一般的,红外遥控的编码由前导码、地址码和数据码组成。
而且有比较精准的时序要求。
遥控码的发射由38KHZ或40KHZ的载波信号,由信号的时间长度来表示二进制数据。
遥控的协议表示方法很多,下面是几种典型的例子:1,1E-mail:dydiy@E-mail :dydiy@2这是某型号长虹电视机遥控器的波形,从图中可以看得出它是用一个4.5毫秒的高电平和4.5毫秒的低电平作为前导码。
之后以0.56毫秒高电平和0.56毫秒低电平表示数据“0”,以0.56毫秒高电平和1.65毫秒低电平表示数据“1”。
一般前导码都是明显比数据码长的信号,我们用COOL EDIT 得到波型图之后可以一眼就看出来。
通过前导码之后有32个数据码(“0”,“1”代码),被分成4个字节,每个字节8位(8个数据)。
数据是由高位到低位排列的,我们可以通过看数据码低电平的长度来看出数据值(长为1)。
写下数据再每8位组成一个字节,我们就可以得出70H ,70H ,1AH ,E5H 这4个字节的数据,前2个字节为地址码,用来区别各个产家或各种型号的遥控器(前导码和数据帧的不同也可以区分不同的遥控器)。
一般第一个字节与第二个字节是校验关系,第二个字节是第一个字节的反码(反码:相反的数据,如果数据为“0”反码则是“1”)或是两个字节相同,上图的字节相同。
后两个字节是数据码,用来区别遥控器的按键值,一般第三个字节与第四个字节也是同码或反码的关系,上图为反码关系。
2,此为SAA3010遥控器的波形,说实话我对这个遥控的协议不了解,不过还是知道一点点,在这里小说一下,让高手见笑大方了。
这种遥控的数据是由T (一定长度,集体没量)表示数据“0”,用数据2T 表示数据“1”。
这种协议是不分高低电平的,不论高还是低只要长度相当就表示数据,这种遥控协议的精度不高容易产生错误。
用T 的高电平表示前导码,后有24个数据码,T 长度为0,2T 长度为1,每8位组成一个字节,共有3个字节。
集体的地址字节和数据字节怎么分我就不了解了。
3,这是SONY-D7C8遥控器的波形,和长虹的遥控相似,它用4T长度高电平表示前导码,用T长度低电平和T长度高电平表示“0”,用T长度低电平和2T 长度高电平表示“1”。
共有12个代码,后4个码都为“0”,可能是地址码,可以不理采。
前8位可以组成一个字节的数据,仅用这一个字节表示数据信息。
以上可以看出遥控的编码各有不同,地址码,数据码也不同,所以我们只要了解了代码的形式(即前导码及数据“0”,“1”的表示方式),就可以完全的玩转红外遥控。
解码思路与方法:我利用电脑的声卡和COOLEDIT软件读出遥控码,首先我们得作一条转接线。
我们可以用红外一体化接收头将38K或40KHZ的调制信号解调、放大、输出TTL数据信号电平。
这里我使用的是红外一体接收集成电路TSOP1738,它有3个引脚,分别为电源VDD,地VSS,信号输出OUT。
TSOP17385V的电源我们可以用稳压电源或是从USB口取电,将输出和地接一条音频线接声卡。
就这么简单,快作吧。
电路图:3E-mail:dydiy@E-mail :dydiy@4下面安装COOL ,这个工作我就不多说了,不然大家说我八卦了。
打开COOL ,在多音轨窗口选择一个音轨,点中R 并单击录音键。
用左上角的音轨窗口转换按钮变到单轨方式。
用放大波形和减少幅度工具调整图像。
就这样,波形出来了。
从图中我们可以看出前导码和代码协议方式。
用下面的标尺还可以算出帧长度,也可以读出代码和字节,一举三得。
知道了波形了,下面我们就开始解码遥控了。
(你可以事先把你手中的遥控器每一个键的波形全5E-mail:dydiy@用COOL录下来,以方便工作)遥控码的解码方法:好了,我们了解了遥控码的协议方式了,可是我们怎么用单片机读这个码,并对电器进行遥控呢?下面就说说单片机解码的原理。
我们的单片机解码电路采用SOTP1738作为红外信号的前期检波、放大、输出TTL电平。
将1738的OUT(输出引脚)直接接到单片机的一个I/O口,再接一个单片机的最小系统(由振荡电路、复位电路、稳压电源电路组成),我们的解码硬件电路就准备好了。
为了读取数据的方便,可以在P1口接8个LED用于显示二进制数据,在一般的51单片机学习板都有这个硬件结构。
好像已经成了一个学习板的标准了。
晶振采用12MHZ和11.0592MHZ都可以,只是在延时读数上我一定的区别。
SOTP1738的输出脚(OUT)在没有信号输入时为高电平(=Vdd),当有38KHZ 的调制信号时则呈低电平(=Vss),我们用单片机的I/O口查寻电平的高低,并查寻某一电平的时间长度,就可以读出数据了。
我们以长虹遥控器为例,说说遥控码的读取:遥控码发射是由9毫秒的高电平和4.5毫秒低电平表示前导码。
用560微秒高电平和1120微秒低电平表示数据“1”,用560微秒高电平和560微秒低电平表示数据“0”。
前导码后共4个字节。
判断数据中低电平的长度是读出数据的要点,这里我们用882US(560~1120US之间)作为标尺,如果882uS之后P3.2还是低电平则表示数据1,将1写入寄存器就可以了(数据为一时还需要再延时一小段时间使电平变为高,以用来检测下一个低电平的起始)。
882US后的电平为高则将0写入寄存器。
之后程序等待下一个低电平的到来。
(发射电路发射的高电平信号被1738接收并输入单片机的是低电平,编程6E-mail:dydiy@时一定要注意。
在COOL的读码时上沉是低电平,下沉是高电平。
)仅对长虹遥控器用查寻方式解码的流程图如下:这是比较常用的解码原程序,其中还加上了正码反码校验(流程图上没有)。
7E-mail:dydiy@系统晶振为12MHZ,如果用11.0592MHZ则需要改动延时子程序。
如果用中断法的程序相似,请大家自己写吧。
JB P3.2,$ ;查寻等待低电平MOV R6,#10SB: ACALL YS1 ;调用882微秒延时子程序JB P3.2,EXIT ;延时882微秒后判断P3.2脚是否出现高电平如果有就退出解码程序DJNZ R6, SB ;重复10次,目的是检测在8820微秒内如果出现高电平就退出解码程序;以上完成对遥控信号的9000微秒的初始低电平信号的识别。
JNB P3.2, $ ;等待高电平避开9毫秒低电平引导脉冲ACALL YS2 ;延时4.74毫秒避开4.5毫秒的结果码MOV R7,#16 ;忽略前26位系统识别码JJJJA:JNB P3.2,$ ;等待地址码第一位的高电平信号LCALL YS1 ;高电平开始后用882微秒的时间尺去判断信号此时的高低电平状态MOV C,P3.2 ;将P3.2引脚此时的电平状态0或1存入C中JNC UUUA ;如果为0就跳转到UUUALCALL YS3 ;检测到高电平1的话延时1毫秒等待脉冲高电平结束UUUA: DJNZ R7,JJJJAMOV R1,#1AH ;设定1AH为起始RAM区MOV R2,#4 ;接收从1AH到1DH的4个内存,用于存放操作码和操作反码PP: MOV R3,#8 ;每组数据为8位JJJJ: JNB P3.2,$ ;等待地址码第一位的高电平信号LCALL YS1 ;高电平开始后用882微秒的时间尺去判断信号此时的高低电平状态MOV C,P3.2 ;将P3.2引脚此时的电平状态0或1存入C中JNC UUU; ; ;如果为0就跳转到UUULCALL YS3 ; ;检测到高电平1的话延时1毫秒等8E-mail:dydiy@待脉冲高电平结束UUU: MOV A,@R1 ;将R1中地址的给ARRC A ;将C中的值0或1移入A中的最低位MOV @R1,A ;将A中的数暂时存放在R1数值的内存中DJNZ R3,JJJJ ;接收满8位换一个内存INC R1 ;对R1中的值加1,换下一个RAM DJNZ R2,PP ;接收完8位数据码和8位数据反码,存放在1AH/1BH中MOV A,1AHCJNE A,1BH,EXIT ;如果不等表示接收数据发生错误,放弃MOV A,1CHCPL A ;对1AH取反后和1BH比较CJNE A,1DH,EXIT ;如果不等表示接收数据发生错误,放弃;1A为遥控地址码正码1B为反码MOV A,1CH;CJNE A,#10H,EXIT; ;10H为遥控器的Power键的值SETB P0.0 (设P0.0口接一个控制电器)即当键值为10H时执行相应功能MOV P1,A ;显示键值;-----------------延时子程序--------------;YS1: MOV R4,#20 ;延时子程序1,精确延时882微秒D1: MOV R5,#20DJNZ R5,$DJNZ R4,D1RETYS2: MOV R4,#10; ;延时子程序2,精确延时4740微秒D2: MOV R5,#235DJNZ R5,$DJNZ R4,D2RETYS3: MOV R4,#2 ;延时程序3,精确延时1000微秒D3:MOV R5,#2489E-mail:dydiy@DJNZ R5,$DJNZ R4,D3RETYS4: MOV R4,#2 ;延时程序3,精确延时??微秒D4:MOV R5,#200D5:MOV R6,#250DJNZ R6,$DJNZ R5,D5DJNZ R4,D4RETEND(此程序仅为参考程序,并不实用,如要使用,请自行修改)可以了,我们用单片机读出了数据值(从P1口的二进制数读出,由高位到低位),之后我们就可以比对这个值控制电器了。