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

PySerial读取串口数据前出现空字节的原因及相关逻辑疑问

串口通信问题解答

问题描述

Arduino发送代码

void setup() {
  Serial.begin(9600);
}

void loop() {
  for(int i = 0; i < 10; i++){
    Serial.print(i);
    delay(200);
  }
}

Python接收代码

import serial

usbport = 'COM3'
ser     = serial.Serial(usbport, 9600, timeout=1)

count = 0
while ser.in_waiting < 1 and count < 5:
    
    p = ser.read(10)
    p = p.decode()
    print(p, type(p))
    count += 1
    
ser.close()

现象与疑问

每次启动串口通信时Arduino会复位(此情况可接受),但Python代码总会在读取有效串口数据前读到空字节,示例输出如下:

<class 'str'>
0123456789 <class 'str'>
0123456789 <class 'str'>
0123456789 <class 'str'>
0123456789 <class 'str'>

疑问:

  1. 为何会读到空字节?
  2. 为何必须使用while ser.in_waiting < 1 and count < 5才能正常工作,而非while ser.in_waiting?

问题解答

1. 读取到空字节的原因

这是因为Arduino串口连接后复位的过程中,串口还未准备好发送数据。Python代码打开串口后立刻尝试读取,此时Arduino正处于复位初始化阶段,还没有进入loop循环发送0-9字符,加上代码设置了timeout=1,当1秒内没有读到数据时,ser.read(10)就会返回空字节,解码后就是空字符串。

等Arduino完成复位流程,进入loop循环后,就会开始持续发送数据,后续的读取操作就能拿到完整的0123456789序列。

2. while条件的差异原因

先明确两个条件的逻辑差异:

  • while ser.in_waiting < 1 and count < 5:当串口接收缓冲区中没有待读取的数据,且循环次数未到5次时,执行读取操作。它的作用是主动轮询缓冲区,即使没数据也会触发读取(因为有timeout设置),等Arduino复位完成开始发数据后,后续读取就能命中有效内容。
  • 如果换成while ser.in_waiting:这个条件是只有当缓冲区有数据时才执行循环体,而你的读取操作写在循环体内,这会导致缓冲区没数据时直接跳出循环,根本不会执行读取动作,自然拿不到任何数据。

其实这个写法逻辑比较绕,更合理的方式是先等待Arduino复位完成(比如加一段延时),再开始读取,或者循环读取直到拿到有效数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:12:05