51单片机--红外遥控

这篇具有很好参考价值的文章主要介绍了51单片机--红外遥控。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

红外遥控的介绍

红外遥控是一种无线、非接触控制技术,通过使用红外线来传送控制信号。它具有抗干扰能力强、信息传输可靠、功耗低、成本低、易实现等显著优点,因此被广泛应用于各种电子设备和家用电器,也越来越多地应用于计算机和手机系统中。
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

硬件电路

红外遥控系统一般由发射和接收两个部分组成。发射部分包括红外发光二极管,它是一种特殊的发光二极管,能够发射调制后的红外光波。接收部分通常采用红外接收模块,用于接收来自遥控器发射的红外信号。当遥控器处于学习状态时,接收模块会接收外来红外信号,并将其转换成电信号。经过检波、整形和放大等处理后,这些电信号会被传送到中央处理单元(CPU)进行解码和执行相应的控制动作。

发射端
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控
IN是输入信号端口,输入的信号会通过38kHz的频率在三极管中放大,到发光二极管中,二极管发出闪烁着的特制红外光线
在现实生活中有很多种类型的红外线,为了让接收方只接收这一类型的红外线,就在电路中加入了频率,让这个信号能有一定频率的闪烁;
当我们没有输入时,默认为高电平,而当我们输入信号时,就会在低电平发出有频率波动的信号
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

接收端
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控
这里将接收的发光二极管内置在了电路中,电路也很容易,电源、接地、以及信号输出
在这里我们会让OUT端口接上外部中断,当产生下降沿就进入中断
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

NEC编码

NEC编码是一种红外遥控协议,常用于遥控器与设备之间的通信。它是一种常用的编码格式;将遥控发送过来的信号进行一定形式的编码,转换为对应的信息
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控
NEC编码的数据格式通常由以下几部分组成:

  1. 引导码(Leader Code):持续低电平(通常为9ms)和持续高电平(通常为4.5ms),用于标识开始传输数据。

  2. 系统码(Customer Code):8位二进制代码,用于识别具体的设备或品牌。

  3. 数据码(Data Code):8位二进制代码,表示具体的指令或按键信息。在传输数据时一般持续低电平(560us)和持续高电平(560us)表示传输‘0’,持续低电平(560us)和持续高电平(1690us)表示传输‘1’;

  4. 取反码(Inverted Data Code):与数据码和系统码相反的二进制代码,用于检验数据的正确性。

  5. 结束码(Stop Bit):持续高电平(通常为0.56ms),表示数据传输结束。在这里,我们没有引用到;

  6. 重复码(Repeat Code):数据传输之后,若持续低电平(9ms)和持续高电平(2.25ms),那么将会重复这个命令信息;

51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

NEC编码使用38kHz的载波频率进行传输,通过在红外光线的调制和解调实现遥控功能。在发射时,数据按照引导码、系统码、数据码和取反码的顺序发送;在接收端,通过解码器将红外信号还原为对应的系统码和数据码,从而实现遥控器与设备的交互。

外部中断

51单片机的外部中断是指通过外部信号触发单片机进行中断处理的一种机制。单片机通过外部引脚接收到特定的信号后,会立即暂停当前的任务,转而执行与该中断相关的程序。

在51单片机中,有两个外部中断源,分别为外部中断0(INT0)和外部中断1(INT1)。这两个中断源分别对应单片机的引脚P3.2和P3.3。
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

外部中断可以通过两种触发方式来进行中断处理:电平触发和边沿触发。电平触发是指当外部信号维持在某个电平上时触发中断,可以是低电平触发或高电平触发;边沿触发是指当外部信号的跳变沿(上升沿或下降沿)出现时触发中断。

中断号
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

此次操作相关寄存器以及原理
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

使用外部中断前,需要进行相应的初始化操作。

初始化

void Interrupt0_Init()
{
	IT0=1;//外部中断0选择边沿触发
	IE0=1;//外部中断0请求标志
	EX0=1;//外部中断0请求允许位
	EA=1;//总中断允许
	PX0=1;//中断优先级控制
}

红外遥控实例代码

接下来,我们要实现的是在屏幕上显示地址,命令码,数字增减,通过遥控的控制,让命令码随之改变,数字达到增减;
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

我们将通过定时器和外部中断0来进行操控,写出NEC编码;
利用不同的状态表示到达不同的编码阶段;
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

Timer0.h

#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0Init();
void Timer0_SetCounter(unsigned int Value);
unsigned int Timer0_GetCounter();
void Timer0_Run(unsigned char Flag);
#endif

Timer0.c

#include <REGX52.H>

/**
  * @brief 定时器0初始化
	* @param 无
	* @reval 无
  */
void Timer0Init(void)		//1毫秒@11.0592MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |=0x01;
	TL0 = 0;		//设置定时初值
	TH0 = 0;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		//定时器0不计时
	
}

//定时器0设置计数器值,范围0-65535
void Timer0_SetCounter(unsigned int Value)
{
	TH0=Value/256;
	TL0=Value%256;
}


