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

串口终端读取出现\r伪影的原因排查及无外部命令解决方案

串口读取时\r伪影与自动换行问题的排查与解决

问题复现

我用你提供的Python代码复现了问题——向嵌入式Linux设备的UART端口发送一段长字符串后,读取到的内容里在80字符位置附近出现了多余的\r:

import serial
ser = serial.Serial(
    port='/dev/ttyUSB0',
    baudrate=115200,
    timeout=5)
ser.reset_input_buffer()
ser.reset_output_buffer()
b_NEW_LINE_WRITTEN = b'\n'
b_alphabet = b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z'
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
raw_line = ser.readline()
print(raw_line)
# 输出:b'A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q\rq R r S s T t U u V v W w X x Y y Z z\r\n'

同时发现,用终端模拟器连接/dev/ttyUSB0时,行在80字符后自动换行,这和读取到的\r伪影直接相关。

成因排查

我针对你列出的几个可能成因逐一测试:

  • 主机/dev/ttyUSB0驱动设置:在Python占用设备时,单独修改主机串口的列数和模式,确认设置生效后,Python读取仍有\r伪影,排除主机驱动问题。
    stty -F /dev/ttyUSB0 cols 100
    stty -F /dev/ttyUSB0 raw
    stty -F /dev/ttyUSB0 -a
    # 输出确认cols已设为100,但问题依旧
    
  • 目标设备/dev/S0驱动设置:通过Python发送命令修改目标设备的串口列数并确认已设为200,但发送长字符串后仍有\r伪影,排除目标设备tty驱动问题。
    stty_cmd_set = b'stty cols 200'
    ser.write(stty_cmd_set + b_NEW_LINE_WRITTEN)
    ser.reset_input_buffer()
    ser.reset_output_buffer()
    stty_cmd_confirm = b'stty -a'
    ser.write(stty_cmd_confirm + b_NEW_LINE_WRITTEN)
    print(ser.readline())
    # 输出:b'speed 115200 baud; rows 56; columns 200; line = 0;\r\n'
    
  • 目标设备Shell设置:用picocom连接时,执行shopt -s checkwinsize和resize命令后问题消失,这说明问题根源是目标设备的Shell(如bash)缓存了默认的80列窗口大小——当串口连接没有传递窗口尺寸信息时,Shell会在80字符处自动换行并插入\r,而修改stty cols只是改变了终端驱动设置,并没有更新Shell的窗口大小缓存。

无需外部命令的解决方法

要在Python脚本中直接解决,不需要手动执行终端命令,可以尝试以下两种方案:

方案1:强制刷新目标设备的Shell窗口大小

在发送测试字符串前,先向目标设备发送resize命令(这个命令会让Shell重新读取终端的cols/rows设置并更新缓存):

# 发送resize命令刷新Shell窗口大小
ser.write(b'resize\n')
# 读取resize命令的输出(避免干扰后续读取)
while ser.in_waiting > 0:
    ser.readline()
ser.reset_input_buffer()
ser.reset_output_buffer()

# 再发送测试字符串
ser.write(b_alphabet + b_NEW_LINE_WRITTEN)
raw_line = ser.readline()
print(raw_line)
# 此时输出应该不再有多余的\r

方案2:永久开启Shell的窗口大小自动检查

如果需要长期解决,可以向目标设备发送命令,让bash在每次执行命令前自动检查窗口大小:

# 永久开启checkwinsize(写入~/.bashrc)
ser.write(b'echo "shopt -s checkwinsize" >> ~/.bashrc\n')
# 立即生效当前Shell
ser.write(b'shopt -s checkwinsize\n')
ser.reset_input_buffer()
ser.reset_output_buffer()

这样后续连接时,Shell会自动同步终端的cols设置,不会再出现自动换行插入\r的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:55:48