零知开源——STM32红外通信YS-IRTM红外编解码器集成灯控与显示系统

✔零知IDE 是一个真正属于国人自己的开源软件平台,在开发效率上超越了Arduino平台并且更加容易上手,大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码,让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品,测试产品。快来动手试试吧!

✔访问零知实验室,获取更多实战项目和教程资源吧!

www.lingzhilab.com

目录

一、硬件设计部分

[1.1 硬件清单](#1.1 硬件清单)

[1.2 接线方案](#1.2 接线方案)

[1.3 具体连接图](#1.3 具体连接图)

[1.4 实物接线图](#1.4 实物接线图)

二、软件代码详解

[2.1 发送端代码(YS-IRTM)](#2.1 发送端代码(YS-IRTM))

1.软串口发送编码字节

2.读取NEC编码

[2.2 接收端代码(IR Receiver)](#2.2 接收端代码(IR Receiver))

1.初始化定义

2.红外接收数据处理

[2.3 红外编码处理流程](#2.3 红外编码处理流程)

三、系统演示效果

[3.1 性能测试](#3.1 性能测试)

[3.2 视频演示](#3.2 视频演示)

四、NEC红外协议

[4.1 NEC编码方式](#4.1 NEC编码方式)

[4.2 数据帧结构](#4.2 数据帧结构)

[4.3 扩展NEC协议](#4.3 扩展NEC协议)

五、常见问题解答

[Q1: 如何提高红外通信的距离和稳定性?](#Q1: 如何提高红外通信的距离和稳定性?)

[Q2: 遇到解码错误或信号干扰怎么办?](#Q2: 遇到解码错误或信号干扰怎么办?)


(1)项目概述

本项目基于零知开发板系列(标准板和增强板)构建了一个完整的红外通信控制系统,实现了通过红外信号远程控制LED灯状态并在显示屏上实时显示控制信息的功能。发送端使用零知增强板通过YS-IRTM红外编解码模块发送编码后的红外信号。接收端使用零知标准板接收红外信号,解析后控制LED灯开关并在240×240分辨率的ST7789屏幕上显示接收信息。

红外通信模块

>YS-IRTM红外编解码模块:集成了红外发射和接收功能,支持多种红外协议,可通过串口进行控制

>IR Receiver红外接收器:常用的红外接收头,能够接收和解码38kHz载波的红外信号

(2)项目难点及解决方案

问题描述:原始红外编码(如0XFF6897)与YS-IRTM模块所需的编码格式(如A1 F1 00 FF 16)之间存在显著差异,需要建立准确的映射关系。

**解决方案:**通过实验测试确定两种编码格式之间的对应关系,创建映射表并在发送端实现格式转换功能。

一、硬件设计部分

1.1 硬件清单

组件 型号/规格 数量
零知标准板 STM32F103RBT6 1
零知增强板 STM32F407VET6 1
YS-IRTM红外编解码模块 支持串口控制 1
IR Receiver红外接收器 38kHz 1
ST7789显示屏 240×240分辨率 1
LED灯 5mm 1

1.2 接线方案

发送端(零知增强板+YS-IRTM)

零知增强板引脚 YS-IRTM模块引脚 功能
3.3V VCC 电源
GND GND 地线
10 TX 数据接收
9 RX 数据发送

接收端(零知标准板)

零知标准板引脚 外设 功能
3.3V IR Receiver VCC 电源
GND IR Receiver GND 地线
6 IR Receiver OUT 数据输出
2 LED阳极 LED控制
10 ST7789 CS 片选
9 ST7789 DC 数据/命令
8 ST7789 RST 复位
7 ST7789 BL 背光控制
11 ST7789 SDA 数据输入
13 ST7789 SCL 时钟

1.3 具体连接图

(1)发送端接线

将零知增强板上的11引脚用作软串口的TX、10引脚用作软串口的RX控制YS-IRTM红外编解码器收发数据

(2)接收端接线

1.4 实物接线图

二、软件代码详解

2.1 发送端代码(YS-IRTM)

1.软串口发送编码字节

cpp 复制代码
#include <SoftwareSerial.h>

// 软串口引脚定义
#define SOFT_RX 10
#define SOFT_TX 11

// 解码后的编码映射 - 以字节数组形式存储
byte irCodes[10][5] = {
  {0xA1, 0xF1, 0x00, 0xFF, 0x16}, // 0
  {0xA1, 0xF1, 0x00, 0xFF, 0x0C}, // 1
  {0xA1, 0xF1, 0x00, 0xFF, 0x18}, // 2
  {0xA1, 0xF1, 0x00, 0xFF, 0x5E}, // 3
  {0xA1, 0xF1, 0x00, 0xFF, 0x08}, // 4
  {0xA1, 0xF1, 0x00, 0xFF, 0x1C}, // 5
  {0xA1, 0xF1, 0x00, 0xFF, 0x5A}, // 6
  {0xA1, 0xF1, 0x00, 0xFF, 0x42}, // 7
  {0xA1, 0xF1, 0x00, 0xFF, 0x52}, // 8
  {0xA1, 0xF1, 0x00, 0xFF, 0x4A}  // 9
};

SoftwareSerial mySerial(SOFT_RX, SOFT_TX); // RX, TX

void setup() {
  // 初始化硬件串口
  Serial.begin(9600);
  
  // 初始化软串口
  mySerial.begin(9600);
  
  Serial.println("YS-IRTM Controller Ready");
  Serial.println("Send numbers 0-9 to transmit IR codes");
  Serial.println("Send 'L' to enter learning mode");
}

void loop() {
  // 处理硬件串口输入
  if (Serial.available()) {
    char c = Serial.read();
    
    if (c >= '0' && c <= '9') {
      int num = c - '0';
      
      // 通过软串口发送编码字节
      mySerial.write(irCodes[num], 5);
      
      Serial.print("Sent code for number ");
      Serial.print(num);
      Serial.print(": ");
      for (int i = 0; i < 5; i++) {
        if (irCodes[num][i] < 0x10) Serial.print("0");
        Serial.print(irCodes[num][i], HEX);
        Serial.print(" ");
      }
      Serial.println();
    } 
    else if (c == 'L' || c == 'l') {
      // 进入学习模式
      enterLearningMode();
    }
  }
  
  // 检查是否有学习到的编码
  readLearnedCode();
  
  delay(100);
}

零知IDE串口调试助手发送对应的数字后,将NEC格式的编码数据通过软串口发送到红外发射头。发送字符'L'时进入学习模式读取新的NEC编码

2.读取NEC编码

cpp 复制代码
// 进入学习模式
void enterLearningMode() {
  Serial.println("Entering learning mode...");
  Serial.println("Press a button on your remote control");
}

// 读取学习到的编码
void readLearnedCode() {
  if (mySerial.available() >= 3) {
    byte receivedData[3];
    mySerial.readBytes(receivedData, 3);
    
    Serial.print("Learned code: ");
    for (int i = 0; i < 3; i++) {
      if (receivedData[i] < 0x10) Serial.print("0");
      Serial.print(receivedData[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
}

2.2 接收端代码(IR Receiver)

1.初始化定义

cpp 复制代码
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include <IRremote.h>

// 引脚定义
#define TFT_CS    10
#define TFT_DC    9
#define TFT_RST   8
#define TFT_BL    7  // 背光控制引脚
#define LED_PIN   2  // 板载LED引脚
#define IR_RECV_PIN 6  // 红外接收引脚

// 创建ST7789显示对象
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// 红外接收对象
IRreceiver irrecv(IR_RECV_PIN);

IRdecode_results decode_result;

// 红外编码映射
unsigned long irCodes[10] = {
  0xFF6897, 0xFF30CF, 0xFF18E7, 0xFF7A85, 0xFF10EF,
  0xFF38C7, 0xFF5AA5, 0xFF42BD, 0XFF4AB5, 0XFF52AD
};

// 当前显示的数字
int currentNumber = -1;

void setup() {
  // 初始化串口通信
  Serial.begin(115200);
  
  // 初始化LED引脚
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  
  // 初始化ST7789显示屏
  tft.init(240, 240);
  tft.setRotation(1);
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH); // 开启背光
  
  // 显示欢迎界面
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(3);
  tft.setCursor(50, 100);
  tft.print("Ready");
  
  // 初始化红外接收
  irrecv.enableIRIn();
  
  Serial.println("System initialized. Waiting for IR input...");
  Serial.println("Send numbers 0-9 via software serial to transmit IR codes");
}

2.红外接收数据处理

cpp 复制代码
void loop() {
  // 处理红外接收
  if (irrecv.decode(&decode_result)) {
    unsigned long value = decode_result.value;
    Serial.print("Received IR code: 0x");
    Serial.println(value, HEX);
    
    // 检查是否为0-9的数字
    for (int i = 0; i < 10; i++) {
      if (value == irCodes[i]) {
        displayNumber(i);
        
        // 控制LED灯
        if (i == 2) {
          digitalWrite(LED_PIN, HIGH);
          Serial.println("LED turned ON");
        } else if (i == 3) {
          digitalWrite(LED_PIN, LOW);
          Serial.println("LED turned OFF");
        }
        break;
      }
    }
    irrecv.resume(); // 接收下一个值
  }  
  delay(100);
}

// 在屏幕上显示数字
void displayNumber(int number) {
  if (number == currentNumber) return; // 避免重复绘制
  
  currentNumber = number;
  
  tft.fillScreen(ST77XX_BLACK);
  
  // 绘制外圈
  tft.fillRoundRect(5, 5, 235, 235, 30, 0X8410);
  
  // 绘制内圈
  tft.fillRoundRect(15, 15, 215, 215, 30, ST77XX_WHITE);
  
  // 绘制数字
  tft.setTextColor(ST77XX_ORANGE);
  tft.setTextSize(20);
  
  // 根据数字大小调整位置
  int xPos = 75;
  if (number == 1) xPos = 80;
  
  tft.setCursor(xPos, 70);
  tft.print(number);
  
  Serial.print("Displaying number: ");
  Serial.println(number);
}

将发送端的数字实时显示到接收端的显示屏,识别到数'2'和'3'时分别打开和关闭LED灯

2.3 红外编码处理流程

三、系统演示效果

3.1 性能测试

(1)红外信号学习与发送测试

通过YS-IRTM模块成功学习了10个数字按键的红外编码,学习过程稳定可靠。发送端使用串口发送对应的红外信号,测试数据如下:

数字键 原始编码 YS-IRTM编码 发送成功率
0 0xFF6897 A1 F1 00 FF 16 100%
1 0xFF30CF A1 F1 00 FF 0C 100%

(2)控制设备测试

数字键2和3分别控制LED灯的开关,测试结果:

开关响应时间:<100ms <

控制准确率:100% <

3.2 视频演示

YS-IRTM红外编解码器集成灯控与显示系统

串口发送红外编码和遥控发送红外信号效果对比

四、NEC红外协议

4.1 NEC编码方式

NEC协议采用脉冲间隔的方式编码每一位数据,用不同数据位的时间间隔来表示不同的逻辑位。与众多单总线IC的通信方式很相似。NEC编码的载波频率为38KHz,对应的单脉冲周期约等于26.3us。

每一数据位起始于562.5µs的载波,约为21.25个38 kHz脉冲组成。 脉冲的占空比通常为1/4或1/3,以减少电流消耗:

(1)数据表示方式

NEC协议使用脉冲距离编码表示数据:

>逻辑"0":560μs高电平 + 560μs低电平

>逻辑"1":560μs高电平 + 1.68ms低电平

逻辑"0"为562.5µs的有效脉冲 + 562.5µs的空闲间隔,总时长为1.125ms。逻辑"1"为562.5µs的有效脉冲 + 1.6875ms的空闲间隔,总时长为2.25ms(为逻辑0的一倍)。

(2)重复码机制

当按键保持按下时,发送重复码:9ms高电平 + 2.25ms低电平 + 560μs高电平

>即使一直按住遥控器上的一个键,命令帧也只会发送一次。 只要按键保持按下状态,就会每110毫秒发送一次重复码。

4.2 数据帧结构

完整的NEC数据帧由 起始位 + 地址码 + 地址码反码 + 命令码 + 命令码反码 组成。

(1)起始位

每个序列均以9ms的脉冲(称为AGC脉冲)(是逻辑数据位使用的脉冲562.5us的16倍)开始。 接下来是4.5毫秒的空闲:(可以理解这一过程是每一帧的起始标志)

(2)地址码+命令码

起始位之后会传输4个字节共32Bit的数据位,分别是 地址码 + 地址码反码 + 命令码 + 命令码反码。字面上是4个字节,而实际只有2个字节有效,多余的2字节为冗余的反码。一方面可以用于校验是否出错。另一方面,因为总有相同数量的反码的存在,每帧的总消息时长保持恒定。

(3)结束位

结束位为末尾的562.5µs的有效脉冲。

4.3 扩展NEC协议

NEC协议因应用广泛,原有地址很快会被用完。

通过牺牲地址冗余,其地址范围从8位、256个扩展到16位、65536个,且无需改动协议其他属性。

不过这样扩展后,消息总时长不再恒定,取决于消息中1和0的总数;若想保持时长恒定,需让地址字段中逻辑1和逻辑0各为8个,此时地址最大数量会减至约13000个。

此外,协议仍保留命令冗余,每个地址仍可处理256个不同命令。

五、常见问题解答

Q1: 如何提高红外通信的距离和稳定性?

A: 可以通过以下方式提高红外通信性能:

使用更高功率的红外发射管、确保发射器和接收器之间没有障碍物,避免强光直射接收器、调整发射器的发射角度、增加红外发射管的数量(阵列)

Q2: 遇到解码错误或信号干扰怎么办?

A: 解决解码错误和信号干扰的方法:

检查电源稳定性,确保供电充足、增加软件去抖动机制,过滤干扰信号、使用错误检测和重发机制提高可靠性、调整接收器的灵敏度和滤波参数

项目资源:

红外编解码模块:YS-IRTM模块数据手册

NEC红外协议:NEC红外协议详解

相关推荐
会编程的果子君10 小时前
平衡车-ADC采集电池电压
单片机·嵌入式硬件
华清远见IT开放实验室12 小时前
喜讯!华清远见参与制定的《电子产品印制电路板可制造性设计(DFM)和可靠性设计规范》正式发布
stm32·嵌入式·制造·设计规范·电子电路
Shang1809893572612 小时前
T40N君正/INGENIC专业嵌入式CPU计算能力,集成XBurst2双核处理器(1.2GHz)、RISC-V协处理器和神经网络加速器(2TOPS算力)
嵌入式硬件·fpga开发·智能视频应用处理器·t40n
Janspran13 小时前
嵌入式硬件 - 51单片机1
单片机·嵌入式硬件·51单片机
智者知已应修善业13 小时前
【51单片机6位数码管显示矩阵键值至右向左自左向右】2022-11-29
c语言·经验分享·笔记·嵌入式硬件·51单片机
大阳12313 小时前
51单片机(单片机基础,LED,数码管)
开发语言·单片机·嵌入式硬件·算法·51单片机·学习经验
小莞尔13 小时前
【51单片机】【protues仿真】基于51单片机呼叫系统
c语言·stm32·单片机·嵌入式硬件·矩阵·51单片机
DebugKitty13 小时前
硬件开发1-51单片机1
单片机·嵌入式硬件·51单片机·嵌入式·ram·rom·按位运算
GalaxySinCos13 小时前
10 51单片机之DS1302实时时钟
单片机·嵌入式硬件·51单片机