//定时器0获取计数器值
unsigned int Timer0_GetCounter()
{
	return (TH0<<8)|TL0;
}

//定时器0启动停止控制
void Timer0_Run(unsigned char Flag)
{
	TR0=Flag;
}


将定时器初始化为0,让定时器实现计时器的功能;

Interrupt.h

#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__

void Interrupt0_Init();

#endif

Interrupt.c

#include <REGX52.H>

//外部中断0初始化
void Interrupt0_Init()
{
	IT0=1;
	IE0=1;
	EX0=1;
	EA=1;
	PX0=1;
}

按键对应命令码:
51单片机--红外遥控,51单片机,51单片机,网络,嵌入式硬件,外部中断0,红外遥控

IR.h

#ifndef __IR_H__
#define __IR_H__


#define IR_POWER		0x45
#define IR_MODE			0x46
#define IR_MUTE			0x47
#define IR_START_STOP	0x44
#define IR_PREVIOUS		0x40
#define IR_NEXT			0x43
#define IR_EQ			0x07
#define IR_VOL_MINUS	0x15
#define IR_VOL_ADD		0x09
#define IR_0			0x16
#define IR_RPT			0x19
#define IR_USD			0x0D
#define IR_1			0x0C
#define IR_2			0x18
#define IR_3			0x5E
#define IR_4			0x08
#define IR_5			0x1C
#define IR_6			0x5A
#define IR_7			0x42
#define IR_8			0x52
#define IR_9			0x4A




void IR_Init();
unsigned char IR_GetDataFlag();
unsigned char IR_GetRepeatFlag();
unsigned char IR_GetAddress();
unsigned char IR_GetCommand();

#endif

IR.c

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

unsigned int IR_Time;
unsigned char IR_State;

unsigned char IR_Data[4];
unsigned char IR_pData;

unsigned char IR_DataFlag;
unsigned char IR_RepeatFlag;
unsigned char IR_Address;
unsigned char IR_Command;

//红外遥控初始化
void IR_Init()
{
	Timer0Init();
	Interrupt0_Init();
}


//红外遥控获取收到数据帧标志位
unsigned char IR_GetDataFlag()
{
	if(IR_DataFlag)
	{
		IR_DataFlag=0;
		return 1;
	}
	return 0;
}

//红外遥控获取收到连发标志位
unsigned char IR_GetRepeatFlag()
{
	if(IR_DataFlag)
	{
		IR_RepeatFlag=0;
		return 1;
	}
	return 0;
}

//红外遥控获取收到的地址数据
unsigned char IR_GetAddress()
{
	return IR_Address;
}

//红外遥控获取收到的命令数
unsigned char IR_GetCommand()
{
	return IR_Command;
}

//外部中断0函数
void Int0_Routine() interrupt 0
{
	if(IR_State==0)  //状态0,空闲状态
	{
		Timer0_SetCounter(0); //计数器清0
		Timer0_Run(1); //定时器启动
		IR_State=1; //变为状态1
	}
	else if(IR_State==1) //状态1,等待Start信号或Repeat信号
	{
		IR_Time=Timer0_GetCounter(); //获取开始的时间或重复的时间
		Timer0_SetCounter(0); //计时器清0
		if(IR_Time>12442-500&&IR_Time<12442+500)//表示是开始信号,进入下一阶段
		{
			IR_State=2;
		}
		else if(IR_Time>10368-500&&IR_Time<10368+500)//是重复信号,回到最初的起点
		{
			IR_RepeatFlag=1; //连发帧标志位置1
			Timer0_Run(0); //定时器停止
			IR_State=0;  //状态置0
		}
		else
		{
			IR_State=1;
		}
	}
	else if(IR_State==2) //状态2,接收数据
	{
		IR_Time=Timer0_GetCounter();//获取接收数据的时间段
		Timer0_SetCounter(0);
		if(IR_Time>1032-500&&IR_Time<1032+500)//数据接到为0
		{
			IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));
			IR_pData++;
		}
		else if(IR_Time>2074-500&&IR_Time<2074+500)//数据接收到为1
		{
			IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));//除8是将32位下标分为4个元素,模8将32位下标从0~7有序循环
			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; //数据帧标志位置1
			}
			Timer0_Run(0); //定时器停止
			IR_State=0; //状态置0
			
		}
	}
}

LCD1602.c

#include <REGX52.H>

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

//函数定义:
/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
	}
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i,SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData(SingleNumber+'0');
		}
		else
		{
			LCD_WriteData(SingleNumber-10+'A');
		}
	}
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
	}
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

main.c

#include <REGX52.H>

#include"LCD1602.h"
#include"IR.h"

unsigned char Num;
unsigned char Address;
unsigned char Command;

