嵌入式开发学习(STC51-15-红外遥控)

内容

使用外部中断功能,使按下红外遥控器,将对应键值编码数据解码后通过数码管显示

红外遥控介绍

红外线简介

人的眼睛能看到的可见光按波长从长到短排列,依次为红、橙、黄、绿、青、蓝、紫;

其中红光的波长范围为 0.62~0.76μm;紫光的波长范围为 0.38~0.46μm;比紫光波长还短的光叫紫外线,比红光波长还长的光叫红外线;

红外线遥控就是利用波长为0.76~1.5μm之间的近红外线来传送控制信号的;

红外遥控的原理

红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠,功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,并越来越多的应用到计算机系统中;

红外遥控通信系统一般由红外发射装置和红外接收设备两大部分组成;

红外发射装置

红外发射装置,也就是通常我们说的红外遥控器是由键盘电路、红外编码电路、电源电路和红外发射电路组成;

红外发射电路的主要元件为红外发光二极管,它实际上是一只特殊的发光二极管,由于其内部材料不同于普通发光二极管,因而在其两端施加一定电压时,它便发出的是红外线而不是可见光;

目前大量的使用的红外发光二极管发出的红外线波长为940nm左右,外形与普通发光二极管相同;

通常红外遥控为了提高抗干扰性能和降低电源消耗,红外遥控器常用载波的方式传送二进制编码,常用的载波频率为38kHz,这是由发射端所使用的455kHz晶振来决定的;在发射端要对晶振进行整数分频,分频系数一般取12,所以455kHz÷12≈37.9kHz≈38kHz;也有一些遥控系统采用36kHz、40kHz、56kHz等,一般由发射端晶振的振荡频率来决定;

所以,通常的红外遥控器是将遥控信号(二进制脉冲码)调制在38KHz的载波上,经缓冲放大后送至红外发光二极管,转化为红外信号发射出去的;

二进制脉冲码的形式有多种,其中最为常用的是NEC Protocol的PWM码(脉冲宽度调制)和Philips RC-5 Protocol的PPM码(脉冲位置调制码,脉冲串之间的时间间隔来实现信号调制);

如果要开发红外接收设备,一定要知道红外遥控器的编码方式和载波频率,我们才可以选取一体化红外接收头和制定解码方案;

红外接收设备

红外接收设备是由红外接收电路、红外解码、电源和应用电路组成;

红外遥控接收器的主要作用是将遥控发射器发来的红外光信好转换成电信号,再放大、限幅、检波、整形,形成遥控指令脉冲,输出至遥控微处理器;

红外接收头的封装大致有两种:一种采用铁皮屏蔽,一种是塑料封装;均有三只引脚,即电源正(VDD)、电源负(GND)和数据输出(VOUT);

从正对接收头的凸起处看,从左至右,管脚依次是 1:VOUT,2:GND,3:VDD;

数据传输

我们使用的红外遥控器使用的是NEC协议,其特征如下:
1、8位地址和8位指令长度;
2、地址和命令2次传输(确保可靠性);
3、PWM脉冲位置调制,以发射红外载波的占空比代表“0”和“1”;
4、载波频率为38Khz;
5、位时间为1.125ms或2.25ms;

NEC码的位定义:一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms(560us脉冲+1680us低电平),一个逻辑0的传输需要1.125ms(560us脉冲+560us低电平);

红外接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平;

因此,我们在接收头端收到的信号为:逻辑1应该是560us低+1680us高,逻辑0应该是560us低+560us高;

所以可以通过计算高电平时间判断接收到的数据是0还是1;

NEC码位定义时序图如下图所示:
在这里插入图片描述

NEC遥控指令的数据格式为:引导码、地址码、地址反码、控制码、控制反码;

引导码由一个9ms的低电平和一个4.5ms的高电平组成,地址码、地址反码、控制码、控制反码均是8位数据格式;

按照低位在前,高位在后的顺序发送;

采用反码是为了增加传输的可靠性(可用于校验);

数据格式如下:
在这里插入图片描述

NEC码还规定了连发码(由9ms低电平+2.5m高电平+0.56ms低电平+97.94ms高电平组成),如果在一帧数据发送完毕之后,红外遥控器按键仍然没有放开,则发射连发码,可以通过统计连发码的次数来标记按键按下的长短或次数;

原理图

在这里插入图片描述
由上图可知,开发板的红外装置的数据输出口与外部中断0连接的管脚口p32共用;

红外接收头在没有脉冲的时候为高电平,当收到脉冲的时候为低电平;

所以我们可以通过外部中断的下降沿触发中断,在中断内通过计算高电平时间来判断接收到的数据是0还是1;

思路

使用外部中断0的下降沿触发方式,当接收到脉冲时进入中断函数;

