51单片机入门:红外遥控

红外遥控系统简介

红外遥控系统是利用红外光进行通信的设备,通常由发射和接收两大部分组成,即:由红外LED将调制后的信号发出,再由专门的红外接收头进行解调输出。

红外LED:外表与普通的LED没有什么不同,发射940nm的红外光,人眼看不到。也有850nm的红外LED,可以看见微微的红光。

通讯方式单工,只能一方发送一方接受,不能反过来;异步,没有单独的时钟线,通信需要双方约定时间。

通信协议标准:NEC标准(我国常用)、RC5、SONY、REC80、SAMSWNG等,主要是欧洲和日本生产厂家所使用的编码格式。

生活中,红外LED被广泛应用,比如在电视、空调和电扇的遥控里都有找到红外LED的身影。这些设备之所以能被控制,是因为内部有与之匹配的红外接收二极管,红外接收二极管的颜色一般是黑色的,当红外接收二极管被红外光照射阻值会变小


硬件电路

1、红外发送部分

主要由如下两种电路结构所示:

对于第一个电路,只有当两个三极管开关同时打开时,红外LED才发光。其中第一个接口的38KHz为调制频率,在发送信号时需要一直给这个接口输入一个频率为38KHz的方波;第二个接口就输入我们想要传输的波形。

将两个接口互相联系起来,会发现:在高电平时,红外LED不会发光;在低电平时,红外LED以38KHz频率闪着亮。(这是为了抵抗干扰,在自然界中有很多红外光,例如太阳光,而调制的目的就是为了区分自然光与作为信号的红外光。)

对于第二个电路,没有了38KHz接口,只是一个纯粹的三极管开关(给低电平亮、给高电平不亮),在发送的时候需要程序来实现38KHz调制的功能。

2、红外接收部分

接收部分有单独的一个红外接收LED(黑色),如果直接用红外接收管,则接受到的信号就会有很多成分(自然光等),因此后面还需要进行电路操作(例如滤除自然光、放大发送的信号、滤除38KHz部分的信号,使其输出信号看上去和IN端输入信号一致)。一体化红外接收管就包含了红外接收LED和这些功能电路。

注意,需要将输出信号OUT接在外部中断上。


基本发送与接收

空闲状态:红外LED不亮,接收头输出高电平。

发送低电平:红外LED以38KHz频率闪烁发光,接收头输出低电平。

发送高电平:红外LED不亮,接收头输出高电平。

接收装置如何区分空闲状态和发送高电平?

接收装置以第一个下降沿为开始,在此之后的一段时间内其输出波形都是发送装置所发送的波形(此时红外LED不亮为高电平输出),波形结束后又一直输出高电平(此时红外LED不亮为空闲状态)。

注意,此处的高电平和低电平都不代表逻辑1或0,仅仅是指物理现象本身。


NEC编码

NEC编码是一种红外遥控协议,常用于遥控器与设备之间的通信。它是一种常用的编码格式;将遥控发送过来的信号进行一定形式的编码,转换为对应的信息。

如上所示,这是一帧完整的红外信号(注意是红外信号,即这是从发送装置来看,对应输出信号波形高低电平与之相反),其中黄色区域既不是高电平也不是低电平,而是38KHz的高频脉冲信号

可以看出,一帧完整的红外信号包括:起始位、地址码、地址反码、数据码、数据反码、结束位。

1、起始位:持续低电平(高频脉冲)9ms后持续高电平(不亮)4.5ms,表示要开始传输数据了。

2、地址码:由8位0或1表示,用于确定(选定)设备(比如家里面有很多红外设备,不同的红外设备其地址码是不同的。)其逻辑0或1表示如下:

逻辑0是由562.5us的高频脉冲和562.5us的不亮表示;逻辑1是由562.5us的高频脉冲和1687.5us的不亮表示。对于上上图,其地址码为:11110000。

3、地址反码:对地址码进行取反,因而地址反码为:00001111。地址反码是为了保证传输的准确性,一旦有一个地址反码和地址码对不上号,这这一帧数据都将作废。

4、数据码:同样由8个0或1组成,对于上上图,其数据码为:1111 1111。其包含的信息为所匹配红外设备需要执行的功能。通过8个0或1的排列组合,有256个不同的结果,也就是说红外遥控器最多有256个按键。

5、数据反码:对数据码进行取反。

6、结束位:持续高频脉冲562.5us,表示数据传输结束。

7、重复码:持续低电平9ms后持续不亮4.5ms,在持续562.5us的高频脉冲,在然后又是持续不亮。每个一帧数据的时间约是110ms。(重复码通常用于调音量时的长按)


