基于单片机的红外遥控通信实验 红外遥控器的发送和接收原理

描述

概述

本章介绍红外遥控通信试验,通过本章的学习掌握红外遥控器的编码原理以及使用。在 RY-51 单片机开发板上,配备了一个红外信号接收头,用于接收红外信号,与开发板配套了一个红外遥控器,用于发送红外数据。

14.1 红外遥控原理简介

红外遥控是一种无线、非接触式数据传输技术、具有成本低、抗干扰能力强的短距离通信技术、被广泛的应用于电子设备遥控通信中,包括电视、空调、手机等多种电子设备中,具有广泛的应用前景。

红外通信原理为将信息加载到红外光波中,利用发射装置发射出去,接收设备接收到红外光后将信息解码并做出相应的操作,便完成了一次红外光通信。我们以一个生活中常见的例子为例,当两个在黑暗中的人,一人拿着手电筒通过不停的开关闪烁手电筒将信息传递给对方。而我们这里使用的是红外光,它的优点为红外光不可见,对周围环境影响较小,另外由于红外光波长远小于其它常用无线电波长,因此,对其它无线通信电子设备无影响。怎样将信息加载到红外光上呢?这就是我们常说的红外遥控编码协议了,目前常用的有 Philips RC-5Protocol、Sharp 协议、NEC 协议等。我们这例重点讲解 NEC 协议。

在数字通信中最小的信息单位为位,即为“0”或“1”,那么在红外通信协议中是怎么表示逻辑“0”和“1”的呢?该协议中以发射红外载波的占空比代表信息“0”和“1”。逻辑“0”的表示法为:560us 的连续载波 +560us 的低电平,总时长为 1.125ms。逻辑“1”的表示法为:560us 的连续载波 +1680us 的低电平,总时长为 2.25ms。其中载波为 38KHz 的方波,逻辑“0”和逻辑“1”表示法如下图所示:

图 14-1 NEC 协议逻辑“0”和逻辑“1”表示法

传输一帧 NEC 格式的数据包括以下内容:

1) 同步码头:9ms 载波 +4.5ms 低电平;
2. 用户码:用户自定义的 8bit 数据;
3. 用户反码:8bit 用户码按位取反;
4. 数据码:8bit 数据,也称为 8 位按键数据码;
5. 数据反码:8bit 数据码按位取反。

由上面内容可知,实际传输的数据内容为用户码和数据码,上面的反码用于数据校验,确保数据传输的可靠性,数据按低位到高位的顺序一次传输。传输一帧 NEC 数据格式如下图所示:

红外遥控器

上图为 NEC 发送模块通过红外光发送的数据,当接收模块接收到 38KHz 的载波时输出低电平,其它情况输出高电平,因此,单片机通过测量接收到的电平高低持续时间便可解码数据了。例如当单片机接收到 9ms 低电平 +4.5ms 高电平时,即接收到了引导码,当接收到 560us 低电平 +560us 高电平表示接收到了数据“0”,当接收到 560us 低电平 +1680us 高电平表示接收到了数据“1”,依照上述模式便可完成一帧数据的接收。

14.2 红外接收硬件电路设计

RY-51 单片机开发板载了红外信号接收模块 VS1838B,模块外形图下图左边所示,电路连接图如下图右边所示。其中,输出引脚与单片机的 P3.2 引脚相连接,同时该引脚为单片机的外部中断 0 输入引脚。因此,可以利用单片机的外部中断 0 来处理红外数据接收。
红外遥控器

14.3 红外解码试验

红外解码软件编写步骤如下:首先进行初始化将外部中断 0 设置为下降沿触发,当接收到的红外信号由高电平变为低电平时,表明一帧红外数据的开始。在外部中断 0 子程序中判断引导码的正确性,判读的方法为通过定时器计数来计算高低电平持续的时间,并分别与引导码规定时间进行对比。当超出了规定时间范围,我们认为这不是一帧标准的红外遥控数据,便直接返回跳出中断子程序。当符合要求后,继续往下执行,并判断和接收 4 个字节的数据,将接收到的数据存放到指定存储变量中,并置位红外标志位。在主程序中查询这个标志位来确定是否收到了红外数据,将数据从存储变量中取出,并将数据显示在602液晶模块上。为了方便后续使用,将红外初始化,以及红外中断子程序放入"HongWai.h","HongWai.c"文件中。

"HongWai.h"代码如下:

#ifndef __IR_H__
#define __IR_H__

extern void InitIR(); //初始化定时器TR0,外部中断0
extern bit Flag_IR;	  //按键标志位
extern unsigned long Data_IR;//4个字节的数据:[31:0]数据反码- >数据码- >用户反码- >用户码

#endif

"HongWai.c"代码如下:

#include< reg52.h >

#define HIGH_IR 1	 //高电平
#define  LOW_IR 0	 //低电平