在中断函数内部,通过高低电平的时间间隔来确定输入的数据;(注意还需要对控制码校验,防止出错)

编码

User

main.c

/*
 * @Description: 按下红外遥控器,将对应键值编码数据解码后通过数码管显示
 */
#include "public.h"
#include "smg.h"
#include "ired.h"

void main()
{
	u8 ired_buf[3];

	ired_init(); // 红外初始化

	while (1)
	{
		ired_buf[0] = gsmg_code[gired_data[2] / 16]; // 将控制码高4位转换为数码管段码
		ired_buf[1] = gsmg_code[gired_data[2] % 16]; // 将控制码低4位转换为数码管段码
		ired_buf[2] = 0X76;							 // 显示H的段码
		smg_display(ired_buf, 6);
	}
}

Public

public.h

#ifndef _public_H
#define _public_H

#include "reg52.h"

typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;

void delay_10us(u16 ten_us);
void delay_ms(u16 ms);

#endif

public.c

#include "public.h"

/**
 * @description: 延时函数,ten_us=1时,大约延时10us
 * @param {u16} ten_us 延时倍数
 * @return {*}
 */
void delay_10us(u16 ten_us)
{
	while (ten_us--)
		;
}

/**ms延时函数,ms=1时,大约延时1ms***
 * @param {u16} ms 延时倍数
 * @return {*}
 */
void delay_ms(u16 ms)
{
	u16 i, j;
	for (i = ms; i > 0; i--)
		for (j = 110; j > 0; j--)
			;
}

App/ired

ired.h

#ifndef _ired_H
#define _ired_H

#include "public.h"

// 管脚定义
sbit IRED = P3 ^ 2;

// 声明变量
extern u8 gired_data[4];

// 函数声明
void ired_init(void);

#endif

ired.c

#include "ired.h"

u8 gired_data[4]; // 存储4个字节接收码(地址码+地址反码+控制码+控制反码)

/**
 * @description: 红外端口初始化函数,外部中断0配置
 * @return {*}
 */
void ired_init(void)
{
	IT0 = 1;  // 下降沿触发
	EX0 = 1;  // 打开中断0允许
	EA = 1;	  // 打开总中断
	IRED = 1; // 初始化端口
}

/**
 * @description: 外部中断0服务函数
 * @return {*}
 */
void ired() interrupt 0 // 中断号必须对应上
{
	u8 ired_high_time = 0;
	u16 time_cnt = 0;
	u8 i = 0, j = 0;

	if (IRED == 0)
	{
		time_cnt = 100;
		while ((IRED == 0) && (time_cnt)) // 等待引导信号9ms低电平结束,若超过10ms强制退出
		{
			delay_10us(10); // 延时约10us
			time_cnt--;
			if (time_cnt == 0)
				return;
		}
		if (IRED) // 引导信号9ms低电平已过,进入4.5ms高电平
		{
			time_cnt = 50;
			while (IRED && time_cnt) // 等待引导信号4.5ms高电平结束,若超过5ms强制退出
			{
				delay_10us(10);
				time_cnt--;
				if (time_cnt == 0)
					return;
			}
			for (i = 0; i < 4; i++) // 循环4次,读取4个字节数据
			{
				for (j = 0; j < 8; j++) // 循环8次读取每位数据即一个字节
				{
					time_cnt = 60;
					while ((IRED == 0) && time_cnt) // 等待数据1或0前面的0.56ms低电平结束,若超过0.6ms强制退出
					{
						delay_10us(1);
						time_cnt--;
						if (time_cnt == 0)
							return;
					}
					while (IRED) // 等待数据1或0后面的高电平结束,若超过2ms强制退出
					{
						delay_10us(10); // 这里的延时不能太短,否则不能稳定的检测出高电平的时间,在0.1ms左右比较好
						ired_high_time++;
						if (ired_high_time > 20)
							return;
					}
					gired_data[i] >>= 1;	 // 先读取的为低位,然后是高位
					if (ired_high_time >= 8) // 如果高电平时间大于0.8ms,数据则为1,否则为0
						gired_data[i] |= 0x80;
					ired_high_time = 0; // 重新清零,等待下一次计算时间
				}
			}
		}
		if (gired_data[2] != ~gired_data[3]) // 校验控制码与反码,错误则返回
		{
			for (i = 0; i < 4; i++)
				gired_data[i] = 0;
			return;
		}
	}
}

App/smg

smg.h

#ifndef _smg_H
#define _smg_H

#include "public.h"

#define SMG_A_DP_PORT P0 // 使用宏定义数码管段码口

// 定义数码管位选信号控制脚
sbit LSA = P2 ^ 2;
sbit LSB = P2 ^ 3;
sbit LSC = P2 ^ 4;

