Proteus8仿真:51单片机IrLink红外发送加接受模块的使用

注意:本篇的密码接受有问题,不够仍然可以使用,想优化可以看我最新文章:最新优化,这个是没有bug的版本。

元器件

元器件 名称
51单片机 AT89C51
红外收发 IRLINK
按键 BUTTON
发光二极管 LED-RED
时钟激励源 DCLOCK
与门 74LS08
示波器

原理图部分

在这里插入图片描述
关于IRLINK的使用:
在Proteus上就是一个红外的发射接受一体的一个模块,另外在该模块红外接受上有一个解调的功能。如下图,1区域就是红外的发射区域,2区域就是红外的接受区域,3区域就是红外接受后进行解调的区域。
在这里插入图片描述

然后关于载波的频率,在IRLINK是可以选择对载波频率的要求的,双击元件。默认是40KHz。
在这里插入图片描述
这里频率采用的是Proteus激励源然后与单片机发出的信号经过们与门调制出来。下图是示波器观察信号的结果。
在这里插入图片描述
关于的发射的协议采用的网上说索尼的SonySIRC协议。本次实验采用类似的,以2.4ms的高电平加600us低电平为起始信号,600us为间隔,600us为高电平表示0,1200us为间隔,600us为高电平表示1,数据帧为:帧头为0x80,数据帧为0x40,帧尾为0x20,如果接受到0x40,且帧头帧尾不错误就点灯。本次irlink载波频率为20kHz。

代码

本次实验由单片机通过按键控制IrLink红外来进行通信点灯。

单片机1发送main.c

代码如下:

#include "reg51.h"
#include "intrins.h"

typedef unsigned char uint_8;
typedef unsigned int uint_16;

sbit TX=P2^0;
sbit KEY=P1^0;

//600us
#define High_Low_Wide_H 0XFD 
#define High_Low_Wide_L 0xA8 

//600us
#define Low_Gap_H 0XFD
#define Low_Gap_L 0xA8

//1200us
#define High_Gap_H 0xFB
#define High_Gap_L 0x50

//2400us
#define Start_High_H 0xF6
#define Start_High_L 0xA0

void scan_Key(void); //按键扫描函数
void Ir_Send_Bit(uint_16 us_h,uint_16 us_l,bit Status);
void Ir_Send_Data(uint_8 Data);
void TimerInit(void);
void main(void)
{
    
    
	bit key=0;
	TimerInit();TX = 0;
	while(1)
	{
    
    
		scan_Key();
	}
}

//按键扫描函数
void scan_Key(void)
{
    
    
	if(KEY==0)
	{
    
    
		TX = 0;
		Ir_Send_Bit(Start_High_H,Start_High_L,1); //起始信号2.4ms
		Ir_Send_Bit(Low_Gap_H,Low_Gap_L,0); //间隔输出0.6ms
		Ir_Send_Data(0x80);//起始帧0x80
		Ir_Send_Data(0x40); //数据
		Ir_Send_Data(0x20);//终止帧
	}
}

//一位发送
void Ir_Send_Bit(uint_16 us_h,uint_16 us_l,bit Status) 
{
    
    
	TH0 = us_h;		//设置定时初值
	TL0 = us_l;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	if(Status==1)
	{
    
    
		TX = 1;
		while(TF0==0);
	}
	else if(Status==0)
  {
    
    
		TX = 0;
		while(TF0==0);
	}
	TF0 = 0;
	TR0 = 0;  //关闭定时器
	TX = 0;
}

//八位发送 从最低位往高位发送
void Ir_Send_Data(uint_8 Data)
{
    
    
	uint_8 i=0;
	for(i=0;i<8;i++)
	{
    
    
		if(Data&0x01) //高电平
		{
    
    
			Ir_Send_Bit(High_Low_Wide_H,High_Low_Wide_L,1); //脉宽输出
			Ir_Send_Bit(High_Gap_H,High_Gap_L,0); //间隔输出
		}
		else
		{
    
    
			Ir_Send_Bit(High_Low_Wide_H,High_Low_Wide_L,1); //脉宽输出
			Ir_Send_Bit(Low_Gap_H,Low_Gap_L,0); //间隔输出			
		}
		Data >>=1;
	}
}

void TimerInit(void)		//12微秒@12.000MHz
{
    
    
	TMOD=0X01;		//设置定时器模式
}

单片机2接受main.c

#include "reg51.h"
#include "intrins.h"

typedef unsigned char uint_8;
typedef unsigned int uint_16;

sbit RX=P2^1;
sbit LED=P1^0;

void Ir_Receive(void);
uint_8 Ir_Receive_8Bit(void);
void TimerInit(void);
uint_8 All_Data[3]={
    
    0,0,0};
uint_16 time=0;

void main(void)
{
    
    
	TimerInit();
	while(1)
	{
    
    	
		if((All_Data[1]==0x40)&&(All_Data[0]==0x80)&&(All_Data[2]==0x20))LED=1;
		else LED=0;
		Ir_Receive();
	}
}


//接受数据
void Ir_Receive(void) 
{
    
    
	uint_8 i=0;
	if(RX==0)
	{
    
    
		time=0;
		TR0 = 1;		//定时器0开始计时
		while(RX==0);
		time=TH0*256+TL0; //计算时间
		TR0 = 0;
		
		if((time>2000)&&(time<3000)) 
		{
    
    
			
			TH0=0;TL0=0;	
			time=0;
			TR0 = 1;		//定时器0开始计时
			while(RX==1);
			time=TH0*256+TL0; //计算时间			
			TR0 = 0;
			
			if((time>300)&&(time<1000)) 
			{
    
    
				
				time=0;
				while(i<3)
				{
    
    
					All_Data[i]=Ir_Receive_8Bit();
					i++;
				}
			}
		}
	}
}

//8位接受
uint_8 Ir_Receive_8Bit(void)
{
    
    
	uint_8 Data=0;
	uint_8 i=0;
	while(i<8)
	{
    
    
		if(RX==1)
		{
    
    
			TH0=0;TL0=0;	
			time=0;
			TR0=1;
			while(RX==1);
			time=TH0*256+TL0; //计算时间
			TR0 = 0;
			
			TF0=0;
				
			if((time>300)&&(time<1000)) Data>>=1;
			else if(time>1000) Data |=0x80;
			i+=1;
		}
	}
	return Data;
}

void TimerInit(void)		//12微秒@12.000MHz
{
    
    
	TMOD=0X01;		//设置定时器模式
	TH0=TL0=0;
	TR0 = 0;
}

运行效果如图,led被正常点亮:
在这里插入图片描述

工程文件

工程文件

猜你喜欢

转载自blog.csdn.net/darlingqx/article/details/128371855