#define  Min_9ms	 8000	   //8ms
#define  Max_9ms	 10000	   //10ms
#define  Min_4_5ms	 3500	   //3.5ms
#define  Max_4_5ms	 5000	   //5ms
#define  Min_560us	 300	   //300us
#define  Max_560us	 700	   //700us
#define  Min_1680us	 1300	   //1.3ms
#define  Max_1680us	 1800	   //1.8ms
#define  Time_16ms   16000	   //16ms

sbit Led1  = P1^1;
sbit IR_in = P3^2;//红外接收引脚,也是外部中断0输入脚
bit Flag_IR = 0;//红外接收标志,收到正确帧数据后,由程序置1
unsigned long Data_IR;//4个字节的数据:[31:0]数据反码- >数据码- >用户反码- >用户码
//红外接收初始化
void InitIR()
{
	IR_in = 1;//释放
	TMOD &= 0xF0;//清零T0控制位
	TMOD |= 0x01;//配置T0为模式1
	TR0 = 0; //停止T0记数
	ET0 = 0;//关定时器0中断
	IT0 = 1;//设置INT0为下降沿触发
	EX0 = 1;//开INT0中断
	EA=1; //开总中断
}
unsigned int T_Count(bit flag)//电平计时器
{
	TH0 = 0; //清零T0
	TL0 = 0;
	TR0 = 1;//启动T0
	//判断高电平是否超过16ms,若超过定义为异常,直接跳出循环,防止进入死循环
	while(IR_in==flag){if(TH1 >= (Time_16ms > >8)) break;}
	TR0 = 0;
	return (TH0*256 + TL0);//返回计数值,数值单位为us		
}
//外部中断0,中断子程序,下降沿触发进入中断
void Int0() interrupt 0	
{
	unsigned int i;
	unsigned int T_Low,T_High;

	T_Low = T_Count( LOW_IR);//接收9ms的引导码低电平	
	T_High = T_Count(HIGH_IR);//接收4.5ms引导码高电平
	//判断引导码正确性
	if(T_Low< Min_9ms || T_Low >Max_9ms || T_High< Min_4_5ms || T_High >Max_4_5ms){IE0=0; return;}
    //接收4个字节的数据,共32位
	for(i=0;i< 32;i++)
	{
		T_Low = T_Count( LOW_IR);//接收560us位低电平		
		T_High = T_Count(HIGH_IR);//接收560us或1680us位高电平
		//判读位电平的正确性
		if(T_Low< Min_560us || T_Low >Max_560us || T_High< Min_560us || T_High >Max_1680us) {IE0=0;return;}			
		Data_IR > >=1; //为0时高位补0
		if(T_High >Min_1680us) Data_IR |= 0x80000000;//为1时高位置1
	}
	Flag_IR = 1; //接收到按键值后,置位
	Led1 = 0;//闪烁小灯
	//for(i=0;i< 5000;i++);
	Led1 = 1;
	IE0=0;//清楚中断标志位,确保在响应外部中断0过程中产生的外部中断请求不再被响应。
}

在主程序中判断数据标志位是否置1,并将接收到的数据显示出来,主程序如下所示:

#include< reg52.h >
#include"HongWai.h"
#include"Drive_1602.h"

sbit DU = P2^7;//数码管段选、位选引脚定义
sbit WE = P2^6;	

unsigned char *Key_Str=0;
void main()
{
	unsigned char Key;
	Init_1602();//1602初始化
	P0 = 0xff;//关闭所有数码管
	WE = 1;
	WE = 0;
	
	InitIR();
	while(1)
	{
		if(Flag_IR)
		{
			Flag_IR = 0;
			Key = (unsigned char)(Data_IR > >16);//数据码
		   	switch(Key)
			{
				case 69:Key_Str = "CH-";break;
				case 70:Key_Str = "CH";break;
				case 71:Key_Str = "CH+";break;
				case 68:Key_Str = "PREV";break;
				case 64:Key_Str = "NEXT";break;
				case 67:Key_Str = "PLAY/PAUSE";break;
				case  7:Key_Str = "-";break;
				case 21 :Key_Str = "+";break;
				case  9:Key_Str = "EQ";break;
				case 22:Key_Str = "0";break;
				case 25:Key_Str = "100+";break;
				case 13:Key_Str = "200+";break;
				case 12:Key_Str = "1";break;
				case 24:Key_Str = "2";break;
				case 94:Key_Str = "3";break;
				case  8:Key_Str = "4";break;
				case 28:Key_Str = "5";break;
				case 90:Key_Str = "6";break;
				case 66:Key_Str = "7";break;
				case 82:Key_Str = "8";break;
				case 74:Key_Str = "9";break;
				default:Key_Str = "error!";
			}
			Disp_1602_str(2,1,"           ");	
			Disp_1602_str(2,1,Key_Str);					
		}		
	}
}

14.4 本章小结

本章介绍了红外遥控器的发送和接收原理,并编写了单片机接收红外数据的驱动程序,后续可直接调用函数应用到具体的工程中去了。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分