登录/注册

STM32如何接收红外的信号

STM32如何接收红外的信号

更多

STM32 接收红外信号(主要指来自电视遥控器等设备的红外遥控信号)主要涉及硬件连接和软件解码两个核心部分。以下是详细步骤和关键点:

核心原理: 红外遥控器将按键信息编码(常用 NEC、RC5、Sony SIRC 等协议)后,调制在约 38kHz 的载波上发射出来。STM32 需要:

  1. 通过 红外接收头 将光信号转换成电信号,并解调(去掉 38kHz 载波)。
  2. 通过 GPIO 引脚 读取解调后的数字波形。
  3. 软件中解码 该波形,提取出地址码、命令码等信息。

步骤详解:

  1. 硬件准备与连接:

    • 红外接收头模块: 这是必不可少的元件(如 VS1838B, TSOP382xx, HS0038B 等)。它通常有 3 个引脚:
      • VCC: 接 3.3V 或 5V 电源(确保与 STM32 逻辑电平兼容,推荐 3.3V)。
      • GND: 接地。
      • OUT连接到 STM32 的一个 GPIO 引脚。这个引脚需要配置为输入模式。接收头的输出在没有接收到信号时一般是高电平(或上拉到高电平),接收到有效红外信号时,它会随着原始编码信号的高低电平变化。
    • STM32 开发板: 如 STM32F103C8T6 (Blue Pill), STM32F407 Discovery, Nucleo 系列等。
    • 连接示意图:
      [红外接收头]
        VCC ---- STM32 3.3V
        GND ---- STM32 GND
        OUT ---- STM32 GPIOx_Pin_y (e.g., PA0, PB10)
  2. 软件开发(解码): 解码的关键在于准确测量接收头 OUT 引脚上高低电平的持续时间。常用方法有:

    • 方法 1:外部中断 + 定时器(推荐且常用)

      • GPIO 配置: 将连接接收头 OUT 的 GPIO 引脚配置为 浮空输入或上拉输入 模式。
      • 外部中断配置: 使能该引脚的外部中断(EXTI),设置为 双边沿触发EXTI_Trigger_Rising_Falling),这样引脚电平每次变化(从高到低或从低到高)都会触发中断。
      • 定时器配置: 启用一个基本定时器(如 TIM2)。配置其时钟源(通常内部时钟),设置较高的计数速度和足够长的自动重装载值(ARR)。停止计数清零计数器 作为初始状态。
      • 中断服务程序(ISR):
        1. 当 EXTI 触发(检测到边沿)时:
          • 获取定时器当前的计数器值(TIM_GetCounter())。
          • 记录这个时刻(capture_time = TIM_GetCounter())。
        2. 判断边沿类型(上升沿或下降沿):
          • 如果是 下降沿(通常代表脉冲开始):记录起始时间 start_time = capture_time
          • 如果是 上升沿(通常代表脉冲结束):记录结束时间 end_time = capture_time,计算本次脉冲的持续时间:
            pulse_width = end_time - start_time; // 注意处理定时器溢出!
        3. pulse_width 与协议规定的时序(引导码、逻辑 0、逻辑 1、重复码等)进行比较,判断当前脉冲代表什么含义(起始位、逻辑位、停止位、重复码)。
        4. 根据协议规则组装数据位(address, command)。
        5. 检测到完整的帧(如 NEC 的 32 位)后,进行校验(如 NEC 的命令反码校验),若校验通过,则存储或处理接收到的数据。
        6. 超时处理: 在每次进入 EXTI 中断时启动一个软件计时器或利用另一个定时器实现超时检测。如果超过协议规定的最大帧间隔时间(通常几十毫秒)都没有新的边沿触发,则认为上一帧结束或出错,重置解码状态机。
    • 方法 2:定时器输入捕获模式(更精确,利用硬件)

      • 定时器配置: 使用支持输入捕获的定时器(如 TIMx_CHx)。
      • GPIO 配置: 将接收头的 OUT 引脚连接到选定的定时器捕获通道引脚(如 TIM2_CH1 -> PA0),并配置该引脚为浮空输入或上拉输入。
      • 输入捕获配置: 配置定时器通道为输入捕获模式,设置为 双边沿捕获TIM_ICPolarity_BothEdge)。
      • 中断/事件配置: 使能定时器的捕获中断(TIM_IT_CCx)。
      • 中断服务程序(ISR):
        1. 当捕获事件发生时(TIM_GetITStatus(TIMx, TIM_IT_CCx) == SET):
          • 读取当前捕获寄存器值(capture_val = TIM_GetCapturex(TIMx))。
        2. 判断触发捕获的边沿(通过检查通道配置极性标志位或状态寄存器):
          • 如果是 下降沿:记录 start_val = capture_val
          • 如果是 上升沿
            • 记录 end_val = capture_val
            • 计算脉冲宽度:
              pulse_width = end_val - start_val; // 注意处理定时器溢出!
        3. 后续步骤与方法 1 中的第 3-6 步相同:判断脉冲类型、组装数据、校验、超时处理。
  3. 协议解码(以 NEC 协议为例):

    • 引导码:9ms 低电平 + 4.5ms 高电平。
    • 数据码:32 位(地址 16bit + 地址反码 16bit + 命令 16bit + 命令反码 16bit。常用简化版本是地址 8bit + 地址反码 8bit + 命令 8bit + 命令反码 8bit)。
    • 逻辑 0:560us 低电平 + 560us 高电平。
    • 逻辑 1:560us 低电平 + 1.69ms 高电平。
    • 重复码:9ms 低电平 + 2.25ms 高电平 + 560us 低电平(之后不再发送数据,代表上次按键持续按下)。
    • 解码逻辑:
      • 检测到符合 9ms low + 4.5ms high 的引导码,开始接收数据。
      • 对后续每个脉冲(560us low 后跟一个高电平):
        • 测量高电平持续时间。
        • 如果高电平持续约 560us,判为逻辑 0
        • 如果高电平持续约 1.69ms,判为逻辑 1
      • 连续接收 32 位数据(按特定顺序,通常是 LSB first)。
      • 检查地址部分的反码是否正确。
      • 检查命令部分的反码是否正确。
      • 如果检验通过,提取有效的地址(address)和命令(command)。
      • 如果是重复码(9ms low + 2.25ms high),则视为重复上次的命令。