void main()
{
	LCD_Init();
	LCD_ShowString(1,1,"ADDR  CMD  NUM");
	LCD_ShowString(2,1,"00    00   000");

	IR_Init(); //NEC编码初始化
	while(1)
	{
		if(IR_GetDataFlag()||IR_GetRepeatFlag()) //数据帧或者重复帧
		{
			Address=IR_GetAddress(); //获取遥控器地址吗
			Command=IR_GetCommand(); //获取遥控器命令吗
			
			LCD_ShowHexNum(2,1,Address,2);
			LCD_ShowHexNum(2,7,Command,2);
			
			if(Command==IR_VOL_MINUS)
			{
				Num--;
			}
			if(Command==IR_VOL_ADD)
			{
				Num++;
			}
			LCD_ShowNum(2,12,Num,3);
			
		}
	}
}

通过判断标志位是否为1来表示是否有遥控信息传输文章来源地址https://www.toymoban.com/news/detail-611147.html

到了这里,关于51单片机--红外遥控的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 51单片机学习笔记-15 红外遥控

    [toc] 注:笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。 注:工程及代码文件放在了本人的Github仓库。 15.1.1 红外遥控器 红外遥控是利用红外光进行通信的设备,由 红外LED 将调制后的信号发出,由专用的红外接收头进行解

    2024年02月04日
    浏览(46)
  • 【【51单片机11.0592晶振红外遥控】】

    这是初步实现的架构 怎么实现内部的详细逻辑 我们用状态机的方法 0状态时一个空闲状态 当它接收到下降沿开始计时然后转为1状态 1状态下 寻找start 或者repeat的信号 再来下降沿读出定时器的值 如果是start 那就进入2状态开始译码 如果repeat 那么重发标志位 重新切回去 我每次

    2024年02月15日
    浏览(40)
  • 基于51单片机设计的红外遥控器

    遥控器是现代生活中必不可少的电子产品之一,目前市面上的遥控器种类繁多,应用范围广泛。而 NEC 红外遥控器协议则是目前应用最为广泛的一种协议之一,几乎所有的电视、空调等家用电器都支持该协议。 本项目是基于 51 单片机设计支持 NEC 协议的红外遥控器,实现接收

    2024年02月09日
    浏览(43)
  • 使用C51单片机实现红外遥控行为控制

    目录 引言 红外遥控原理 实现红外遥控功能 代码示例 结论

    2024年02月12日
    浏览(38)
  • 48、基于51单片机红外遥控智能温控风扇系统设计

        本设计为一种温控风扇系统,具有灵敏的温度感测和显示功能,系统STC89C52单片机作为控制平台对风扇转速进行控制。可由用户设置高、低温度值,测得温度值在高低温度之间时打开风扇弱风档,当温度升高超过所设定的温度时自动切换到大风档,当温度小于所设定的温

    2024年02月04日
    浏览(47)
  • 104、基于51单片机智能风扇pwm调速红外遥控无线遥控风扇温控风扇系统设计

    毕设帮助、开题指导、技术解答(有偿)见文末。 目录 摘要 一、硬件方案 二、设计功能 三、实物图 四、原理图 五、Protues仿真 六、流程图 七、程序源码 八、资料包括 随着气温的逐渐上升,风扇的需求量也逐渐扩大。传统风扇不能根据外界温度的变化对风扇转速快慢进行

    2024年02月15日
    浏览(67)
  • 63、基于51单片机红外遥控人体感应自动门控制系统设计

    毕设帮助、开题指导、技术解答(有偿)见文末。 目录 摘要 一、硬件方案 二、设计功能 三、实物图 四、原理图 五、PCB图 六、Protues仿真 七、程序 部分代码 八、资料包括 伴随着电气技术的发展,电气控制控制技术已经成熟,针对电子自动门进行研究。基于8051内核的单片

    2024年02月03日
    浏览(44)
  • 免费开源51单片机个人课程设计--基于stc89c52及红外遥控的测温智能电风扇

    51单片机个人课程设计–基于stc89c52及红外遥控的测温智能电风扇 个人学校的课程设计-智能电风扇,包含proteus原理图与源代码。 代码部分由我个人写的也有普中实验中的代码块。 3.1 硬件设计 主要器件: 单片机 AT89C52 红外接收 HS0038 LCD1602 温度测量 DS18B20 驱动集成芯片 L298

    2023年04月10日
    浏览(55)
  • 【单片机毕业设计】基于STM32单片机蓝牙app遥控语音控制老年轮椅车GSM位置定位报警系统--物联网 单片机 嵌入式

            这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉小洪学长自己做的项目系统达不到老师的要求。为了大家能够顺利以及最少的精力通过毕设,小洪学长分享优质毕业

    2024年01月22日
    浏览(101)
  • 单片机/嵌入式小白教程—硬件(三)51单片机最小系统

    目录 简介 51单片机器件原理图 复位电路 供电电路 晶振电路 下载电路 最小系统原理图  更加方便的51单片机 传统51单片机最小系统包含:复位电路、供电电路、晶振电路、下载电路   其中, 第9脚(RST)为复位引脚, 第40脚(VCC)第20脚(GND)为供电引脚, 第19脚(XTAL1)第

    2024年02月08日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包