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

树莓派Python:如何通过USB串口无丢失传输大数据?

解决USB OTG Serial Gadget大文件传输丢包问题

这种串口传输丢包的情况我之前在树莓派USB OTG场景下碰到过好几次,尤其是传输大体积数据时,核心问题基本都是缓冲区溢出或者缺少流控制机制导致的。结合你的代码,给你几个针对性的解决方案,亲测有效:

1. 启用硬件流控制(RTS/CTS)

这是解决丢包最关键的一步。默认情况下,串口传输没有流控制,当接收端的缓冲区被填满时,后续的数据会直接丢失。而USB Serial Gadget支持RTS/CTS硬件流控制——当接收端缓冲区快满时,会通过RTS信号通知发送端暂停发送,等缓冲区有空间了再继续。

修改树莓派端代码:

import serial

# 初始化串口时添加rtscts=True参数
ser = serial.Serial(
    port='/dev/ttyGS0',
    baudrate=115200,
    rtscts=True,  # 启用硬件流控制
    timeout=1
)

# 更高效地创建1MB数据包
packet = bytearray([0x2f]) * 1000000
ser.write(packet)
ser.close()

修改电脑端代码:

import serial

ser = serial.Serial(
    port='COM30',
    baudrate=115200,
    rtscts=True,  # 必须和发送端同时启用
    timeout=5  # 设置超时,避免无限等待
)

expected = 1000000
received = 0

# 循环读取直到收完预期字节数
while received < expected:
    remaining = expected - received
    data = ser.read(remaining)
    received += len(data)
    print(f"已接收:{received}/{expected} 字节")

print(f"传输完成!总接收字节数:{received}")
ser.close()

2. 增大串口缓冲区大小

默认的串口接收/发送缓冲区通常只有几KB,传输1MB数据时很容易被填满溢出。我们可以通过代码手动增大缓冲区,减少溢出概率:

树莓派端添加缓冲区设置:

# 在串口初始化后添加
ser.set_buffer_size(tx_size=1048576)  # 设置发送缓冲区为1MB

电脑端添加缓冲区设置:

# 在串口初始化后添加
ser.set_buffer_size(rx_size=1048576)  # 设置接收缓冲区为1MB

3. 可选:分块发送+握手确认

如果对数据完整性要求极高,可以加入简单的握手机制——发送端分块发送数据,每发送一块就等待接收端的确认信号,确认收到后再发送下一块。这种方式能彻底避免丢包,但会稍微降低传输速度:

树莓派端分块发送代码:

import serial

ser = serial.Serial(
    port='/dev/ttyGS0',
    baudrate=115200,
    rtscts=True,
    timeout=2
)
ser.set_buffer_size(tx_size=65536)

total_bytes = 1000000
block_size = 65536  # 每次发64KB
packet = bytearray([0x2f]) * total_bytes

for i in range(0, total_bytes, block_size):
    end = min(i + block_size, total_bytes)
    ser.write(packet[i:end])
    # 等待接收端的确认信号(比如一个字节'A')
    ack = ser.read(1)
    while ack != b'A':
        ack = ser.read(1)

ser.close()

电脑端对应确认代码:

import serial

ser = serial.Serial(
    port='COM30',
    baudrate=115200,
    rtscts=True,
    timeout=5
)
ser.set_buffer_size(rx_size=65536)

expected = 1000000
received = 0

while received < expected:
    remaining = expected - received
    data = ser.read(min(remaining, 65536))
    received += len(data)
    print(f"已接收:{received}/{expected} 字节")
    # 发送确认信号
    ser.write(b'A')

print(f"传输完成!总接收字节数:{received}")
ser.close()

额外检查点

确保树莓派的USB OTG配置是正确的:

  • /boot/config.txt中已经添加了dtoverlay=dwc2
  • /etc/modules中添加了g_serial
  • 重启树莓派后,/dev/ttyGS0设备正常存在

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:37:51