extern u8 gsmg_code[17]; // 使“共阴极数码管显示0~F的段码数据”这个变量定义为外部可用

void smg_display(u8 dat[], u8 pos);

#endif

smg.c

#include "smg.h"

// 共阴极数码管显示0~F的段码数据
u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};

/**
 * @description: 动态数码管显示函数
 * @param {u8} dat 要显示的数据
 * @param {u8} pos 从左开始第几个位置开始显示,范围1-8
 * @return {*}
 */
void smg_display(u8 dat[], u8 pos)
{
	u8 i = 0;
	u8 pos_temp = pos - 1;

	for (i = pos_temp; i < 8; i++)
	{
		switch (i) // 位选
		{
		case 0:
			LSC = 1;
			LSB = 1;
			LSA = 1;
			break;
		case 1:
			LSC = 1;
			LSB = 1;
			LSA = 0;
			break;
		case 2:
			LSC = 1;
			LSB = 0;
			LSA = 1;
			break;
		case 3:
			LSC = 1;
			LSB = 0;
			LSA = 0;
			break;
		case 4:
			LSC = 0;
			LSB = 1;
			LSA = 1;
			break;
		case 5:
			LSC = 0;
			LSB = 1;
			LSA = 0;
			break;
		case 6:
			LSC = 0;
			LSB = 0;
			LSA = 1;
			break;
		case 7:
			LSC = 0;
			LSB = 0;
			LSA = 0;
			break;
		}
		SMG_A_DP_PORT = dat[i - pos_temp]; // 传送段选数据
		delay_10us(100);							  // 延时一段时间,等待显示稳定
		SMG_A_DP_PORT = 0x00;						  // 消影
	}
}

编译和结果

按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机

结果:按下红外遥控器键位0,数码管上显示对应键值编码;
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flink Windows(窗口)详解

Windows&#xff08;窗口&#xff09; Windows是流计算的核心。Windows将流分成有限大小的“buckets”&#xff0c;我们可以在其上应用聚合计算&#xff08;ProcessWindowFunction&#xff0c;ReduceFunction&#xff0c;AggregateFunction或FoldFunction&#xff09;等。在Fl…

一、ADAS技术概述

根据《国家车联网产业标准体系建设指南》对智能网联汽车定义&#xff1a;智能网联汽车是指搭载先进的车载传感器、控制器、执行器等装置&#xff0c;并融合现代通信与网络技术&#xff0c;实现车与X&#xff08;人、车、路、云端等&#xff09;智能信息交换、共享&#xff0c;具…

阶段总结(linux基础)

目录 一、初始linux系统 二、基本操作命令 三、目录结构 四、文件及目录管理命令 查看文件内容 创建文件 五、用户与组管理 六、文件权限与压缩管理 七、磁盘管理 八、系统程序与进程管理 管理机制 文件系统损坏 grub引导故障 磁盘资源耗尽 程序与进程的区别 查…

【云原生】Serverless 技术架构分析

一、什么是Serverless? 1、Serverless技术简介 ​ Serverless&#xff08;无服务器架构&#xff09;指的是由开发者实现的服务端逻辑运行在无状态的计算容器中&#xff0c;它由事件触发&#xff0c; 完全被第三方管理&#xff0c;其业务层面的状态则被开发者使用的数据库和存…

交换机Vlan实验

介绍 Vlan表示虚拟局域网。 常见的网络安全技术 VlanACL Vlan的作用 Vlan隔离了广播域&#xff0c;增加了网络的安全性。 知识点 默认vlan vlan1 是默认vlan&#xff0c;主要机器开机了&#xff0c;默认所有的接口都属于Vlan1 交换机的接口模式 Access : 这个模式用来…

【设计模式】-建造者模式

Java建造者模式&#xff1a;创建复杂对象的灵活构建者 在软件开发中&#xff0c;我们经常遇到需要创建一个复杂对象的情况。如果使用传统的构造函数进行对象创建&#xff0c;可能会导致构造函数参数过多&#xff0c;难以管理和维护。建造者模式&#xff08;Builder Pattern&am…

MongoDB 使用总结

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

无人驾驶实战-第五课(动态环境感知与3D检测算法)

激光雷达的分类&#xff1a; 机械式Lidar&#xff1a;TOF、N个独立激光单元、旋转产生360度视场 MEMS式Lidar&#xff1a;不旋转 激光雷达的输出是点云&#xff0c;点云数据特点&#xff1a; 简单&#xff1a;x y z i &#xff08;i为信号强度&#xff09; 稀疏&#xff1a;7%&…

【肺炎分类数据集】数据量非常充足的新冠肺炎分类数据共享

