Python 调用串口通信详解(基于 pySerial)
一. 需要的库
在 Python 中,首先需要导入 pySerial 库:
Import serial
二. 搜索串口
使用 pySerial 库进行串口通信时,有时需要先获取系统中所有可用的串口列表,pySerial 提供了 serial.tools.list_ports 模块来实现这个功能。
示例代码:
Import serial.tools.list_ports
ports =list(serial.tools.list_ports.comports()) # 获取可用串口列表
If ports:
print("可用的串口列表:")
for port inports:
print(port.device)
else:
print("未找到可用的串口。")
三. 打开串口
pySerial 配置和打开串口有两种方式
第一种是在调用函数接口打开串口时传入配置参数,第二种方式是先配置参数,然后再打开串口。
方式1:调用函数打开串口时传入配置参数
这种方式是在创建 serial.Serial 对象时,直接将串口的配置参数作为参数传递给该对象,从而在创建对象的同时打开串口。
示例代码:
Import serial
try:
ser =serial.Serial # 在创建 Serial 对象时传入配置参数,同时打开串口
(
port='COM3',# 串口号,Windows 下通常为 COMx,Linux 下为 /dev/ttyUSBx 等
baudrate=9600,# 波特率,常见值有 9600、115200 等
bytesize=serial.EIGHTBITS,# 数据位,通常为 8 位
parity=serial.PARITY_NONE,# 奇偶校验位,无校验
stopbits=serial.STOPBITS_ONE,# 停止位,通常为 1 位
timeout=1# 读取超时时间,单位为秒
)print(f"成功打开串口 {ser.name}")
方式2:先配置参数,然后再打开串口
这种方式是先创建一个 serial.Serial 对象,但不传入任何配置参数。然后修改对象的属性来配置串口参数,最后调用 open() 方法打开串口。
示例代码:
Import serial
try: # 创建 Serial 对象,但不传入配置参数
ser =serial.Serial()# 配置串口参数
ser.port ='COM3'
ser.baudrate =9600
ser.bytesize =serial.EIGHTBITS
ser.parity =serial.PARITY_NONE
ser.stopbits =serial.STOPBITS_ONE
ser.timeout =1# 打开串口
ser.open()
print(f"成功打开串口 {ser.name}")
except serial.SerialException as e:
print(f"操作串口时出现错误: {e}")
两种方式的比较
方式1:代码简洁,适用于串口配置参数固定且不需要动态修改的场景。
方式2:灵活性更高,适用于需要动态修改串口配置参数的场景,例如根据用户输入或其他条件来调整串口参数。
四.查询串口状态
- 检查串口是否打开
可以使用 Serial.is_open 属性来检查串口当前是否处于打开状态。
示例代码:
Import serial
try:
ser =serial.Serial('COM3',9600)# 打开串口
if ser.is_open:
print("串口已打开")
else:print("串口未打开")
ser.close()# 关闭串口
if ser.is_open:
print("串口已打开")
else:
print("串口未打开")
except serial.SerialException as e:
print(f"操作串口时出现错误: {e}")
- 查询串口的配置参数
可以通过 Serial 对象的多个属性来查询当前串口的配置参数,比如波特率、数据位、停止位等
示例代码:
Import serial
try:
ser =serial.Serial('COM3',9600)
print(f"串口号: {ser.port}")
print(f"波特率: {ser.baudrate}")
print(f"数据位: {ser.bytesize}")
print(f"奇偶校验位: {ser.parity}")
print(f"停止位: {ser.stopbits}")
print(f"读取超时时间: {ser.timeout}")
ser.close()
exceptserial.SerialException as e:
print(f"操作串口时出现错误: {e}")
- 查询串口的硬件控制信号状态
pySerial 提供了一些方法来查询串口的硬件控制信号状态,例如 DTR(数据终端就绪)、RTS(请求发送)等。
Import serial
try:
ser =serial.Serial('COM3',9600)
print(f"DTR 状态: {ser.dtr}")
print(f"RTS 状态: {ser.rts}")
print(f"CTS 状态: {ser.cts}")
print(f"DSR 状态: {ser.dsr}")
print(f"RI 状态: {ser.ri}")
print(f"CD 状态: {ser.cd}")
ser.close()
exceptserial.SerialException as e:
print(f"操作串口时出现错误: {e}")
五. 关闭串口
关闭串口很简单,直接调用 close() 方法即可。
ser.close()
六.串口发送数据
可以使用 write() 方法向串口发送数据。
注意事项:
○ write() 方法发送的数据必须是字节类型,通常需要对字符串进行encode编码。
○ write() 方法执行完成后,会将发送的字节数作为返回值。
示例代码:
Import serial
ser =serial.Serial('COM3',9600,timeout=1)
data_to_send = "Hello, Serial!"
write_len = ser.write(data_to_send.encode())
print(f"已发送数据: {data_to_send}")
print("串口发出{}个字节。".format(write_len))
ser.close()
七.串口接收数据
有多种方法可以从串口接收数据:
○ read():读取指定数量的字节。
○ readline():读取一行数据,直到遇到换行符 \n。
○ readlines():读取多行数据,返回一个列表。
1.read()方法默认一次读取一个字节,可以通过传入参数指定每次读取的字节数。
注意事项:
○ 超时设置:读取操作可能会受到 timeout 参数的影响。如果在指定的超时时间内没有读取到足够数量的字节,read() 方法会返回已读取到的字节,而不会一直等待。
○ 数据类型:返回的数据类型是 bytes 类型,需要根据实际情况进行解码。
示例代码:
Import serial
try:
ser =serial.Serial('COM3',9600,timeout=1)# 打开串口
data =ser.read(10)# 读取 10 个字节的数据
If data:
print(f"读取到的数据: {data.decode('utf-8',errors='ignore')}")
else:
print("未读取到数据")
ser.close()# 关闭串口
exceptserial.SerialException as e:
print(f"操作串口时出现错误: {e}")
- readline() 方法用于从串口读取一行数据,直到遇到换行符 \n 为止。如果在超时时间内没有遇到换行符,会返回已读取到的字节。
注意事项:
○ 换行符:该方法依赖于换行符 \n 来确定一行数据的结束。如果发送方没有正确添加换行符,可能会导致读取异常。
○ 超时设置:同样会受到 timeout 参数的影响。
○ 数据类型:返回的数据类型是 bytes 类型,需要进行解码。
示例代码:
Import serial
try:
ser =serial.Serial('COM3',9600,timeout=1)# 打开串口
line =ser.readline()# 读取一行数据
if line:
print(f"读取到的行数据: {line.decode('utf-8',errors='ignore').strip()}")
else:
print("未读取到行数据")
ser.close()# 关闭串口
exceptserial.SerialException a se:
print(f"操作串口时出现错误: {e}")
3.readlines() 方法用于从串口读取多行数据,返回一个包含每行数据的列表。每行数据以 \n 结尾
注意事项:
○ 换行符:与 readline() 方法一样,依赖于换行符 \n 来分割每行数据。
○ 超时设置:会受到 timeout 参数的影响。在超时时间内,会持续读取数据,直到超时后返回已读取到的所有行。
○ 数据类型:返回的列表中的每个元素都是 bytes 类型,需要进行解码。
示例代码:
Import serial
try:
ser =serial.Serial('COM3',9600,timeout=2)# 打开串口
lines =ser.readlines() # 读取多行数据
If lines:
print("读取到的多行数据:")
For line inlines:
print(line.decode('utf-8',errors='ignore').strip())
else:
print("未读取到多行数据")
ser.close() # 关闭串口
exceptserial.SerialException as e:
print(f"操作串口时出现错误: {e}")
• read() 适用于读取固定数量的字节数据。
• readline() 适用于按行读取数据,需要发送方正确添加换行符。
• readlines() 适用于一次性读取多行数据,同样依赖于换行符。

浙公网安备 33010602011771号