在使用家电过程中,必不可少的就是遥控器了。 

       常用的红外遥控系统一般分发射和接收两个部分。应用编/解码专用集成电路芯片来进行控制操作,如下图所示。发射部分包括键盘矩阵、编码调制、LED红外发送器;接收部分包括光、电转换放大器、解调、解码电路。

ir红外遥控发射demo 红外遥控发射头电路图_#include

        发射部分的主要元件为红外发光二极管。它实际上是一只特殊的发光二极管;由于其内部材料不同于普通发光二极管,因而在其两端施加一定电压时,它便发出的是红外线而不是可见光。目前大量的使用的红外发光二极管发出的红外线波长为940nm左右。 

ir红外遥控发射demo 红外遥控发射头电路图_智能传感器_02

        由于我们目的不是制作遥控器,而是利用遥控器控制单片机的功能,我们将会重点在于红外接收到信号部分。红外接收头通常使 HS0038(38KHZ)。

  注:红外的接收头的选用,是由遥控器发出的信号频率决定的,最常见是38KHZ的遥控器。

ir红外遥控发射demo 红外遥控发射头电路图_ir红外遥控发射demo_03

ir红外遥控发射demo 红外遥控发射头电路图_物联网_04

                 

      红外的协议类型有很多种,使用最为广泛的是NEC红外协议。以下是按下暂停键后,抓到的红外接收头的解码后的波形。

ir红外遥控发射demo 红外遥控发射头电路图_智能传感器_05

ir红外遥控发射demo 红外遥控发射头电路图_单片机_06

ir红外遥控发射demo 红外遥控发射头电路图_#include_07

    从抓取的数据上看,在前面表示0 与1的高电平信号脉宽不一样,0比较短,而1是高电平是0的两倍左右。

        使用51单片接收信号,对信号解码,在lcd1602上显示。效果如下

ir红外遥控发射demo 红外遥控发射头电路图_ir红外遥控发射demo_08

main.c

#include "lcd1602.h"
#include "infr.h"

void main()
{

    LCD1602_Init();
    Infr_Qrq0Init();
   
    while(1);


}

void irq0(void) interrupt  0
{
    Infr_GetCode();
	Infr_LcdShow();
   
}

sys.h 

#include "stdio.h"		 //标准库头文件

#define ON 1
#define OFF 0

//---重定义关键词---//
//#ifndef uchar
#define uchar unsigned char
//#endif

//#ifndef uint 
#define uint unsigned int
//#endif
typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;


void delayms(uint y);
void delayus(uint i);

#endif

sys.c

#include "sys.h"


 void delayms(uint y)
{
	uint x;
	for( ; y>0; y--)
	{
		for(x=110; x>0; x--);
	}
}


/*******************************************************************************
* 函 数 名         : delay
* 函数功能		   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delayus(uint i)
{
	while(i--);	
}

lcd1602.h

#ifndef  __LCD1602_H__
#define  __LCD1602_H__
#include "sys.h"



sbit LCD_WR = P2^5;
sbit LCD_RS = P2^6;
sbit LCD_EN = P2^7;


void LCD1602_WriteCmd(uchar cmd);
void LCD1602_WriteData(uchar ldata);
void LCD1602_Init();

void LCD1602_WriteNumXY(uchar x,uchar y,uchar num);



#endif

lcd1602.c

#ifndef  __LCD1602_H__
#define  __LCD1602_H__
#include "sys.h"



sbit LCD_WR = P2^5;
sbit LCD_RS = P2^6;
sbit LCD_EN = P2^7;


void LCD1602_WriteCmd(uchar cmd);
void LCD1602_WriteData(uchar ldata);
void LCD1602_Init();


void LCD1602_WriteStrXY(uchar x,uchar y,uchar *str);
void LCD1602_WriteNumXY(uchar x,uchar y,uchar num);

//写入地址,字符串,字符串长度,移动字符数
void LCD1602_StrMove(uchar addr, uchar *str,uchar length,uchar step);

#endif

infr.h 

#ifndef  __INFR_H__
#define  __INFR_H__
#include "sys.h"

sbit IRIN = P3^2;
void Infr_Qrq0Init();
void Infr_GetCode();
void Infr_LcdShow();
#endif

infr.c

#include "infr.h"
#include "lcd1602.h"
IrValue[4] = {0};

/*******************************************************************************
* 函 数 名         : Interrupt
* 函数功能		   : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void Infr_Qrq0Init()
{
   IT0 = 1;
   EA = 1;
   EX0 = 1;
}
void Infr_GetCode()
{
    u8 j,k;
	u16 err;
	u8 Time=0;
   				 
	delayus(700);	//7ms
	if(IRIN==0)		//确认是否真的接收到正确的信号
	{	 
		
		err=1000;				//1000*10us=10ms,超过说明接收到错误的信号
		/*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
		侯,程序死在这里*/	
		while((IRIN==0)&&(err>0))	//等待前面9ms的低电平过去  		
		{			
			delayus(1);
			err--;
		} 
		if(IRIN==1)			//如果正确等到9ms低电平
		{
			err=500;
			while((IRIN==1)&&(err>0))		 //等待4.5ms的起始高电平过去
			{
				delayus(1);
				err--;
			}
			for(k=0;k<4;k++)		//共有4组数据
			{				
				for(j=0;j<8;j++)	//接收一组数据
				{

					err=60;		
					while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
					{
						delayus(1);
						err--;
					}
					err=500;
					while((IRIN==1)&&(err>0))	 //计算高电平的时间长度。
					{
						delayus(10);	 //0.1ms
						Time++;
						err--;
						if(Time>30)
						{
							return;
						}
					}
					IrValue[k]>>=1;	 //k表示第几组数据
					if(Time>=8)			//如果高电平出现大于565us,那么是1
					{
						IrValue[k]|=0x80;
					}
					Time=0;		//用完时间要重新赋值							
				}
			}
		}
		if(IrValue[2]!=~IrValue[3])
		{
			return;
		}
	}
}



void Infr_LcdShow()
{
     LCD1602_WriteStrXY(2,0,"User:");
     LCD1602_WriteNumXY(9,0,IrValue[0]&0x0F);
     LCD1602_WriteNumXY(8,0,IrValue[0]>>4);
     

     LCD1602_WriteNumXY(11,0,IrValue[1]&0x0F);
     LCD1602_WriteNumXY(10,0,IrValue[1]>>4);
     
     LCD1602_WriteStrXY(2,1,"Code:");
     LCD1602_WriteNumXY(9,1,IrValue[2]&0x0F);
     LCD1602_WriteNumXY(8,1,IrValue[2]>>4);
     

     LCD1602_WriteNumXY(11,1,IrValue[3]&0x0F);
     LCD1602_WriteNumXY(10,1,IrValue[3]>>4);

}