一、肺炎数据集介绍&#x1f349;&#xff1a; 1.1 格式&#x1f388; 按照标准的格式分为了①训练集train&#xff08;134138575198张&#xff09;&#xff0c;②验证集val&#xff08;8816张&#xff09;&#xff0c;③测试集test&#xff08;234390624张&#xff09;&#…

Windows server上用nginx部署vue3项目

Windows server上用nginx部署vue3项目 一、Node中node_modules文件夹及package.json文件的作用说明二、VUE3项目打包三、Windows Server上的Nginx部署 一、Node中node_modules文件夹及package.json文件的作用说明 node_modules是安装node后用来存放用包管理工具下载安装的包的…

【项目 计网3】Socket介绍 4.9字节序 4.10字节序转换函数

文章目录 4.8 Socket介绍4.9字节序简介字节序举例 4.10字节序转换函数 4.8 Socket介绍 所谓 socket&#xff08;套接字&#xff09;&#xff0c;就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端&#xff0c;提供了应用层进…

VUE之JWT前后端分离认证,学生管理系统

参考资料: SpringBoot搭建教程 SpringCloud搭建教程 JWT视频教程 JWT官网 Vue视频教程 JWT视频参考资料、VUE视频资料,及前后端demo 特别有参考价值的JWT博客1 特别有参考价值的JWT博客2 cookie、localstorage和sessionStorage的区别1 cookie、localstorage和sessi…

总结七大排序!

排序总览 外部排序&#xff1a;依赖硬盘&#xff08;外部存储器&#xff09;进行的排序。对于数据集合的要求特别高&#xff0c;只能在特定场合下使用&#xff08;比如一个省的高考成绩排序&#xff09;。包括桶排序&#xff0c;基数排序&#xff0c;计数排序&#xff0c;都是o…

【数据库】将excel数据导入mysql数据库

环境&#xff1a;Windows10 mysql8以上 将你要导入的excel表另存为txt格式 打开txt格式文件&#xff0c;删除表头行并另存为并更改编码方式&#xff08;由于与数据库的编码不同&#xff0c;会导致导入报错&#xff09; 通过命令行登录数据库 winr cmd进入 进入装mysql的目录位…

软件设计原则

文章目录 一、软件设计原则1. 开闭原则2. 里氏代换原则3. 依赖倒转原则4. 接口隔离原则5. 迪米特法则6. 合成复用原则 一、软件设计原则 在软件开发中&#xff0c;为了提高软件系统的可维护性和可复用性&#xff0c;增加软件的可扩展性和灵活性&#xff0c;程序员要尽量根据软件…

【ASP.NET MVC】使用动软(四)(12)

一、筛选器类和Cookie实现路由 需解决的问题&#xff1a; 网站登录往往需要用户名密码验证&#xff0c;为避免重复验证&#xff0c;一般采用Cookie 、Session等技术来保持用户的登录状态&#xff1a; Session是在服务端保存的一个数据结构&#xff0c;用来跟踪用户的状态&…

Last-Mile Embodied Visual Navigation 论文阅读

论文阅读 题目&#xff1a;Last-Mile Embodied Visual Navigation 作者&#xff1a;JustinWasserman, Karmesh Yadav 来源&#xff1a;CoRL 时间&#xff1a;2023 代码地址&#xff1a;https://jbwasse2.github.io/portfolio/SLING Abstract 现实的长期任务&#xff08;例如…

antv/l7地图,鼠标滚动,页面正常滑动-- 我们忽略的deltaY

背景 在官网项目中&#xff0c;需要使用一个地图&#xff0c;展示产品的分布区域及数量。希望的交互是&#xff0c;鼠标放上标点&#xff0c;tooltip展示地点和数量等信息。鼠标滚动&#xff0c;则页面随着滚动。但是鼠标事件是被地图代理了的&#xff0c;鼠标滚动意味着地图的…

4,链表【p5】

链表 4.1哈希表简介4.2有序表简介4.3链表4.3.1例1-反转单向和双向链表4.3.2例2-打印两个有序链表的公共部分4.3.3面试时链表解题的方法论4.3.4例3-判断一个链表是否为回文结构4.3.4.1快慢指针 4.3.5例4-将单向链表按某值划分成左边小、中间相等、右边大的形式4.3.6例5-复制好友…

RabbitMQ - 简单案例

目录 0.引用 1.Hello world 2.轮训分发消息 2.1 抽取工具类 2.2 启动两个工作线程接受消息 2.4 结果展示 3.消息应答 3.1 自动应答 3.2 手动消息应答的方法 3.3 消息自动重新入队 3.4 消息手动应答代码 4.RabbitMQ 持久化 4.1 队列如何实现持久化 4.2 消息实现持久化 5.不…