51单片机的外部中断

以STC89C52为例,有4个外部中断(传统51单片机只有两个)。其外部中断有两种触发方式:下降沿触发和低电平触发。

其外部中断0(INT0)和外部中断1(INT1)外部中断号分别为0、2。


代码设计

Timer0.c

#include <REGX52.H>

//定时器初始化
void Timer0_Init()
{
	TMOD&=0xF0;    //设置定时器模式
	TMOD|=0x01;    //设置定时器模式
	TL0=0x18;      //设置定时器初值
	TH0=0xFC;      //设置定时器初值
	TF0=0;         //清除TF0标志
	TR0=0;         //定时器0不计时
}

//设置定时器初始值
void Timer0_SetCounter(unsigned int Value)
{
	TH0=Value/256;
	TL0=Value%256;
}

//把定时器里变化后的数据拿出来,得到时间差
unsigned int Timer0_GetCounter()
{
	return (TH0<<8)|TL0;
}

//定时器启动开关
void Timer0_Run(unsigned char Flag)
{
	TR0=Flag;     //Flag为1,开始计时;为0,停止计时
}

Int0.c

#include <REGX52.H>

//外部中断0初始化
void Int0_Init()
{
	IT0=1;
	IE0=0;
	EX0=1;
	EA=1;
	PX0=1;   //优先级设为高优先级
}

此处需要将外部中断0的中断优先级设置为高优先级,保证在同时触发多个中断时优先执行此中断,使红外信号被及时接收。

IR.c

#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"

unsigned int IR_Time;      //计时(时间差)
unsigned char IR_State;    //状态

unsigned char IR_Data[4];  //存储数据
unsigned char IR_pData;    //0~31,即一个完整的信号有32位

unsigned char IR_DataFlag;   //数据帧标志位
unsigned char IR_RepeatFlag; //连发帧标志位
unsigned char IR_Address;    //地址码
unsigned char IR_Command;    //数据码

//红外遥控初始化
void IR_Init()
{
	Timer0_Init();
	Int0_Init();
}


/**
  *功能:红外遥控获取收到数据帧标志位
  *参数:无
	*返回值:是否收到数据帧,1为收到,0为未收到
  */
unsigned char IR_GetDataFlag()
{
	if(IR_DataFlag)
	{
		IR_DataFlag=0;
		return 1;
	}
	return 0;
}

/**
  *功能:红外遥控获取收到连发帧标志位
  *参数:无
	*返回值:是否收到连发帧,1为收到,0为未收到
  */
unsigned char IR_GetRepeatFlag()
{
	if(IR_RepeatFlag)
	{
		IR_RepeatFlag=0;
		return 1;
	}
	return 0;
}

/**
  *功能:红外遥控获取收到的命令数据
  *参数:无
	*返回值:收到的命令数据
  */
unsigned char IR_GetCommand()
{
	return IR_Command;
}

/**
  *功能:红外遥控获取收到的地址数据
  *参数:无
	*返回值:收到的地址数据
  */
unsigned char IR_GetAddress()
{
	return IR_Address;
}


//外部中断0函数,下降沿触发
void Int0_Routine() interrupt 0
{
	if(IR_State==0)          //状态为0,说明是空闲状态
	{
		Timer0_SetCounter(0);     //设置定时器初始值
		Timer0_Run(1);            //开始计时
		IR_State=1;               //进入状态1,即准备接收信号
	}
	else if(IR_State==1)
	{
		IR_Time=Timer0_GetCounter();   //读取计时的时间(时间差)
		Timer0_SetCounter(0);          //定时器清0,重新计时间差
		
		//计时为13.5ms,则收到了起始位(注意,11.0592MHz下为12442)
		if(IR_Time>12442-500&&IR_Time<12442+500) //如果是起始位
		{
			IR_State=2;   //进入状态2,即开始接收数据
		}
		
		//计时为11.25ms,则收到了重复位(同样,11.0592MHz下为10368)
		else if(IR_Time>10368-500&&IR_Time<10368+500)
		{
			IR_RepeatFlag=1;    //说明这一帧已经结束
			Timer0_Run(0);      //结束计时
			IR_State=0;         //回到空闲状态
		}
		
		//接收出错
		else
		{
			IR_State=1;
		}
	}
	else if(IR_State==2)
	{
		IR_Time=Timer0_GetCounter();  //读取计时的时间(时间差)
		Timer0_SetCounter(0);         //定时器清0
		
		//计时为1120us,则收到了逻辑0(注意,11.0592MHz下为1032us)
		if(IR_Time>1032-500&&IR_Time<1032+500) 
		{
			IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8)); //数据对应位  置0
			IR_pData++;
		}
		
		//计时为2250us,则收到了逻辑1(注意,11.0592MHz下为2074us)
		else if(IR_Time>2074-500&&IR_Time<2074+500)
		{
			IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));  //数据对应位  置1
			IR_pData++;
		}
		
		//如果接受失败,这一帧作废
		else
		{
			IR_pData=0;
			IR_State=1;
		}
		
		if(IR_pData>=32)   //表示32位数据接受完毕
		{
			IR_pData=0; //重新置0
			if((IR_Data[0]==~IR_Data[1])&&(IR_Data[2]==~IR_Data[3]))
			{
				IR_Address=IR_Data[0];  //数据转移
				IR_Command=IR_Data[2];  //数据转移
				IR_DataFlag=1;
			}
			Timer0_Run(0);  //定时器停止
			IR_State=0;     //置状态为0
		}
	}
}

