这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 【M5stackS3】调试串口的数据回传功能

共1条 1/1 1 跳转至

【M5stackS3】调试串口的数据回传功能

高工
2026-07-20 19:40:11     打赏

一:使用串口中断功能回传数据

实现ESP32的串口数据“回传”,最直接的理解就是 “回声” (Echo) 功能:将ESP32从串口收到的任何数据,原样发回去。这在调试设备或验证通信链路时非常常用。

实现这个功能的核心逻辑非常简单,在Arduino框架下的标准写法如下:

void setup() {
  // 初始化串口通信,波特率设为115200
  Serial.begin(115200); 
}

void loop() {
  // 检查串口缓冲区是否有数据可读
  if (Serial.available() > 0) {
    // 读取一个字节的数据
    char incomingChar = Serial.read();
    
    // 将收到的这个字节原样发送回去,实现“回传”
    Serial.print(incomingChar);
  }
}

这段代码的逻辑是:当ESP32从USB串口(连接到电脑的Serial Monitor)收到数据时,就会立即把同样的数据发送回去。你可以打开Arduino IDE的串口监视器,发送任意字符,都会看到它被立即返回。

监听:通过available();检查是否有数据。

读取:使用Serial.read()等方法获取数据。

回写:通过Serial.print();方法将数据发送回去

二:串口空闲中断回传数据

ESP32在Arduino环境下,虽然没有和STM32完全一样的“空闲中断”硬件机制,但通过较新版本的HardwareSerial库,可以使用 onReceive() 回调函数达到非常相似的效果。

这个功能允许你设置一个回调函数,当串口在指定时间内没有收到新数据时被触发,这正是处理不定长数据帧的理想时机

#include <HardwareSerial.h>

// 自定义 Serial1 的 RX 和 TX 引脚
// 推荐使用开发板上不冲突的引脚,例如:
#define SERIAL1_RX 18   // 接收引脚
#define SERIAL1_TX 19   // 发送引脚

// 数据接收缓冲区
uint8_t rxBuffer[512];
uint8_t rxLength = 0;

void setup() {
  // 初始化 USB 串口用于调试输出
  Serial.begin(115200);
  
  // 初始化 Serial1,配置波特率、数据位、停止位、奇偶校验
  // 格式:begin(波特率, 配置模式, RX引脚, TX引脚)
  // SERIAL_8N1 表示 8数据位、无校验、1停止位(最常用)
  Serial1.begin(115200, SERIAL_8N1, SERIAL1_RX, SERIAL1_TX);
  
  // 设置空闲超时时间为 10ms
  // 即:当 Serial1 在 10ms 内没有收到新数据时,触发回调
  Serial1.setRxTimeout(10);
  
  // 注册回调函数,第二个参数 'true' 表示仅在超时时触发
  // 这等同于"空闲中断"的效果
  Serial1.onReceive(onSerial1Receive, true);
  
  Serial.println("=== Serial1 空闲中断式回传已启动 ===");
  Serial.printf("RX 引脚: %d, TX 引脚: %d\n", SERIAL1_RX, SERIAL1_TX);
}

void loop() {
  // 主循环中可以执行其他任务
  // 例如:每秒打印一次心跳信息
  static unsigned long lastPrint = 0;
  if (millis() - lastPrint > 5000) {
    lastPrint = millis();
    Serial.println("系统运行中...");
  }
}

// ========================================
// Serial1 空闲中断回调函数
// 这个函数在每帧数据接收完毕后被自动调用
// 注意:此函数运行在中断上下文中,应尽量简短
// ========================================
void onSerial1Receive() {
  // 获取当前可读的字节数(即这一帧的数据长度)
  rxLength = Serial1.available();
  
  if (rxLength > 0) {
    // 从串口读取全部数据到缓冲区
    Serial1.readBytes(rxBuffer, rxLength);
    
    // ===== 数据处理 =====
    // 1. 将收到的数据通过 USB 串口打印出来(用于调试)
    Serial.print("[收到数据帧] 长度: ");
    Serial.print(rxLength);
    Serial.print(" 字节, 内容: ");
    Serial.write(rxBuffer, rxLength);  // 使用 write 以支持二进制数据
    Serial.println();  // 换行
    
    Serial1.write(rxBuffer, rxLength);
    

    // }
  }
}

注意事项;

回调函数的执行环境:onSerial1Receive在中断上下文中执行,因此:

    避免使用delay

    尽量保持代码简短快速

    不要在回调中做复杂计算或阻塞操作

超时时间的选取:

    如果超时时间太短(如1ms),在数据流传输时可能因短暂间隙而误触发

    如果超时时间太长(如100ms),则帧处理的实时性会下降

对于115200波特率,10ms是比较通用的值

    缓冲区大小:uint8_t rxBuffer[512];可以根据需要调整,确保能容纳最大的一帧数据。

    如果不需要回传:只需要将Serial1.write(rxBuffer, rxLength);这一行注释掉或删除即可。




关键词: M5stack     串口     回传    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]