serial
模块(也称为pyserial
)是Python中用于串口通信的标准库,支持Windows、Linux和macOS等多个平台。
安装pyserial
pip install pyserial
基本使用方法
1. 打开串口连接
import serial # 打开串口 ser = serial.Serial( port='COM3', # Windows下的串口号 # port='/dev/ttyUSB0', # Linux下的设备名 baudrate=9600, # 波特率 bytesize=8, # 数据位 parity='N', # 校验位(N无校验/E偶校验/O奇校验) stopbits=1, # 停止位 timeout=1 # 读取超时时间(秒) ) print(f"串口状态: {'打开' if ser.is_open else '关闭'}") print(f"串口设置: {ser}")
2. 发送数据
data_to_send = "Hello, Serial!\r\n" # 通常需要加回车换行 ser.write(data_to_send.encode('utf-8')) # 需要编码为字节
3. 接收数据
# 读取一行(直到遇到换行符) received = ser.readline().decode('utf-8').strip() print(f"收到数据: {received}") # 或者读取指定字节数 data = ser.read(10) # 读取10个字节 print(f"收到数据: {data}") # 检查接收缓冲区中有多少字节等待读取 bytes_waiting = ser.in_waiting print(f"等待读取的字节数: {bytes_waiting}")
4. 关闭串口
ser.close() print(f"串口状态: {'打开' if ser.is_open else '关闭'}")
实用技巧
1. 自动检测可用串口
import serial.tools.list_ports ports = serial.tools.list_ports.comports() for port in ports: print(f"找到串口: {port.device} - {port.description}")
2. 使用with语句自动管理资源
with serial.Serial('COM3', 9600, timeout=1) as ser: ser.write(b'AT\r\n') response = ser.readline() print(response.decode('utf-8'))
3. 二进制数据收发
# 发送二进制数据 ser.write(bytes([0x41, 0x42, 0x43])) # 发送ABC的ASCII码 # 接收二进制数据 binary_data = ser.read(5) # 读取5个字节 print(f"收到二进制数据: {binary_data}")
4. 设置RTS/CTS硬件流控
ser = serial.Serial('COM3', 115200, rtscts=True)
常见问题解决
-
权限问题(Linux/Mac):
sudo chmod 666 /dev/ttyUSB0
或将自己加入dialout组:
sudo usermod -a -G dialout $USER
-
串口被占用:
-
确保没有其他程序正在使用该串口
-
关闭所有串口终端软件
-
-
数据接收不完整:
-
检查波特率、数据位、停止位和校验位设置
-
增加读取超时时间
-
-
中文乱码:
-
确保发送和接收使用相同的编码(通常utf-8或gbk)
-
完整示例
import serial import threading def read_from_port(ser): while True: if ser.in_waiting > 0: data = ser.readline().decode('utf-8').strip() print(f"收到: {data}") def main(): port = input("请输入串口号(如COM3或/dev/ttyUSB0): ") baudrate = int(input("请输入波特率(如9600): ")) try: ser = serial.Serial(port, baudrate, timeout=1) print(f"已连接 {port} @ {baudrate} bps") # 启动读取线程 thread = threading.Thread(target=read_from_port, args=(ser,)) thread.daemon = True thread.start() # 主线程处理发送 while True: message = input("发送(输入quit退出): ") if message.lower() == 'quit': break ser.write((message + '\r\n').encode('utf-8')) except serial.SerialException as e: print(f"串口错误: {e}") finally: if 'ser' in locals() and ser.is_open: ser.close() print("串口已关闭") if __name__ == "__main__": main()