You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何清除Arduino软件串口输出窗口乱码?附收发代码求助

解决SoftwareSerial通信乱码与ACK逻辑问题

让我来帮你排查并修复代码里的问题,乱码和异常输出主要来自波特率选择、数据收发逻辑的漏洞,还有字符串处理的不规范,下面是具体的分析和修正后的代码:

核心问题分析

  1. 非标准波特率:你用了1000这个非标准波特率,SoftwareSerial对这类波特率的时序支持很差,很容易出现数据丢包或者乱码,换成9600这种标准波特率就能解决大部分底层通信问题。
  2. 字符串终止符处理:C语言的字符串需要以\0结尾才能正常打印,你的接收缓冲区没有预留终止符位置,打印时会读取内存里的随机内容,造成乱码。
  3. 接收逻辑漏洞:原接收端直接连续调用read(),但串口数据可能分批到达,当缓冲区数据不足时,会读入无效值(比如-1),导致乱码;发送端判断available() ==3太严格,容易错过分批到达的数据。
  4. ACK触发逻辑错误:接收端用sizeof(mystr) ==3作为触发ACK的条件,而sizeof是编译时确定的固定值(永远等于3),导致只要进入loop就会不断发送ACK,造成发送端收到重复数据。

修正后的发送端代码

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX

const char* sendMsg = "CAT"; // 待发送的字符串,自带终止符
char ackBuf[4]; // 存储ACK的缓冲区(3个字符+1个终止符)
const int ACK_LEN = 3;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600); // 改用标准波特率9600
}

void loop() {
  // 发送3个字符(不包含终止符)
  mySerial.write(sendMsg, ACK_LEN);
  Serial.println("已发送: CAT");
  delay(1000);

  // 接收ACK:累计接收够3个字符再处理
  if (mySerial.available() >= ACK_LEN) {
    for (int i = 0; i < ACK_LEN; i++) {
      ackBuf[i] = mySerial.read();
    }
    ackBuf[ACK_LEN] = '\0'; // 手动添加字符串终止符
    Serial.print("收到ACK: ");
    Serial.println(ackBuf);
  }
}

修正后的接收端代码

#include <SoftwareSerial.h>
SoftwareSerial mySerial_1(2, 3); // RX, TX

char recvBuf[4]; // 接收缓冲区(3个字符+1个终止符)
const int PACKET_LEN = 3;
int recvCount = 0; // 记录已接收的字符数
const char* ackMsg = "YES"; // ACK字符串

void setup() {
  Serial.begin(9600);
  mySerial_1.begin(9600); // 和发送端保持相同的标准波特率
}

void loop() {
  // 逐个读取串口数据,累计够3个再处理
  while (mySerial_1.available() > 0 && recvCount < PACKET_LEN) {
    char c = mySerial_1.read();
    // 这里可以加字符校验,比如只接收预期的C/A/T,也可以直接存储所有有效字符
    if (c >= 'A' && c <= 'Z') { // 过滤无效字符,可选
      recvBuf[recvCount++] = c;
    }
  }

  // 当接收够3个字符时,处理数据并发送ACK
  if (recvCount == PACKET_LEN) {
    recvBuf[PACKET_LEN] = '\0'; // 添加终止符,确保正常打印
    Serial.print("收到数据: ");
    Serial.println(recvBuf);
    
    // 发送ACK(3个字符,不带终止符)
    mySerial_1.write(ackMsg, PACKET_LEN);
    Serial.println("已发送ACK: YES");
    
    recvCount = 0; // 重置计数器,准备接收下一包数据
  }
}

关键改动说明

  • 波特率统一为9600:标准波特率能保证SoftwareSerial的通信稳定性,避免底层时序错误导致的乱码。
  • 缓冲区预留终止符位置:所有存储字符串的数组都多开一个字节,手动添加\0,确保打印时不会出现乱码。
  • 累计接收逻辑:不再假设数据一次性到达,用计数器记录接收的字符数,够数后再处理,避免读入无效数据。
  • 修复ACK触发条件:用实际接收的字符数recvCount == PACKET_LEN代替sizeof,只有真正收到完整数据包才发送ACK,避免重复发送。
  • 可选的字符过滤:接收端添加了字母过滤,能进一步减少无效乱码的影响,如果你不需要可以删掉这个判断。

内容的提问来源于stack exchange,提问作者Abd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:07:43