NEC协议红外遥控器

 产品系列     |      2021-11-05 12:59

家电遥控器通信间隔往往要求不高,而红外的本钱比其它无线设备要低的多,所以家电遥控器应用中红外始终占据着一席之地。遥控器的基带通信协议许多,或许有几十种,常用的就有 ITT 协议、NEC 协议、Sharp 协议、Philips RC-5 协议、Sony SIRC 协议等。用的最多的就是 NEC 协议了,因此我们 KST-51 开拓板配套的遥控器直接回收 NEC 协议,我们这节课也以 NEC 协议尺度来讲授一下。

NEC 协议的数据名目包罗了引导码、用户码、用户码(可能用户码反码)、按键键码和键码反码,最后一个遏制位。遏制位主要起断绝浸染,一般不举办判定,编程时我们也不予剖析。个中数据编码总共是 4 个字节 32 位,如图 16-7 所示。第一个字节是用户码,第二个字节大概也是用户码,可能是用户码的反码,详细由出产商抉择,第三个字节就是当前按键的键数据码,而第四个字节是键数据码的反码,可用于对数据的纠错。


图 16-7  NEC 协议数据名目


这个 NEC 协议,暗示数据的方法不像我们之前学过的好比 UART 那样直观,而是每一位数据自己也需要举办编码,编码后再举办载波调制。

引导码:9ms 的载波+4.5ms 的空闲。

比特值“0”:560us 的载波+560us 的空闲。

比特值“1”:560us 的载波+1.68ms 的空闲。


团结图 16-7 我们就能看大白了,最前面黑乎乎的一段,是引导码的 9ms 载波,紧接着是引导码的 4.5ms 的空闲,尔后边的数据码,是浩瀚载波和空闲交错,它们的是非就由其要通报的详细数据来抉择。HS0038B 这个红外一体化吸收头,当收到有载波的信号的时候,会输出一个低电平,空闲的时候会输出高电平,我们用逻辑阐明仪抓出来一个红外按键通过HS0038B 解码后的图形来相识一下,如图 16-8 所示。

图 16-8  红外遥控器按键编码


图 16-8  红外遥控器按键编码


从图上可以看出,先是 9ms 载波加 4.5ms 空闲的起始码,数据码是低位在前,高位在后,数据码第一个字节是 8 组 560us 的载波加 560us 的空闲,也就是 0x00,第二个字节是 8 组 560us的载波加 1.68ms 的空闲,可以看出来是 0xFF,这两个字节就是用户码和用户码的反码。按键的键码二进制是 0x0C,反码就是 0xF3,最后跟了一个 560us 载波遏制位。对付我们的遥控器来说,差异的按键,就是键码和键码反码的区分,用户码是一样的。这样我们就可以通过单片机的措施,把当前的按键的键码给理会出来。

我们前边进修间断的时候,学到 51 单片机有外部间断 0 和外部间断 1 这两个外部间断。我们的红外吸收引脚接到了 P3.3 引脚上,这个引脚的第二成果就是外部间断 1。在寄存器TCON 中的 bit3 和 bit2 这两位,是和外部间断 1 相关的两位。个中 IE1 是外部间断符号位,当外部间断产生后,这一位被自动置 1,和按时器间断符号位 TF 相似,进入间断后会自动清零,也可以软件清零。bit2 是配置外部间断范例的,假如 bit2 为 0,那么只要 P3.3 为低电平就可以触发间断,假如 bit2 为 1,那么 P3.3 从高电平到低电平的下降沿产生才可以触发间断。另外,外部间断 1 使能位是 EX1。那下面我们就把措施写出来,利用数码管把遥控器的用户码和键码显示出来。

Infrared.c 文件主要是用来检测红外通信的,当产生外部间断后,进入外部间断,通过按时器 1 按时,首先对引导码判定,尔后对数据码的每个位逐位获取坎坷电平的时间,从而得知每一位是 0 照旧 1,最终把数据码解出来。固然最终实现的成果很简朴,但因为编码自己的巨大性,使得红外吸收的间断措施在逻辑上显得就较量巨大,那么我们首先提供出间断函数的措施流程图,各人可以比较流程图来领略措施代码,如图 16-9 所示。

图 16-9  红外吸收措施流程图


图 16-9  红外吸收措施流程图

