树莓派Python环境下如何确认串口写入完成以解决丢包问题
树莓派Python环境下如何确认串口写入完成以解决丢包问题
嗨,我完全懂你的困扰——直接写串口会丢字符,加延迟能凑合用但总觉得不优雅,想要精准判断串口写入完成对吧?这其实是因为pyserial的write()方法默认只是把数据放到输出缓冲区就返回了,并不会等待硬件真正把数据发送完毕,所以如果后续操作衔接太急,就容易出现数据丢包的情况。
给你两个靠谱的解决办法,不用依赖固定延迟:
方法一:用flush()阻塞等待写入完成
pyserial提供了ser.flush()方法,它会一直阻塞到输出缓冲区里的所有数据都被串口硬件发送完毕,相当于帮你自动“等”到写入真的完成。你只需要在每次ser.write(data)之后加上这一行就行:
ser.write(data) ser.flush() # 等待串口把数据发完再继续
方法二:轮询out_waiting状态(非阻塞可选)
如果你不想用阻塞方式,可以循环检查ser.out_waiting属性——这个属性代表当前输出缓冲区中还未发送的字节数,直到它变成0,就说明所有数据都发送完成了:
ser.write(data) while ser.out_waiting > 0: pass # 循环等待缓冲区清空
另外还要提醒你,你的代码里有缩进错误,except和finally块下面的代码没有正确缩进,这会导致语法错误,得修正才能正常运行。下面是修正缩进并加入flush()后的完整代码:
import socket import serial from threading import Thread from datetime import datetime def on_new_client(client_socket, addr): try: while True: client_socket.settimeout(60) data = client_socket.recv(1) ser.write(data) ser.flush() # 新增:等待串口写入完成 client_socket.settimeout(None) if not data: print(f'Client {addr} disconnected') break Ctime = datetime.now().strftime("%H:%M:%S") print(f"Address: {addr},Time:{Ctime}, Data: {data}") except socket.timeout: print(f"Connection timed out for {addr}") except Exception as e: print(f"Error with client {addr}: {e}") finally: client_socket.close() print(f"Connection closed for {addr}") def main(): global ser ser = serial.Serial( port='/dev/ttyS0', baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS ) host1 = '192.168.176.248' port1 = 4002 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((host1, port1)) s.listen(5) print(f"Server started on {host1}:{port1}") while True: client_socket,addr = s.accept() print(f"New connection from: {addr}") thread = Thread(target=on_new_client, args=(client_socket, addr), daemon=True) # Mark thread as daemon thread.start() # Start the thread if __name__ == '__main__': main()
这样修改后,你就不用再加额外的延迟,串口写入完成后才会继续执行后续代码,应该就能解决丢字符的问题了。
备注:内容来源于stack exchange,提问作者Sathish
相关产品推荐
相关产品推荐

