选择一体化红外吸收头作为红外旗子暗记的吸收端,这是一种分外的红外吸收电路,它把红外吸收管和放大电路集成到了一块,从形状上看只有一个三极管大小,如图
一体化红外吸收头共有三个引脚,将有突出的一壁临准自己后从左到右依次是旗子暗记输出、GND、VCC,它的事情电压为5V,可以选择一体化红外吸收模块,我们在利用的时候只须要给它接上5V电源,接地,然后将旗子暗记输出脚连接到单片机就可以利用了。本篇文章我利用51单片机进行试验,51单片机用来解码红外旗子暗记是足够的并且易于理解,文章紧张是讲解解码事理。

第一步是硬件连接,用到的硬件非常大略,只有一体化红外吸收头和单片机最小系统。首先,我们给单片机最小系统和红外吸收头接上电源,把稳共地,然后将红外吸收头的旗子暗记输出脚接到单片机的外部中断引脚上,这样就完成了硬件的连接。之以是将旗子暗记输出脚接到单片机的外部中断引脚是由于前面说过红外吸收头在吸收到红外旗子暗记后会输出高低电平,接在外部中断引脚后单片机可以在有旗子暗记的时候快速做出反应,后面的程序也是靠中断程序实现的。

前面讲过红外吸收头在吸收到红外旗子暗记后会输出高低电平,然后就可以通过我们的程序剖析电平的变革来识别吸收到的旗子暗记的内容。要将吸收真个旗子暗记解码我们就要知道发送真个数据是如何编码的,在本文中用到的红外遥控器所利用的是NEC编码协议,以是我们首先要讲解一下NEC协议的干系信息。NEC协议是用于红外通信中的一种协议,通过NEC协议发送信息的格式如下图:
信息的开始是9ms高电平加4.5ms低电平的勾引码,浸染便是见告设备通讯开始,有旗子暗记发送过来了。之后接的是8位地址码和8位地址反码,地址码的浸染便是区分不同的吸收器件,实现单独掌握某个器件。末了是8位数据码和8位数据反码,数据码便是功能码,我们可以给不同数据码设定不同的功能,反码的浸染便是考验吸收到的数据是否精确。在上面的这条信息里,‘0’是用560us高电平加560us低电平表示的,‘1’是用560us高电平加1680us低电平表示。要把稳的是上面的波形图是发射真个波形,我们红外吸收端收到的旗子暗记的高低电平是与上图相反的,还要把稳发射端在发射数据是是从最低位开始发射,以是我们吸收到的旗子暗记也是从最低位开始的,其余当我们持续按住同一个按键时,发射端并不会重复发送地址码和数据码而是在发送完一次后每隔一段韶光发送一次勾引码(重复),间隔韶光大约是108ms。下图为吸收端勾引码、勾引码(重复)、‘0’、‘1’的波形:
在理解了这些关于NEC协议的信息后我们就可以开始写程序掌握单片机来解码红外旗子暗记了。首先我来讲解一下解码程序的思路,之前我们将红外吸收头的旗子暗记输出脚接在了单片机的外部中断引脚上,我们将外部中断的触发办法设置为跳变沿触发,当吸收头吸收到旗子暗记后就会输出一个低电平,低电平触发外部中断,我们在中断程序中启动定时器,这样当下一次低电平触发中断前,在这期间定时器所定的韶光我们可以进行比较从而确定脉冲的宽度,确定数据为‘0’还是‘1’。接下来我根据详细代码进行先容,
#include"reg52.h"#define uint unsigned int #define uchar unsigned charuchar IRtime; //储存检测红外高低电平持续韶光uchar IRcord[4]; //储存解码后的4个字节数据uchar IRdata[33]; //包含起始码在内的33位数据bit IRpro_ok; //解码后4个数据吸收完成标志位bit IRok; //33位数据吸收完成标志位
在上面这段函数中我们添加上相应的头文件和一些宏定义,之后我们定义一些变量和数组作为一些标志位以及一些数据的保存,在每个定义后面都有注释来阐明相应的浸染,在这里就不再赘述。
void init(){ TMOD |= 0x02; //设置定时器0事情模式2 TL0 = TH0 = 0; //初始化定时器0寄存器 EA = 1; ET0 = 1; TR0 = 1; IT0 = 1; EX0 = 1; TMOD |= 0x20; //设置定时器1事情模式2 TL1 = TH1 = 0xfd; //比特率9600 SM1 = 1; //设置串口事情模式1,10位异步收发 TR1 = 1; //启动定时器1 }
然后我们定义一个初始化函数用于定时器和中断的初始化设置,我们将定时器0用于打算红外旗子暗记高低电平的韶光,将定时器1用于串口发送数据。
void T0_ISR(void) interrupt 1 //定时器0中断一次277.76us{ IRtime++;}
上面这段是定时器0的程序,在里面只是用来打算韶光,定时器0中断一次是277.76us,我们通过IRtime就可以打算出红外旗子暗记的持续韶光。
void int0(void) interrupt 0{ static uchar i; //静态变量用于存入33次数据计数 static bit startflag; //开始存储脉宽标志位 if(startflag) { if((IRtime < 53) && (IRtime >= 32)) //判断是否为勾引码 若为勾引码则从起始码开始存 {i = 0;} IRdata[i] = IRtime; //以T0溢出的次数来打算脉宽把这个韶光存放在数组中 IRtime = 0; //计数清零 i++; //计数脉宽存入次数自加 if(i == 30) { IRok = 1; //脉宽检讨完成 i = 0; //把脉宽计数清零准备下次存入 } } else { IRtime = 0; //定时器0计数清零 startflag = 1; //开始处理标志位置1 }}
上面这段程序是外部中断的处理程序,当红外吸收头吸收到红外旗子暗记后会输出相应的高低电平变革,勾引码和“1”、“0”的波形在前面的吸收端波形图已经画出,这样当吸收端为高电平的时候,就会触发外部中断,这是会查看IRtime的值,根据这个值来判断是否是9ms的勾引码,如果是勾引码则先将IRtime清零,然后将往后的脉冲韶光都保存下来,如果不是则把IRtime清零,这样红外吸收头吸收到的33次脉冲的宽度就会保存到IRdata[]数组里。
void IRcordpro(){ uchar i; //用于计数处理4个字节 uchar j; //用于计数处理1个字节的8位数据 uchar k; //用于计数处理33次脉宽 k = 1; //从第一位开始处理 丧失落起始码 for(i = 0;i < 4;i++) { for(j = 0;j <8;j++) { if(IRdata[k] > 5) //如果脉宽大于数据0标准的1125us就剖断为数据1 { IRcord[i] |= 0x80; //置于最高位 } if(j < 7) //从最高位移位置低位 { IRcord[i] >>= 1; } k++; //处理下一次脉宽 } } IRpro_ok = 1; //解码完成}
上面这个函数是用来处理我们之前保存的33次脉冲宽度,并且转化为4字节的数据保存在IRcord[]数组里,详细的操作便是根据脉冲的韶光来判断是“1”还是“0”,大家可以根据程序后面的注释来理解函数的内容。
void main(){ uchar i; //计数串口发送字节数 init(); //初始化 while(1) { if(IRok) //判断33次脉宽是否提取完成 { IRcordpro(); //根据脉宽解码出4字节数据 IRok = 0; //清零脉宽检讨完成标志位等待下一次脉宽检讨 if(IRpro_ok) //判断解码是否完成 { for(i = 0;i < 4;i++) { SBUF = IRcord[i]; while(!TI); TI = 0; } IRpro_ok = 0; //清零解码标志位 } } }}
末了我们在主函数部分调用之前的函数,并且在等待解码完成后将解码出来的4字节数据通过串口发送到电脑。末了我们看一下实际的效果,首先打开串口助手,波特率设置为9600,吸收设置为HEX模式,这样当按下红外遥控器的按键时,就会返回遥控器的键值了,
好了,本期教程到此就结束了,感谢各位的不雅观看。
更多干货内容只须要你关注电子芯吧客微信公众号










