STC12红外接收与NEC解码

news2024/11/17 21:38:07

文章目录

  • 一、红外通信简介
  • 二、红外遥控组成
  • 三、NEC协议简介
  • 四、红外接收与NEC解码例程
  • 五、参考资料

一、红外通信简介

红外通信是一种无线通信技术,利用红外光传输信息。红外光波长介于可见光和微波之间,通常在780纳米至1毫米的范围内。红外通信在许多领域得到广泛应用,例如消费电子产品(如遥控器)、安防系统、智能家居、医疗设备、工业自动化等。它具有以下几个特点和优点:

  1. 无线性:红外通信不需要物理连接,通过红外光传输信息,实现无线通信,方便灵活。
  2. 高安全性:由于红外光的传播范围较短,相对不易受到干扰,通信较为安全。
  3. 低功耗:红外通信设备通常使用低功耗的电子元件,适合电池供电的设备。
  4. 成本较低:红外通信设备的制造和维护成本相对较低。

红外通信的一个典型应用是红外遥控器。遥控器将电信号转换成红外光信号发送给待控制的设备,设备通过红外接收器接收到信号后进行解码并执行相应操作。

请添加图片描述
在红外通信中,不同的通信协议规定了红外信号的编码和解码方式,常见的协议包括NEC、RC5、RC6等。通信双方必须使用相同的协议保证正确的通信。总体而言,红外通信是一种简单实用的无线通信技术,在广泛的应用领域发挥着重要的作用。

本篇文章使用STC12单片机接收红外遥控型号,并进行NEC解码。

二、红外遥控组成

在使用红外遥控器时,当用户按下某个按键时,驱动电路会解读按键信息,然后将对应的指令转换成特定的红外信号。红外发射装置发射出的红外光信号被目标设备的红外接收器接收并解码,完成相应的操作。

需要注意的是,不同的红外遥控器可能使用不同的红外通信协议和编码方式,因此在选择红外遥控器时,需要确保它与所控制的目标设备兼容。

总结来说,红外遥控器由按键、红外发射装置、驱动电路、电源和电路板、封装和外壳等组成,通过发射红外光信号实现与目标设备的通信和控制。
请添加图片描述
在这里插入图片描述

三、NEC协议简介

NEC编码是一种常用的红外通信协议,用于遥控器等设备的红外通信。它是由NEC Corporation(日本电气公司)开发的,被广泛应用于各种消费电子产品中,如电视遥控器、音视频设备、空调遥控器等。

NEC编码使用的是脉宽编码调制(PWM)方式,通过控制红外发射器的脉冲宽度来表示不同的信息。NEC编码的一个典型信号由一个引导码(Header Pulse)、一个逻辑"0"的时间间隔(Logic “0” Pulse)和逻辑"1"的时间间隔(Logic “1” Pulse)组成。

NEC编码的时间间隔定义如下:

  1. 引导码的脉冲宽度为9ms的高电平脉冲,后跟4.5ms的低电平间隔。
  2. 逻辑"0"的脉冲宽度为0.56ms的高电平脉冲,后跟0.56ms的低电平间隔。
  3. 逻辑"1"的脉冲宽度为0.56ms的高电平脉冲,后跟1.69ms的低电平间隔。
  4. NEC编码的数据格式通常为32位,包括一个8位的地址码(Address)和一个8位的命令码(Command),以及它们的反码。

使用NEC编码时,发送端通过在一系列时间间隔内发送特定的脉冲宽度来表示不同的信息,接收端接收到红外信号后根据脉冲宽度解码并执行相应的操作。NEC编码作为一种简单和可靠的红外通信协议,在许多遥控器和其他红外设备中得到了广泛应用。
在这里插入图片描述

四、红外接收与NEC解码例程

#include <STC12C5A60S2.H>
#include <intrins.h>



//定义接口功能
sbit buzzer 					= P2^3;//蜂鸣器
sbit IR								= P3^2;//红外接收器



//时钟选择宏定义
#define MAIN_Fosc		11059200L
//#define MAIN_Fosc		12000000L



//相关接口功能宏定义
#define buzzer_OFF	buzzer = 1;//关蜂鸣器
#define buzzer_ON		buzzer = 0;//开蜂鸣器
#define EA_ON				EA 		 = 1;//开总中断
#define EA_OFF			EA     = 0;//关总中断



//对已有数据类型重新定义
typedef signed char int8;  		//8位有符号型
typedef signed int  int16; 		//16位有符号型
typedef unsigned char uint8;  //8位无符号型
typedef unsigned char uchar;  //8位无符号型
typedef unsigned int  uint16; //16位无符号型
typedef unsigned int  uint; 	//16位无符号型
typedef unsigned long uint32; //32位无符号型
typedef unsigned char BYTE;	  //8位无符号型
typedef unsigned int WORD;	  //16位无符号型