/***************************Infrared.c 文件措施源代码*****************************/ #include <reg52.h> sbit IR_INPUT = P3^3; //红外吸收引脚 bit irflag = 0; //红外吸收符号,收到一帧正确数据后置 1 unsigned char ircode[4]; //红外代码吸收缓冲区 /* 初始化红外吸收成果 */ void InitInfrared(){ IR_INPUT = 1; //确保红外吸收引脚被释放 TMOD &= 0x0F; //清零 T1 的节制位 TMOD |= 0x10; //设置 T1 为模式 1 TR1 = 0; //遏制 T1 计数 ET1 = 0; //克制 T1 间断 IT1 = 1; //配置 INT1 为负边缘触发 EX1 = 1; //使能 INT1 间断 } /* 获取当前高电平的一连时间 */ unsigned int GetHighTime(){ TH1 = 0; //清零 T1 计数初值 TL1 = 0; TR1 = 1; //启动 T1 计数 while (IR_INPUT){ //红外输入引脚为 1 时轮回检测期待,变为 0 时则竣事本轮回 //当 T1 计数值大于 0x4000,即高电平一连时间高出约 18ms 时, //强制退出轮回,是为了制止信号异常时,措施假死在这里。 if (TH1 >= 0x40){ break; } } TR1 = 0; //遏制 T1 计数 return (TH1*256 + TL1); //T1 计数值合成为 16bit 整型数,并返回该数 } /* 获取当前低电平的一连时间 */ unsigned int GetLowTime(){ TH1 = 0; //清零 T1 计数初值 TL1 = 0; TR1 = 1; //启动 T1 计数 while (!IR_INPUT){ //红外输入引脚为 0 时轮回检测期待,变为 1 时则竣事本轮回 //当 T1 计数值大于 0x4000,即低电平一连时间高出约 18ms 时, //强制退出轮回,是为了制止信号异常时,措施假死在这里。 if (TH1 >= 0x40){ break; } } TR1 = 0; //遏制 T1 计数 return (TH1*256 + TL1); //T1 计数值合成为 16bit 整型数,并返回该数 } /* INT1 间断处事函数,执行红外吸收及解码 */ void EXINT1_ISR() interrupt 2{ unsigned char i, j; unsigned char byt; unsigned int time; //吸收并鉴定引导码的 9ms 低电平 time = GetLowTime(); //时间鉴定范畴为 8.5~9.5ms, //高出此范畴则说明为误码,直接退出 if ((time<7833) || (time>8755)){ IE1 = 0; //退出前清零 INT1 间断符号 return; } //吸收并鉴定引导码的 4.5ms 高电平 time = GetHighTime(); //时间鉴定范畴为 4.0~5.0ms, //高出此范畴则说明为误码,直接退出 if ((time<3686) || (time>4608)){ IE1 = 0; return; } //吸收并鉴定后续的 4 字节数据 for (i=0; i<4; i++){ //轮回吸收 4 个字节 for (j=0; j<8; j++){ //轮回吸收鉴定每字节的 8 个 bit //吸收鉴定每 bit 的 560us 低电平 time = GetLowTime(); //时间鉴定范畴为 340~780us, //高出此范畴则说明为误码,直接退出 if ((time<313) || (time>718)){ IE1 = 0; return; } //吸收每 bit 高电平时间,鉴定该 bit 的值 time = GetHighTime(); //时间鉴定范畴为 340~780us, //在此范畴内说明该 bit 值为 0 if ((time>313) && (time<718)){ byt >>= 1; //因低位在先,所以数据右移,高位为 0 //时间鉴定范畴为 1460~1900us, //在此范畴内说明该 bit 值为 1 }else if ((time>1345) && (time<1751)){ byt >>= 1; //因低位在先,所以数据右移, byt |= 0x80; //高位置 1 }else{ //不在上述范畴内则说明为误码,直接退出 IE1 = 0; return; } } ircode[i] = byt; //吸收完一个字节后生存到缓冲区 } irflag = 1; //吸收完毕后配置符号 IE1 = 0; //退出前清零 INT1 间断符号 } 各人在阅读这个措施时,会发明我们在获取坎坷电平时间的时候做了超时判定 if(TH1 >= 0x40),这个超时判定主要是为了应对输入信号异常(好比意外的滋扰等)环境的,假如不做超时判定,当输入信号异常时,措施就有大概会一直期待一个无法到来的跳变沿,而造成措施假死。

别的增补一点,遥控器的单按按键和一连按住按键发出来的信号是差异的。我们先来比拟一下两种按键方法的实测信号波形,如图 16-10 和 16-11 所示。