Arduino软件串口输出异常:使用newSerial仅输出首条NMEA语句的问题
故障核心原因
- Software Serial半双工属性限制:你当前的代码把同一个
newSerial同时用作输入接收、输出发送端口,Software Serial本身不支持全双工同时收发,发送操作会直接打断正在进行的串口接收流程,导致第一条NMEA发完后,后续正在传输的GSA、RMC语句的字节流被截断,再也没法被完整解析。这也是你之前用硬件串口Serial.println输出时功能正常的核心原因——硬件串口支持全双工收发并行,不会出现发送打断接收的问题。 - 解码触发时机问题:通用NMEA解析库的
decode()方法,仅在完整收到一条以换行符结尾的合法NMEA语句时返回true。你在刚触发第一条GGA语句的解码成功时,就立刻进入发送流程,此时后续GSA、RMC的字节还未进入串口缓冲区,发送操作直接清空了缓冲区的待接收数据。 - 单字节读取逻辑缺陷:当前
loop每次仅读取1个串口字节,在波特率适配间隙很容易漏帧,进一步加剧了后两条语句的丢失。 - 部分开发板的Software Serial默认接收缓冲区仅能存储1条NMEA语句的长度,连续传输3条语句时会直接溢出丢弃后续数据。
可落地的修复方案
- 拆分收发端口:不要将同一个Software Serial同时作为输入接收、输出发送通道。硬件资源允许的情况下,把GPS输入接在硬件串口上,将Software Serial专用为输出端;如果需要用Software Serial接外部GPS输入,就把输出换到硬件USB串口,从根源上避免收发冲突。
- 调整处理顺序:先把当前串口缓冲区里的所有待接收字节全部喂给NMEA解析库,等当前批次的所有NMEA语句都完整解码完成后,再统一执行发送操作,杜绝边收边发打断接收的问题。
- 硬件资源不足需同口收发的适配方案:如果必须用同一个Software Serial完成双向收发,每执行完一次
println输出后,按波特率添加对应延时(9600波特率下建议加100ms延时),等待串口状态复位后再恢复接收逻辑。 - 适当调大Software Serial的接收缓冲区大小,保证能存下连续传输的3条NMEA语句的全部字节。
- 修正后的参考代码结构:
// 独立拆分接收、输出串口 SoftwareSerial outputSerial(2, 3); NmeaParser gps; void setup() { Serial.begin(9600); // 硬件串口专门接收GPS输入 outputSerial.begin(9600); } void loop() { // 循环读完当前所有待接收字节,不提前触发发送 while (Serial.available() > 0) { gps.decode(Serial.read()); } // 等语句完整解码后再执行发送 if (gps.hasValidSentence()) { outputSerial.println(gps.sentence()); gps.resetBuffer(); // 清空解析缓存,准备接收下一批数据 } }
内容的提问来源于stack exchange,提问作者Erwin
相关产品推荐
相关产品推荐