//变量宏定义
uchar IRtime; 			//检测红外高电平持续时间(脉宽)
uchar IRcord[4];    //此数组用于储存分离出来的4个字节的数据(用户码2个字节+键值码2个字节)
uchar IRdata[33];   //此数组用于储存红外的33位数据(第一位为引导码用户码16+键值码16)
bit IRpro_ok, IRok; //第一个用于红外接收4个字节完毕。IRok用为检测脉宽完毕



//基于STC12单片机1ms延时函数
//函数说明:内部调用
static void Delay1ms()		
{
	# if MAIN_Fosc == 11059200L
	//晶振11.0592MHz
	unsigned char i, j;

	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
	
	#elif MAIN_Fosc == 12000000L
	//晶振12.000000MHZ
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 12;
	j = 168;
	do
	{
		while (--j);
	} while (--i);
	
	#endif
	
}

//基于STC12单片机ms延时函数
//函数说明:外部调用
void Delay_ms(uint16 time)
{
	int i;
	for(i=0; i<time; i++)
	{
		Delay1ms();
	}
}

//串口初始化,晶振11.0592,波特率9600
void UartInit(void)//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x04;		//独立波特率发生器时钟为Fosc,即1T
	BRT = 0xDC;			//设定独立波特率发生器重装值
	AUXR |= 0x01;		//串口1选择独立波特率发生器为波特率发生器
	AUXR |= 0x10;		//启动独立波特率发生器
}

/***************************************
 *函数名称:void sendArray(uchar *s, uint len)
 *函数输入:*s 发送的数组指针,len数组长度
 *函数返回:无
 *函数说明:向串口发送一段数组
 ***************************************/
void sendArray(uchar *s, uint len)
{
	uint i;
	for(i=0; i<len; i++)
	{
		SBUF = *s++;
		while(!TI);
		TI = 0;
	}
}


//定时器0初始化
void Timer0_Init(void)
{
	TMOD = 0x22; //定时器0和定时器1工作方式2,8位自动重装
	TH0 = 0x00;  //高8位装入0那么定时器溢出一次的时间是256个机器周期
	TL0 = 0x00;
	ET0 = 1;	   //定时器0中断
	TR0 = 1;     //启动定时器0
}

//外部中断0初始化
void externalInterrupt0_Init(void)
{
	IT0 = 1;	   //设置外部中断0为跳沿触发方式,来一个下降沿触发一次
	EX0 = 1;	   //启动外部中断0
}

//提取它的33次脉宽进行数据解码
void IRcordpro(void)
{
	uchar i, j, k, cord, value;	/*i用于处理4个字节,j用于处理一个字节中每一位,k用于33次脉宽中的哪一位
	cord用于取出脉宽的时间判断是否符合1的脉宽时间*/
	k = 1; 						//从第一位脉宽开始取,丢弃引导码脉宽
	for(i = 0; i < 4; i++)
	{
		for(j = 0; j < 8; j++)
		{
			cord = IRdata[k];	    //把脉宽存入cord
			if(cord > 5)	 		//如果脉宽大于我11.0592的t0溢出率为约278us*5=1390那么判断为1
			value = value | 0x80;	/*接收的时候是先接收最低位,
			把最低位先放到value的最高位在和0x08按位或一下
			这样不会改变valua的其他位的数值只会让他最高位为1*/
			if(j < 7)
			{
				value = value >> 1;	//value位左移依次接收8位数据。
			}
			k++;				//每执行一次脉宽位加1
		}
		IRcord[i] = value;	   //每处理完一个字节把它放入IRcord数组中。
		value = 0; 			   //清零value方便下次在存入数据
	}
	IRpro_ok = 1;				   //接收完4个字节后IRpro ok置1表示红外解码完成	
}


void main()
{	
	UartInit();										//串口初始化
	Timer0_Init();								//定时器0初始化
	externalInterrupt0_Init();		//外部中断0初始化
	EA_ON;												//开总中断
	
	while(1)
	{
		if(IRok)    		//判断脉宽是否检测完毕                    
		{   
			IRcordpro();	//根据脉宽解码出4个字节的数据
			IRok = 0;			//重新等待脉宽检测
			if(IRpro_ok) 	//判断是否解码完毕  
			{
				sendArray(&IRcord[0], 4);
				IRpro_ok = 0;
			}
		}
	}
}

//定时器0中断处理函数
void timer0(void) interrupt 1
{
	IRtime++;
}

