嵌入式开发学习(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); // 延时约10ustime_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,否则为0gired_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,数码管上显示对应键值编码;
相关文章:

嵌入式开发学习(STC51-15-红外遥控)
内容 使用外部中断功能,使按下红外遥控器,将对应键值编码数据解码后通过数码管显示 红外遥控介绍 红外线简介 人的眼睛能看到的可见光按波长从长到短排列,依次为红、橙、黄、绿、青、蓝、紫; 其中红光的波长范围为 0.62&…...
代码编辑器实践之vue-codemirror使用
前言 程序员用到IDE次数比较频繁,比如vscode、idea等,这些都是市场上比较流行的代码编辑器,拥有非常全面的功能。但是有时候在项目开发上也会用到代码编辑器,比如复杂的Array<Object>输入,或者需要用到用户交互…...
Mapstruct
1. Mapstruct介绍 1. 实体类之间对象映射中间件 2. 实体类相同结构属性自动对象映射 3. 实体类不同结构属性可以手动配置对象映射 2. Mapstruct基本使用 1. 定义一个接口或抽象类加Mapper(componentModel “spring”);spring:可以spring框架注入 2. 定义…...

初阶C语言——特别详细地介绍函数
系列文章目录 第一章 “C“浒传——初识C语言(更适合初学者体质哦!) 第二章 详细认识分支语句和循环语句以及他们的易错点 第三章 初阶C语言——特别详细地介绍函数 目录 系列文章目录 前言 一、函数是个什么鬼东西? 二、C语…...
pulsar-client-1-2 PulsarClient构造函数
前言 上文说到,PulsarClient通过链式调用构建,而在build()中调用了new PulsarClientImpl(conf),而Producer 本文通过解析构造函数,了解其主要结构。 // 创建PulsarClient PulsarClient client = PulsarClient.builder().serviceUrl("pulsar://localhost:6650")…...
原型链污染是什么
__proto__ 一个Foo类实例化出来的foo对象,可以通过foo.__proto__属性来访问Foo类的原型,也就是说: foo.__proto__ Foo.prototype 对象 构造函数 所以,总结一下: prototype是一个类的属性,所有…...
java之石头迷阵单击游戏、继承、接口、窗体、事件、组件、按钮、图片
文章目录 前言主方法实现类 前言 主方法和实现类在同一个包中。 主方法 package PSortGames;public class Main {public static void main(String[] args) {new MainFrame();} }实现类 package PSortGames;import javax.swing.*; import java.awt.event.KeyEvent; import jav…...
Debian 系列 Linux 的静态 DNS 、gateway 、IP 设置和网络重启
文章目录 DNS 设置DNS 配置文件DNS 配置文件内容 gateway、IP 设置网络适配器配置文件网络适配器配置文件内容 网络重启 各个 Linux 发行版的网络设置有很大不同。根据最近对 Debian 系列(含 Debian 12、基于 Debian 12 的Proxmox 8.0-2 以及基于Debian 11 的 openm…...

IP路由基础+OSPF 基础
IP路由 RIB与FIB RIB:Routing Information Base,路由信息库 ,路由器的控制平面 FIB:Forwarding Information Base,转发信息库,路由器的数据平面 路由信息库主要是记录直连路由以及协议宣告的路由信息&am…...
window远程连接Linux
Linux启用ssh服务 管理员权限进入root 安装 OpenSSH 服务器软件包 对于 Debian、Ubuntu 或基于这些发行版的系统,可以运行以下命令安装: sudo apt update sudo apt install openssh-server对于基于 Red Hat、CentOS 或 Fedora 的系统,可以…...

MyBatis 查询数据库之二(增、删、改、查操作)
目录 1. 配置打印 MyBatis 执行的SQL 2. 查询操作 2.1 通过用户 ID 查询用户信息、查询所有用户信息 (1) Mapper 接口 (2)UserMapper.xml 查询所有用户的具体实现 SQL (3)进行单元测试 3. 增加操作 3.1 在 mapper(interface)里面添加增加方法的声…...

unraid docker桥接模式打不开页面,主机模式正常
unraid 80x86版filebrowser,一次掉电后,重启出现权限问题,而且filebrowser的核显驱动不支持amd的VA-API 因为用不上核显驱动,解压缩功能也用不上,官方版本的filebrowser还小巧一些,18m左右 安装的时候总是…...

第七章:进程间通信(IPC)——构成进程间通信的信道方案
系列文章目录 文章目录 系列文章目录前言进程间通信介绍进程间通信目的进程间通信发展进程间通信分类进程通信的原理 管道什么是管道pipe管道通信特点简单设计 命名管道什么是命名管道mkfifostrcmp/strncasecmpunlinkgetch简单设计 共享内存什么是共享内存shmget/ftokipcsshmct…...

部分常用CSS样式
目录 1.字体样式 2.文本样式 3.鼠标样式 cursor 4.背景样式 5.列表样式 6.CSS伪类 7.盒子模型 1.字体样式 font-family 字体类型:隶书” “楷体” font-size 字体大小:像素px font-weight 字体粗细:bold 定义粗体字…...

思科单臂路由、lacp链路聚合、NAT实验
实验拓扑图: 实验目的: 如图所示配置相应IP地址和VLAN,并通过在AR1上配置单臂路由,实现VLAN10和VLAN20的主机能够在VLAN间通信;在SW1和SW2的三条链路实施链路聚合,使用静态LACP模式,使一条链…...

【力扣每日一题】2023.8.5 合并两个有序链表
目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 题目给我们两个有序的链表,要我们保持升序的状态合并它们。 我们可以马上想要把两个链表都遍历一遍,把所有节点的…...
QT 驱动条码打印机(没有验证过)
这里的打印机是条码打印机,因为第一次接触这种设备,所以买了斑马的GK888t型条码打印机,据说ZPL语言就是斑马的杰作想必支持会好点。实际是,除了ZPL本身外,没有SDK,也没有DDK,所以,一…...

Kafka介绍
目录 1,kafka简单介绍 2,kafka使用场景 3,kafka基本概念 kafka集群 数据冗余 分区的写入 读取分区数据 顺序消费 顺序消费典型的应用场景: 批量消费 提交策略 kafka如何保证高并发 零拷贝技术(netty&#…...

Django使用uwsgi+nginx部署,admin没有样式解决办法
Django使用uwsginginx部署,admin没有样式解决办法 如果使用了虚拟环境则修改nginx.conf文件中的/static/路径为你虚拟环境的路径,没有使用虚拟环境则改为你python安装路径下的static server {listen 8008;server_name location; #改为自己的域名,没域名…...

穷举深搜暴搜回溯剪枝(3)
一)字母大小写全排列 784. 字母大小写全排列 - 力扣(LeetCode) 1)从每一个字符开始进行枚举,如果枚举的是一个数字字符,直接忽视 如果是字母的话,进行选择是变还是不变 2)当进行遍历到叶子结点的时候,直接将…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...

android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...