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

news/2025/1/12 17:28:48/

内容

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

红外遥控介绍

红外线简介

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

其中红光的波长范围为 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,数码管上显示对应键值编码;
在这里插入图片描述


http://www.ppmy.cn/news/1008857.html

相关文章

Django架构图

1. Django 简介 基本介绍 Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架 使用 Django&#xff0c;只要很少的代码&#xff0c;Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容&#xff0c;并进一步开发出全功能的 Web 服务 Django 本身…

使用七牛云、阿里云、腾讯云的对象存储上传文件

说明&#xff1a;存在部分步骤省略的情况&#xff0c;请根据具体文档进行操作 下载相关sdk composer require qiniu/php-sdkcomposer require aliyuncs/oss-sdk-php composer require alibabacloud/sts-20150401composer require qcloud/cos-sdk-v5 composer require qcloud_s…

Redis | 主从模式

Redis | 主从模式 1. 简介 Redis主从模式&#xff08;Replication&#xff09;是Redis提供的一种数据备份和高可用性解决方案。通过主从复制&#xff0c;可以将一个Redis服务器的数据复制到其他多个从服务器&#xff0c;从而实现数据的备份和读写分离&#xff0c;提高系统的性…

Spring Boot读取yml或者properties配置信息

文章目录 Spring Boot读取yml或者properties配置信息方法一&#xff1a;Value获取基本信息&#xff0c;适用于少量信息方法二&#xff1a;通过注解ConfigurationProperties(prefix "spring.datasource")方法三&#xff1a;通过api Environment Spring Boot读取yml或…

Android查漏补缺

&#xff08;1&#xff09;android apk编译步骤 ①&#xff0c;aapt工具生成.R文件 ②&#xff0c;javac编译为字节码 ③&#xff0c;dex工具打包为.dex文件 ④&#xff0c;aapt工具打包资源未见为.ap文件 ⑤&#xff0c;apkbuilder工具打包为apk文件 ⑥&#xff0c;keyt…

Linux 内核音频数据传递主要流程

Linux 用户空间应用程序通过声卡驱动程序&#xff08;一般牵涉到多个设备驱动程序&#xff09;和 Linux 内核 ALSA 框架导出的 PCM 设备文件&#xff0c;如 /dev/snd/pcmC0D0c 和 /dev/snd/pcmC0D0p 等&#xff0c;与 Linux 内核音频设备驱动程序和音频硬件进行数据传递。PCM 设…

2.文件的逻辑结构

第四章 文件管理 2.文件的逻辑结构 顺序文件采用顺序存储则意味着各个逻辑上相邻的记录在物理上也是相邻的存储的。所以如果第0号记录的逻辑地址为0的话&#xff0c;则i号记录的逻辑为i *L。 特别的如果这个定长记录的顺序文件采用串结构&#xff0c;也就是这些记录的顺序和他…

Go For Web:Golang http 包详解(源码剖析)

正文&#xff1a; Golang http 包详解&#xff08;源码剖析&#xff09; 前面小节我们认识了 Web 的工作方式&#xff0c;也成功用 Go 搭建了一个最简单的 Web 服务了解了 Golang 运行 Web 的原理。现在我们详细地去解剖以下 http 包&#xff0c;看看它如何实现整个过程的 Go…