使用PySerial.write()发送数据时丢失字节的问题求助
问题描述
使用Python的PySerial库向STM单片机发送命令时,频繁出现字节丢失/错乱的情况,约半数回显异常,但用Putty发送相同命令完全正常。已排查硬件故障,更换操作系统、编译为可执行文件均无效。
示例代码
import serial stm_serial_port = '/dev/ttyUSB0' stm_baud_rate = 460800 ser_stm = serial.Serial(stm_serial_port, stm_baud_rate, timeout=1) cmd = "initc 1 0.6 50 1000 1000 1000 1000 100 100" encoded_cmd = str.encode(cmd+"\r\n") def flush_buffers(): # 原代码未定义此函数,需补充缓冲区清空逻辑 ser_stm.reset_input_buffer() ser_stm.reset_output_buffer() for i in range(100): flush_buffers() print('Cmd : '+cmd) ser_stm.write(encoded_cmd) feedback = ser_stm.readline().decode('utf-8') print('Echo : '+feedback) while(True): data = ser_stm.readline().decode('utf-8') if 'sh>' in data: break
异常回显示例
Cmd : initc 1 0.6 50 1000 1000 1000 1000 100
Echo : intc 0.6 50 1000 1000 1000 1000 100
Cmd : initc 1 0.6 50 1000 1000 1000 1000 100
Echo : initc 1 0.650 1000 1000 1000 1000 100
Cmd : initc 1 0.6 50 1000 1000 1000 1000 100
Echo : initc 1 0.6 50 1000 1000 00 1000 100
Cmd : initc 1 0.6 50 1000 1000 1000 1000 100
Echo : initc 1 0.6 50 10001000 1000 1000 100
问题原因及解决方法
1. 缓冲区刷新逻辑缺失
原代码中flush_buffers()未实现实际的缓冲区清空操作,残留的历史数据会干扰当前通信。必须显式清空串口的输入输出缓冲区:
def flush_buffers(): ser_stm.reset_input_buffer() # 清空接收缓冲区 ser_stm.reset_output_buffer() # 清空发送缓冲区
2. 高波特率下发送时序不匹配
460800属于高波特率,PySerial默认发送后不会等待数据完全发送完毕就开始读取,导致单片机端接收不完整。需在write后等待发送缓冲区为空:
ser_stm.write(encoded_cmd) ser_stm.flush() # 阻塞直到所有数据发送完成
3. 串口流控参数不匹配
Putty可能默认启用了硬件流控(RTS/CTS),而PySerial默认关闭。需显式配置流控参数:
ser_stm = serial.Serial( port=stm_serial_port, baudrate=stm_baud_rate, timeout=1, rtscts=True # 启用硬件流控,匹配Putty设置 )
若单片机未配置硬件流控,可尝试启用软件流控:
ser_stm = serial.Serial( port=stm_serial_port, baudrate=stm_baud_rate, timeout=1, xonxoff=True )
4. 读取时序过快
发送命令后立即调用readline(),可能单片机还未完成回显发送。可增加短暂延迟或循环读取确保获取完整数据:
import time ser_stm.write(encoded_cmd) ser_stm.flush() time.sleep(0.01) # 根据实际通信延迟调整,如10ms feedback = ser_stm.readline().decode('utf-8').strip()
5. 换行符格式不匹配
部分设备仅识别\n而非\r\n,可尝试修改发送的换行符:
encoded_cmd = str.encode(cmd+"\n")
内容的提问来源于stack exchange,提问作者namettra