关键注意事项:

  1. 电平逻辑: 红外接收头输出是 反相 的!发送端的高电平(载波开启)在接收头输出是低电平;发送端的低电平(载波关闭)在接收头输出是高电平。解码时序时务必注意这个反相关系。
  2. 时序精度: 红外协议对时间要求严格(误差通常在 ±100us 内)。STM32 的系统时钟和定时器配置要确保足够精确和分辨率(微秒级)。
  3. 定时器溢出处理: 在计算 pulse_width = end_val - start_val 时,如果 end_val < start_val,说明定时器发生了溢出。此时脉冲宽度应为 (TimerPeriod - start_val) + end_valTimerPeriod 是定时器自动重装载值 ARR + 1)。
  4. 干扰滤波: 红外信号易受日光灯、环境光干扰。可以在软件中加入简单的滤波逻辑,比如连续多次检测到边沿才认为是有效信号,或者在读取 GPIO 时做多次采样取平均值。
  5. 协议多样性: 不同遥控器可能使用不同协议。NEC 最常见,但也可能是 RC5, RC6, Sony SIRC 等。需要根据目标遥控器的协议调整解码逻辑。有些库支持多种协议。
  6. 中断优先级: EXTI 中断和定时器捕获中断需要设置合理的优先级,确保能及时响应电平变化,避免丢失信号。
  7. 现有库: 可以利用现有的开源红外解码库(如 IRremote 库的 STM32 移植版)来简化开发,这些库通常已经实现了多种协议的解码和硬件抽象。

简化代码框架(基于外部中断 + 定时器):

// 变量定义
volatile uint32_t lastEdgeTime = 0;
volatile uint32_t pulseWidth = 0;
volatile uint8_t state = 0; // 解码状态机状态
volatile uint32_t irData = 0; // 存放接收到的数据
volatile uint8_t bitCount = 0;

// 接收头OUT连接的GPIO和EXTI配置 (例如 PA0)
void IR_GPIO_EXTI_Init(void) {
    // ... 配置GPIOA Pin0为输入, 上拉/浮空
    // ... 配置EXTI Line0 连接到 PA0
    // ... 设置EXTI为双边沿触发
    // ... 配置并启用EXTI中断 (NVIC)
}

// 定时器初始化 (例如 TIM2)
void IR_Timer_Init(void) {
    // ... 配置TIM2时钟源, 预分频(PSC), 自动重装载值(ARR) 以获得微秒级计数
    // ... 停止定时器 (TIM_Cmd(DISABLE))
    // ... 清零计数器 (TIM_SetCounter(0))
}

// EXTI中断服务程序 (例如 EXTI0_IRQHandler)
void EXTI0_IRQHandler(void) {
    if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
        uint32_t currentTime = TIM_GetCounter(TIM2); // 获取当前定时器值

        // 判断是否是下降沿 (接收头OUT输出从高变低, 对应发送端载波开启/发射)
        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET) {
            pulseWidth = currentTime - lastEdgeTime; // 计算高电平持续时间
            lastEdgeTime = currentTime;
            HandlePulse(pulseWidth, 0); // 处理高电平脉冲 (逻辑判断在下降沿做)
        } else { // 上升沿 (接收头OUT输出从低变高, 对应发送端载波关闭/停止发射)
            pulseWidth = currentTime - lastEdgeTime; // 计算低电平持续时间
            lastEdgeTime = currentTime;
            // NEC协议通常在下降沿判断逻辑位,上升沿这里只记录时间起点或处理特殊码
        }
        EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志
    }
}