//外部中断0处理函数
void int0() interrupt 0
{
	static uchar i;	 			//	声明静态变量(在跳出函数后在回来执行的时候不会丢失数值)i用于把33次高电平的持续时间存入IRdata
	static bit startflag;		//开始储存脉宽标志位
	if(startflag)	 			//开始接收脉宽检测
	{
		if( (IRtime < 53) && (IRtime >= 32) ) /*判断是否是引导码,底电平9000us+高4500us	
		这个自己可以算我以11.0592来算了NEC协议的引导码低8000-10000+高4000-5000 
		如果已经接收了引导码那么i不会被置0就会开始依次存入脉宽*/
			i = 0;				 //如果是引导码那么执行i=0把他存到IRdata的第一个位
		IRdata[i] = IRtime;  		 //以T0的溢出次数来计算脉宽,把这个时间存到数组里面到后面判断
		IRtime = 0;				 //计数清零,下一个下降沿的时候在存入脉宽
		i++; 					 //计数脉宽存入的次数
		if(i == 33) 				 //如果存入34次 数组的下标是从0开始i等于33表示执行了34次
		{
		 	IRok = 1;				 //那么表示脉宽检测完毕
			i = 0; 				 //把脉宽计数清零准备下次存入
			
			//开蜂鸣器
			buzzer_ON;Delay_ms(500);
			//关蜂鸣器
			buzzer_OFF;Delay_ms(500);
		}
	}
	else		  
	{
		IRtime = 0; 				 //引导码开始进入把脉宽计数清零开始计数
		startflag = 1;			 //开始处理标志位置1
	}
}

五、参考资料

本文章及例程主要参考清翔电子51单片机入门教程,文章开源供单片机学习交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/920443.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python爬虫10:selenium库

python爬虫10&#xff1a;selenium库 前言 ​ python实现网络爬虫非常简单&#xff0c;只需要掌握一定的基础知识和一定的库使用技巧即可。本系列目标旨在梳理相关知识点&#xff0c;方便以后复习。 申明 ​ 本系列所涉及的代码仅用于个人研究与讨论&#xff0c;并不会对网站产…

一文详解:安防监控视频AI智能分析平台区域入侵/周界报警

区域入侵/周界报警入侵检测技术是TSINGSEE青犀智能分析平台推出的一种视频监控系统&#xff0c;可检测划定区域内是否有可疑人员并且在检测出这样的事件时生成警报。 视频监控/安防监控/视频存储TSINGSEE青犀视频智能分析平台可以在监控范围内划定特定区域&#xff0c;有人员入…

业务系统架构实践总结

我从2015年起至今2022年&#xff0c;在业务平台&#xff08;结算、订购、资金&#xff09;、集团财务平台&#xff08;应收应付、账务核算、财资、财务分析、预算&#xff09;、本地生活财务平台&#xff08;发票、结算、预算、核算、稽核&#xff09;所经历的业务系统研发实践…

记录解决IOS滚动跳转不生效问题

目录 背景 &#xff1a; 解决过程 &#xff1a; 解决方案 &#xff1a; 最终代码 &#xff1a; 背景 &#xff1a; 项目类似于问卷星里面的问卷调查&#xff0c;当你点击提交按钮时&#xff0c; 页面会有弹窗提醒你有哪些题型没回答&#xff0c;点击确认之后&#xff0c; 页…

C++学习-特殊的6个函数

设计一个Per类&#xff0c;类中包含私有成员&#xff1a;姓名&#xff0c;年龄&#xff0c;指针成员身高&#xff0c;体重&#xff0c;在设计一个stu类&#xff0c;类中包含私有成员&#xff1a;成绩&#xff0c;Per类对象p1,设计这两类的构造函数&#xff0c;析构函数和拷贝函…

2000-2020年全国各地级市资本存量测算数据(以2000年为基期)(含原始数据和测算过程)

2000-2020年全国各地级市资本存量测算数据&#xff08;以2000年为基期&#xff09;&#xff08;含原始数据和测算过程&#xff09; 1、时间&#xff1a;2000-2020年 2、来源&#xff1a;整理自城市统计年鉴、省份统计年鉴以及各市的公报 3、指标&#xff1a;固定资产投资总额…

DevOps团队如何提高Kubernetes性能

今天&#xff0c;Kubernetes仍然是开发人员最需要的容器。Kubernets最初由 Google 工程师开发&#xff0c;作为跨本地、公共云、私有云或混合云托管的首选解决方案享誉全球。 来自Statista的报告显示&#xff0c;公共云中的Kubernetes市场份额在过去一年中上升了近30%。并且在…

