51单片机学习笔记13 红外遥控接收
- 一、红外遥控
- 1. **发射原理**
- 2. **接收原理**
- 3. **发射、接收示例**
- 二、编码、解码
- 1. **编码方式分类**:
- (1)Pulse Distance Modulation (PDM) 脉冲距离调制:
- (2)Pulse Width Modulation (PWM) 脉冲宽度调制:
- (3)Manchester Encoding 曼彻斯特编码:
- (4)Bi-Phase Encoding 双相编码:
- 2. 常见的红外编解码格式
- (1)**RC-5 和 RC-6**
- (2)**Sony SIRC(索尼红外编码)**
- (3)**Samsung 标准**
- (4)**NEC 日本电气公司**
- (5)**RAW (原始) 码**
- 3. NEC编解码详解
- (1)帧结构
- (2)脉冲编码
- (3)地址码
- (4)命令码
- (5)反码
- (6)结束码
- (7)连发码
- 4. 一体化红外遥控接收头
- 三、实现
- 1. 硬件电路设备
- 2. 软件实现
- (1)IO口及中断初始化
- (2)外部中断0
- 3. 使用main.c
一、红外遥控
红外遥控技术是一种常见的无线通信技术,常用于控制家电、汽车、电视机、音响系统等设备。其原理主要基于红外光的发射与接收。
1. 发射原理
- 发射器通常是一个红外二极管(IR LED),它能够将电能转换为红外光能。
- 当发射器接收到来自遥控器的信号时,会通过载波调制将信号转换为红外光信号,然后通过发射器发射出去。
- 这些红外光信号的频率一般在30kHz到60kHz之间,常用的有33K、36K、36.6K、38K、40K、56K等,其中38K使用最多。
- 在发射端要对晶振进行整数分频,分频系数一般取12,所以455kHz÷12≈37.9 kHz≈38kHz。
- 常用占空比有1/3、1/2,1/3最多。
2. 接收原理
- 接收器通常是一个红外接收模块(IR Receiver Module),它包括一个红外光敏元件和一个解调器。
- 红外光敏元件接收到发射器发射的红外光信号后,将其转换为电信号。
- 解调器对接收到的信号进行解调,将其还原为数字信号,然后发送给被控制设备的处理器或微控制器。
3. 发射、接收示例
二、编码、解码
1. 编码方式分类:
(1)Pulse Distance Modulation (PDM) 脉冲距离调制:
PDM 是一种基于脉冲的编码方式,它根据脉冲之间的距离来表示信息。通常,长脉冲和短脉冲分别代表不同的二进制位或符号。
(2)Pulse Width Modulation (PWM) 脉冲宽度调制:
PWM 是一种通过调节脉冲宽度来编码信息的方法。不同的脉冲宽度代表不同的符号或信息。
(3)Manchester Encoding 曼彻斯特编码:
曼彻斯特编码将每个比特位编码为两个等长的脉冲,根据脉冲的变化来表示信息。例如,高电平到低电平表示1,低电平到高电平表示0。
(4)Bi-Phase Encoding 双相编码:
双相编码将每个比特位分为两个阶段,根据信号的相位变化来编码信息。常见的双相编码包括差分曼彻斯特编码(Differential Manchester Encoding)。
2. 常见的红外编解码格式
NEC(日本电气公司)编解码格式是红外遥控器常用的一种标准格式,广泛应用于各种消费电子产品的遥控器中。它采用了一种特定的脉宽调制(PWM)编码方式。
(1)RC-5 和 RC-6
由飞利浦公司(现在的NXP半导体)开发的另两种常见的红外编码解码标准。RC-5 通常用于欧洲市场,而 RC-6 用于全球市场。
(2)Sony SIRC(索尼红外编码)
索尼公司开发的一种常见的红外编码格式,通常用于索尼品牌的遥控器中。
(3)Samsung 标准
三星公司采用的一种红外编码标准,用于其产品系列的遥控器中。
(4)NEC 日本电气公司
广泛用于各种消费电子产品。
(5)RAW (原始) 码
RAW 码不使用特定的编码格式,而是直接记录脉冲的时间间隔,可以通过分析脉冲的时间来解码。
3. NEC编解码详解
文档地址:https://www.sbprojects.net/knowledge/ir/nec.php
(1)帧结构
以下是使用 Markdown 表示 NEC 帧的组成部分的示例:
部分 | 描述 |
---|---|
引导脉冲 | NEC 编码帧的开始标志,通常是一个特定脉冲序列,用于同步接收器,9ms。 |
地址码 | 用于识别接收器要控制的设备,通常是 8 位二进制数。 |
反码 | 对地址码的按位取反,用于增强数据的可靠性。 |
命令码 | 表示具体的操作或命令,用于控制目标设备的功能。 |
命令反码 | 对命令码的按位取反,用于增强数据的可靠性。 |
结束码 | NEC 编码帧的结束标志,表示一个完整的指令。 |
一个完整的 NEC 编码帧通常由连续的脉冲序列组成,包括引导脉冲、地址码、反码、命令码、命令反码和结束码等部分。
(2)脉冲编码
NEC 编码器使用脉冲宽度调制(PWM)来编码信息,通常:
- 一个脉冲对应 560us 连续载波
- 逻辑1传输需要2.25ms(560us脉冲+1680us低电平)
- 逻辑0传输需要1.125ms(560脉冲+560us低电平)
接收端与发送端电平相反 。
下图是逻辑电平1、逻辑电平0的示例:
(3)地址码
在红外遥控器的通信过程中,地址码标识了特定的设备或设备组,它包含以下几个重要概念:
-
长度:
- 地址码的长度通常是 8 位二进制数,即包含 8 位 0 或 1 的序列。这种长度允许识别 256 个不同的设备或设备组。
-
编码规则:
- 采用脉冲宽度调制(PWM)方式。通常,逻辑 1 由一个特定宽度的脉冲表示,而逻辑 0 则由另一个宽度的脉冲表示。
-
设备识别:
- 接收器根据接收到的地址码来识别要控制的设备。在一个系统中,不同的设备或设备组通常被分配不同的地址码,以确保每个设备都可以准确地识别和响应来自遥控器的命令。
-
校验位:
- 在 NEC 编码格式中,通常会包含一个地址码的反码作为校验位,用于增强数据的可靠性。接收器在接收到地址码后,会对其进行校验,以确保数据的准确性。
-
地址范围:
- 由于地址码的长度为 8 位二进制数,因此地址码的地址范围是从 00000000 到 11111111(0 到 255)。这允许 NEC 编码格式支持多达 256 个不同的设备或设备组。
通过地址码,接收器能够准确地识别要控制的设备或设备组,从而确保遥控器发送的命令能够正确地被接收并执行。
(4)命令码
命令码用于表示遥控器发送的具体操作或命令。每个命令码都对应着一项特定的功能或动作,例如开启/关闭、音量调节、频道切换等,其主要概念:
-
长度:
命令码的长度通常是 8 位二进制数,与地址码相同。这种长度允许有 256 种不同的命令。 -
编码规则:
与地址码相同。 -
操作指令:
每个命令码都代表着一项具体的操作指令。例如,命令码 00000000 可能代表着“开启”操作,而命令码 11111111 可能代表着“关闭”操作。 -
校验位:
类似于地址码,命令码也可以包含一个校验位,通常是命令码的反码。这个校验位用于增强数据的可靠性,确保接收器正确地解码命令。 -
功能范围:
NEC 编码格式支持多种不同的功能和操作,因此命令码可以涵盖各种各样的控制命令。这些命令可以包括开关控制、音量调节、频道切换、模式选择等等。
(5)反码
除了地址码和命令码外,NEC 编码格式还包括反码,用于增强数据的可靠性。反码是对地址码和命令码的按位取反。
(6)结束码
结束码表示一个编码帧的结束,用于标识一个完整的指令。
(7)连发码
在用户按住遥控器上的某个按钮时,会连续发送相同的命令信号,直到用户释放按钮为止。
4. 一体化红外遥控接收头
一体化红外遥控接收头是一种集成了红外接收器功能的组件,它具有接收红外信号并解码的功能,一般支持多种协议 。
三、实现
1. 硬件电路设备
开发板在 P3.2上安装了红外接收头。
2. 软件实现
对红外的接收使用外部中断,出现下降沿时触发 。下面代码实现在按下遥控器按键后,数码管显示对应的控制码值,并通过串口输出控制码值。
(1)IO口及中断初始化
u8 ired_data[4];
/**
* @brief ired 初始化
*/
void ired_init(void){
// 使能外部中断0
IT0 = 1;
// 设置外部中断0下降沿触发
EX0 = 1;
// 使能总中断
EA = 1;
// 拉高IRED
IRED = 1;
}
(2)外部中断0
/**
* @brief ired 接收中断
*/
void ired() interrupt 0{
u8 i,j;
u16 time_cnt ;
// 保存高电平时间
u16 high_cnt;
// 是不是低电平
if(IRED == 0){
time_cnt = 1000;
// 高电平时退出
while((!IRED) && time_cnt){
delay_10us(1);
time_cnt--;
}
if(time_cnt==0)return;
// ired接收到信号, 10ms内进入高电平
if(IRED){
// 4.5ms高电平结束,超过5ms就是错误信号
time_cnt = 500;
while(IRED && time_cnt){
delay_10us(1);
time_cnt--;
}
if(time_cnt==0)return;
// 接收数据,地址码、地址反码、控制码、控制反码
for(i=0;i<4;i++){
for(j=0;j<8;j++){
// 0.56ms低电平(这里使用600us)
time_cnt = 600;
while(IRED==0 && time_cnt){
delay_10us(1);
time_cnt--;
}
// 大于560us,非正常信号
if(time_cnt==0)return;
// 判断高电平时间,0 560us, 1680us
time_cnt = 20;
high_cnt = 0;
while(IRED && time_cnt){
delay_10us(10);
time_cnt--;
high_cnt++;
}
// 超时
if(time_cnt==0)return;
ired_data[i] >>= 1;
// 大于800us就认为是1
if(high_cnt>=8){
// 高电平
ired_data[i] |= 0x80;
}
}
}
// 反码判断数据是否正确
if(ired_data[2] != ~ired_data[3] ){
// 数据错误
for(i=0;i<4;i++){
ired_data[i] = 0;
}
}
}
}
}
3. 使用main.c
#include "led_utils.h"
#include "ired_utils.h"
#include "segment_display_utils.h"
#include "uart_utils.h"
/**
* @brief 主函数
*/
void main()
{
// 关闭所有led
led_all_off();
ired_init();
// 速率 9600
uart_init(0xfa);
while(1)
{
uart_send(0);
uart_send(ired_data[2]);
uart_send(1);
segment_show_u8(0, ired_data[2]);
}
}
本文代码开源地址:
https://gitee.com/xundh/learn51.git