// 处理测量到的脉冲宽度
void HandlePulse(uint32_t width, uint8_t edgeType) {
    // 重置超时计时器

    switch (state) {
        case 0: // 等待引导码
            if (width > NEC_HEADER_HIGH_MIN && width < NEC_HEADER_HIGH_MAX) {
                // 检测到可能是引导码后的高电平部分
                state = 1;
            }
            break;
        case 1: // 等待引导码低电平或重复码
            if (width > NEC_HEADER_LOW_MIN && width < NEC_HEADER_LOW_MAX) {
                state = 2; // 进入数据接收状态
                bitCount = 0;
                irData = 0;
            } else if (width > NEC_REPEAT_HIGH_MIN && width < NEC_REPEAT_HIGH_MAX) {
                // 处理重复码 (触发上次命令)
                handleRepeat();
                state = 0; // 回到初始状态
            } else {
                state = 0; // 时序错误,复位
            }
            break;
        case 2: // 接收数据位 (在下降沿判断)
            // 根据上一个高电平脉冲的宽度(pulseWidth)判断逻辑值
            if (width > NEC_BIT_1_MIN && width < NEC_BIT_1_MAX) {
                irData = (irData << 1) | 0x01; // 逻辑 '1' (MSB first)
            } else if (width > NEC_BIT_0_MIN && width < NEC_BIT_0_MAX) {
                irData = irData << 1; // 逻辑 '0' (MSB first)
            } else {
                state = 0; // 时序错误,复位
                break;
            }
            bitCount++;
            if (bitCount >= 32) { // 接收完32位
                // 校验地址和命令反码
                if (/* 地址反码正确 && 命令反码正确 */) {
                    uint8_t address = (irData >> 24) & 0xFF;
                    uint8_t command = (irData >> 8) & 0xFF;
                    handleCommand(address, command); // 处理有效命令
                }
                state = 0; // 回到初始状态
            }
            break;
    }
}

总结:

STM32 接收红外信号需要 红外接收头模块 作为前置硬件进行信号转换和解调。软件核心是利用 外部中断定时器输入捕获 功能精确测量接收头输出引脚上 高低电平的持续时间。开发者需要根据目标遥控器使用的 特定红外协议(如 NEC)编写解码逻辑,将测量到的脉冲宽度序列解析为有效的地址码和命令码。注意电平反相、时序精度、定时器溢出和干扰过滤等关键点。利用现有开源库可以加速开发。

红外接收头的主要功能_红外接收头的应用场景有哪些

红外接收头(又称红外线接收模组,IRM)是集成红外线

2024-10-21 16:04:44

红外接收头内部结构_红外接收头的作用

红外接收头是红外信号收发系统的典型电路元件,通常被集成在一个元件中,成为一体化红外接收

2024-10-21 16:02:24

红外接收头通用吗_红外接收头使用方法

红外接收头并不通用。不同品牌的红外接收头可能存在不兼容问题,因此不能互换使用。   红外接收头是一种用于

2024-10-21 15:58:01

红外接收改装电路图

红外接收改装电路图

资料下载 fs4523 2022-02-09 17:25:19

STM32红外接收分析

title: STM32红外接收分析date: 2020-06-18 00:45:12tags:categories: STM32学习记录

资料下载 贾熹 2021-12-01 09:51:06

stm32实现红外自发自收

基于stm32实现红外自发自收红外遥控简介红外发射

资料下载 靓仔峰 2021-11-25 10:36:07

红外测量控器的发射与接收电路设计

红外测量控器的发射与接收电路设计

资料下载 佚名 2021-06-27 10:08:37

如何使用STM32单片机实现红外测温仪的设计

利用嵌入式高性能ARM 的Cortex-M3 内核微控制器芯片STM32 进行红外测温仪的研制,给出了硬件设计的原理框图。重点阐述了信号处理、带

资料下载 佚名 2020-03-02 16:59:05

红外接收头好坏测量

红外接收头是一种重要的电子元件,用于接收红外线信号并将其转换为电

2024-10-21 15:49:41

STM32红外遥控信号自学习实现

STM32之红外遥控信号自学习实现

2023-09-18 15:52:02

红外接收二极管接收光的多少和输出信号的关系?

红外接收二极管:光的多少与输出信号的巧妙关系一、引言在光电检测系统中,红外接收二极管是一种非常重要的元件。它的作用是

2023-09-12 08:30:21

红外的简单发射接收原理及编解码解析

在发射端,输入信号经放大后送入红外发射管发射,在接收端,接收管收到

2022-09-15 17:15:25

STM32红外接收分析相关资料分享

title: STM32红外接收分析date: 2020-06-18 00:45:12tags:categories: STM32学习记录

2022-01-25 06:28:54

红外信号发射端与接收端的关系是什么?

红外信号发射端的原理是什么?红外信号发射端与

2022-01-18 07:18:13

hs0038红外接收电路

红外遥控有发送和接收两个组成部分。发送端采用单片机将待发送的二进制信号编码调制为一系列的脉冲串

2019-09-13 11:24:00

7天热门专题 换一换
相关标签