Pandas数据清洗和常用函数

数据清洗 数据清洗是对一些没用的数据进行处理的过程。 当数据出现确实、数据格式错误、错误数据或重复数据的情况&#xff0c;如果我们想要分析的更加准确&#xff0c;就要对没用的数据进行处理。 此时我们学习采用菜鸟教程的数据作为案例&#xff0c;如下图所示。 在途中包…

IDEA常用插件之依赖关系查看Maven Helper

文章目录 安装使用 安装 使用 安装完成后点击pom.xml文件&#xff0c;可以查看Maven依赖关系

Linux下jenkins全量迁移到新服务器

文章目录 1、目的2、迁移1&#xff09;查看jenkins的主目录2&#xff09;登录要迁出的服务器打包3&#xff09;找到对应的war包4&#xff09;登录对应迁入服务&#xff0c;上传war包和打包的jenkins数据等5&#xff09;在新的服务器解压迁入的数据等&#xff0c;并查看端口是否…

新生录取信息收集

随着高等教育的普及&#xff0c;每年都有大量的学生被大学录取。对于学校来说&#xff0c;新生录取确认和信息收集是一项重要的工作&#xff0c;但也是一项繁琐而耗时的任务。然而&#xff0c;通过合理的规划和利用现代科技手段&#xff0c;我们可以轻松搞定这一工作&#xff0…

代码随想录第28天|93. 复原 IP 地址,78.子集, 90.子集II

93. 复原 IP 地址 回溯三部曲 1.递归参数&#xff1a;startIndex一定是需要的&#xff0c;因为不能重复分割&#xff0c;记录下一层递归分割的起始位置 2.递归终止条件 终止条件和131.分割回文串 (opens new window)情况就不同了&#xff0c;本题明确要求只会分成4段&#x…

系统安全——SpringBoot配置文件加密

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;SpringBoot、配置文件、明文加密☀️每日 一言&#xff1a;自己动手丰衣足食~ 一、前言 在日常开发中&#xff0c;项目中会有很多配置文件。比如SpringBoot项目核心的数据库配置、Redis账号密码…

Java基于SpringBoot+Vue实现酒店客房管理系统(2.0 版本)

文章目录 一、前言介绍二、系统结构三、系统详细实现3.1用户信息管理3.2会员信息管理3.3客房信息管理3.4收藏客房管理3.5用户入住管理3.6客房清扫管理 四、部分核心代码 博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云…

openGauss学习笔记-48 openGauss 高级数据管理-函数

文章目录 openGauss学习笔记-48 openGauss 高级数据管理-函数48.1 数学函数48.2 三角函数列表48.3 字符串函数和操作符48.4 类型转换相关函数 openGauss学习笔记-48 openGauss 高级数据管理-函数 openGauss常用的函数如下&#xff1a; 48.1 数学函数 abs(x) 描述&#xff1a;…

网络安全—黑客技术(自学笔记)

一、网络安全应该怎么学&#xff1f; 1.计算机基础需要过关 这一步跟网安关系暂时不大&#xff0c;是进入it行业每个人都必须掌握的基础能力。 计算机网络计算机操作系统算法与数据架构数据库 Tips:不用非要钻研至非常精通&#xff0c;可以与学习其他课程同步进行。 2.渗透技…

百度23Q2财报最新发布:营收利润加速增长,AI+生态战略渐显规模

百度集团-SW(9888.HK)Q2财报已于2023/08/22(美东)盘前发布&#xff0c;二季度百度集团整体收入实现341亿元&#xff0c;同比增长15%;归属百度的净利润(non-GAAP)达到80亿元&#xff0c;同比增长44%。营收和利润双双实现大幅增长&#xff0c;超市场预期。其中&#xff0c;百度核…

【Linux操作系统】Linux中的信号回收:管理子进程的关键步骤

在Linux中&#xff0c;我们可以通过捕获SIGCHLD信号来实现对子进程的回收。当一个子进程终止时&#xff0c;内核会向其父进程发送SIGCHLD信号。父进程可以通过注册信号处理函数&#xff0c;并在处理函数中调用wait()或waitpid()函数来回收已终止的子进程。 文章目录 借助信号捕…

stm32之3.key开关

假设key电阻为40kΩ&#xff0c;则key0 的电压3.3v*4/52.64v 2.key开关代码 ② GPIO_OType_PP//推挽输出 GPIO_OType_PP//开漏输出 推挽输出是指输出端口可以同时提供高电平和低电平输出&#xff0c;而开漏输出则是指输出端口只能提供低电平输出&#xff0c;高电平时需要借…

Java加载ICC文件的方法总结

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…