此代码主要通过下降沿之间的时间差来判断逻辑0、逻辑1、起始位、重复位。

对于重复位直接返回状态0即可(不需要再进入状态2中改变地址码和数据码),并且在下一次下降沿到来时在进行判断时起始位还是重复位。

对于起始位,则让其进入状态2,记录地址码与数据码。

  • 28
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是DS小龙哥编写的(STC)51单片机开发手册,适合51单片机入门初学者,大学生等当做工具书使用。实验的平台采用的是普中科技单片机平台,文章中的知识点详细,代码清晰,注释清楚,可以复制粘贴,配套代码详细。目前写了4个大章节,后续会持续更新,更新后重新下载即可。 每个例子的完整的工程源码在PDF里有百度云盘的下载链接。失效了可以私信发送。 目前PDF里包含的目录如下: 51单片机开发手册 1 一、 单片机开发入门知识介绍 1 1.1 51单片机介绍 1 1.2 市场上的主流单片机种类 1 1.3 FPGA与单片机区别 2 1.4 DSP和单片机区别 3 二、搭建开发环境 4 2.1 STC单片机命名介绍 4 2.2 安装keil软件 4 2.3 新建工程 5 2.4 下载程序 8 2.5 使用辅助工具计算延时时间 12 2.6 STC90C51系列单片机引脚图 13 三、 基础入门学习 14 3.1 LED灯模块 14 3.2 蜂鸣器模块 17 3.5 独立按键 18 3.6 矩阵键盘 22 3.7 独立数码管(静态数码管) 26 3.8 动态数码管 29 3.9 LED 16*16点阵 33 3.10 采用38译码器驱动8位数码管 48 四、单片机提高篇 53 4.1 定时器 53 4.2 中断 60 4.3 串口通信 71 4.4 NEC红外线遥控器解码 80 4.5 DS18B20温度传感器 87 4.6 EEPROM存储芯片(AT24C02) 96 4.7 DS1302 实时时钟芯片 107 4.8 PCF8591(ADC/DAC)转换芯片 119 4.9 (HC-SR04)超声波测距模块 130 4.10 使用计数器测量NE555脉冲频率 134 4.11 LCD1602显示屏 139 四、 单片机项目篇 146 5.1 16x16点阵滚动显示 146
单片机c语言编程100个实例目录1 函数的使用和熟悉 实例3:用单片机控制第一个灯亮 实例4:用单片机控制一个灯闪烁:认识单片机的工作频率 实例5:将 P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能 实例6:使用P3口流水点亮8位LED 实例7:通过对P3口地址的操作流水点亮8位LED 实例8:用不同数据类型控制灯闪烁时间 实例9:用P0口、P1 口分别显示加法和减法运算结果 实例10:用P0、P1口显示乘法运算结果 实例11:用P1、P0口显示除法运算结果 实例12:用自增运算控制P0口8位LED流水花样 实例13:用P0口显示逻辑"与"运算结果 实例14:用P0口显示条件运算结果 实例15:用P0口显示按位"异或"运算结果 实例16:用P0显示左移运算结果 实例17:"万能逻辑电路"实验 实例18:用右移运算流水点亮P1口8位LED 实例19:用if语句控制P0口8位LED的流水方向 实例20:用swtich语句的控制P0口8位LED的点亮状态 实例21:用for语句控制蜂鸣器鸣笛次数 实例22:用while语句控制LED 实例23:用do-while语句控制P0口8位LED流水点亮 实例24:用字符型数组控制P0口8位LED流水点亮 实例25: 用P0口显示字符串常量 实例26:用P0 口显示指针运算结果 实例27:用指针数组控制P0口8位LED流水点亮 实例28:用数组的指针控制P0 口8 位LED流水点亮 实例29:用P0 、P1口显示整型函数返回值 实例30:用有参函数控制P0口8位LED流水速度 实例31:用数组作函数参数控制流水花样 实例32:用指针作函数参数控制P0口8位LED流水点亮 实例33:用函数型指针控制P1口灯花样 实例34:用指针数组作为函数的参数显示多个字符串 单片机c语言编程100个实例目录2 实例35:字符函数ctype.h应用举例 实例36:内部函数intrins.h应用举例 实例37:标准函数stdlib.h应用举例 实例38:字符串函数string.h应用举例 实例39:宏定义应用举例2 实例40:宏定义应用举例2 实例41:宏定义应用举例3 * 中断、定时器中断、定时器 *中断、定时器*中断、定时器 / 实例42:用定时器T0查询方式P2口8位控制LED闪烁 实例43:用定时器T1查询方式控制单片机发出1KHz音频 实例44:将计数器T0计数的结果送P1口8位LED显示 实例45:用定时器T0的中断控制1位LED闪烁 实例46:用定时器T0的中断实现长时间定时 实例47:用定时器T1中断控制两个LED以不同周期闪烁 实例48:用计数器T1的中断控制蜂鸣器发出1KHz音频 实例49:用定时器T0的中断实现"渴望"主题曲的播放 实例50-1:输出50个矩形脉冲 实例50-2:计数器T0统计外部脉冲数 实例51-2:定时器T0的模式2测量正脉冲宽度 实例52:用定时器T0控制输出高低宽度不同的矩形波 实例53:用外中断0的中断方式进行数据采集 实例54-1:输出负脉宽为200微秒的方波 实例54-2:测量负脉冲宽度 实例55:方式0控制流水灯循环点亮 实例56-1:数据发送程序 实例56-2:数据接收程序 实例57-1:数据发送程序 实例57-2:数据接收程序 实例58:单片机向PC发送数据 实例59:单片机接收PC发出的数据 *数码管显示*数码管显示 数码管显示数码管显示*/ 实例60:用LED数码显示数字5 实例61:用LED数码显示器循环显示数字0~9 实例62:用数码管慢速动态扫描显示数字"1234" 实例63:用LED数码显示器伪静态显示数字1234 实例64:用数码管显示动态检测结果 实例65:数码秒表设计 实例66:数码时钟设计 实例67:用LED数码管显示计数器T0的计数值 实例68:静态显示数字“59” 单片机c语言编程100个实例目录3 键盘控制*键盘控制* *键盘控制 *键盘控制 */ 实例69:无软件消抖的独立式键盘输入实验 实例70:软件消抖的独立式键盘输入实验 实例71:CPU控制的独立式键盘扫描实验 实例72:定时器中断控制的独立式键盘扫描实验 实例73:独立式键盘控制的4级变速流水灯 实例74:独立式键盘的按键功能扩展:"以一当四" 实例75:独立式键盘调时的数码时钟实验 实例76:独立式键盘控制步进电机实验 实例77:矩阵式键盘按键值的数码管显示实验 //实例78:矩阵式键盘按键音 实例79:简易电子琴 实例80:矩阵式键盘实现的电子密码锁 液晶显示LCD*液晶显示LCD *液晶显示LCD * *液晶显示LCD*液晶显示LCD *液晶显示LCD */ 实例81:用LCD显示字符'A' 实例82:用LCD循环右移显示"Welcome to China" 实例83:用LCD显示适时检测结果 实例84:液晶时钟设计 *一些芯片的使用*24c02 DS18B20 X5045 ADC0832 DAC0832 DS1302 红外遥控/ 实例85:将数据"0x0f"写入AT24C02再读出送P1口显示 实例86:将按键次数写入AT24C02,再读出并用1602LCD显示 实例87:对I2C总线上挂接多个AT24C02的读写操作 实例88:基于AT24C02的多机通信 读取程序 实例89:基于AT24C02的多机通信 写入程序 实例90:DS18B20温度检测及其液晶显示 实例91:将数据"0xaa"写入X5045再读出送P1口显示 实例92:将流水灯控制码写入X5045并读出送P1口显示 实例93:对SPI总线上挂接多个X5045的读写操作 实例94:基于ADC0832的数字电压表 实例95:用DAC0832产生锯齿波电压 实例96:用P1口显示红外遥控器的按键值 实例97:用红外遥控器控制继电器 实例98:基于DS1302的日历时钟 实例99:单片机数据发送程序 实例100:电机转速表设计 模拟霍尔脉冲
51单片机基础应用设计C语言实例(400例)合集: 10-LED循环左移 100-24c02记忆开机次数 101-24c02存储上次使用中状态 102-DS1302 时钟原理 103-DS1302可调时钟 104-DS1302时钟串口自动更新时间 105-1602液晶显示DS1302时钟 106-字库ST7920 12864液晶基础显示 107-按键 12864显示 108-PCF8591 1路AD数码管显示 109-PCF8591 4路AD数码管显示 11-LED循环右移 110-PCF8591 DA输出模拟 111-PCF8591 输出锯齿波 112-PCF8591 1602液晶显示 113-串口通讯 114-串口通讯中断应用 115-RS485基本通讯原理 116-红外接收原理 117-红外解码数码管显示 118-红外解码1602液晶显示 119-红外发射原理 12-查表显示LED灯 120-红外收发测试 121-双红外发射避障原理测试 122-1个18B20 温度传感器 数码管显示 123-1个18b20温度传感器1602液晶显示 124-多个18b20温度传感器1602液晶显示 125-超温报警测试 126-温度可调上下限1602 126-温度可调上下限1602显示 127-PS2键盘输入1602液晶显示 128-双色点阵1种颜色显示测试 129-双色点阵2种颜色显示测试 13-双灯左移右移闪烁 130-双色点阵显示特定图形 131-双色点阵交替图形显示 132-双色点阵双色交替动态显示 133-热敏电阻测试数码管显示 134-光敏电阻测试数码管显示 135-自动调光测试 136-串转并数字芯片测试 137-非门数字芯片测试 138-电子琴 139-实用99分钟倒计时器 14-花样灯 140-外部频率测试 141-定时做普通时钟可调 142-1602液晶显示的密码锁 143-实用密码锁 144-1602液晶显示的计算器 145-秒表 146-串口测温电脑显示 147-交通灯测试 148-点阵模拟电梯上行下行 149-点阵流动广告模拟 15-PWM调光 150-综合测试程序 151-12位AD_DS1621与12864液晶 152-闪烁灯一 153-闪烁灯二 154-流水灯A 155-51单片机12864大液晶屏proteus仿真 156-流水灯B 157-数码管显示 158-12864LCD显示计算器键盘按键实验 159-数码管显示(锁存器) 16-共阳数码管静态显示 160-数码管动态显示 161-数码管滚动显示 162-数码管字符显示 163-独立按键 164-矩阵键盘 165-矩阵键盘(LCD) 166-用DS1302与12864LCD设计的可调式中文电子日历 167-定时器的使用(方式1) 168-12864LCD图形滚动演示 169-用PG12864LCD设计的指针式电子钟 17-1个共阳数码管显示变化数字 170-定时器的使用(方式2) 171-外部中断的使用 172-定时器和外部中断 173-开关控制12864LCD串行模式显示 174-点阵显示 175-液晶1602显示 176-12864带字库测试程序 177-串行12864显示 178-遥控键值解码-12864LCD显示 179-液晶12864并行 18-单个数码管模拟水流 180-液晶12864并行2 181-串口发送试验 182-串口接收试验 183-串口接收(1602) 184-蜂鸣器发声 185-直流电机调速 186-蜂鸣器间断发声 187-lcd-12864应用 188-继电器控制 189-直流电机调速 19-按键控制单个数码管显示 190-步进电机 191-存储AT24C02 192-PCF8591T AD实验 193-PCF8591T芯片DA实验 194-温度采集DS18B20 195-EEPROM_24C02 196-12864LCD显示24C08保存的开机画面 197-红外解码 198-12864LCD显示EPROM2764保存的开机画面 199-时钟DS1302(LCD) 2-IO输出-点亮1个LED灯方法2 20-单个数码管指示逻辑电平 200-宏晶看门狗 201-SD卡 202-秒表 203-普通定时器时钟 204-彩屏控制 205-彩屏图片显示 206-12864+DS1302时钟+18B20温度计 207-12864测试程序 208-12864串行驱动演示 209-12864生产厂程序 21-8位数码管显示其中之一 210-12864中文显示测试 211-LCD12864 212-12864M液晶显示(有字库)程序(汇编) 213-超声波测距LCD12864显示 214-红外遥控键值解码12864液晶显示(汇编语言)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值