什么是串口通信?
串口通信是一种设备间按位(bit)进行数据传输的通信方式,它只需要两根线(TX 发送,RX 接收)就可以实现全双工通信,简单可靠,在嵌入式系统和硬件调试中非常流行。

准备工作:安装必要的库
Python 本身没有内置串口通信的模块,我们需要借助第三方库,最常用、最稳定的是 pyserial。
安装 pyserial:
打开你的终端或命令提示符,运行以下命令:
pip install pyserial
串口显示的核心步骤
使用 Python 进行串口通信并显示数据,通常遵循以下步骤:
- 导入
serial库:import serial - 打开串口:
serial.Serial(),指定串口号、波特率等参数。 - 读取数据:
ser.read()或ser.readline()。 - 处理和显示数据:将读取到的字节流解码成字符串,并打印到控制台。
- 关闭串口:
ser.close(),这是一个好习惯,确保资源被释放。
代码示例
示例 1:最简单的“一问一答”模式
这个例子适用于你向设备发送一个命令,然后设备返回一行数据的场景。

import serial
import time
# --- 1. 配置串口 ---
# 'COM3' 是 Windows 下的串口号
# '/dev/ttyUSB0' 或 '/dev/ttyACM0' 是 Linux 下的串口号
# '/dev/cu.usbserial-XXXX' 是 macOS 下的串口号
# 你需要在设备管理器或 `ls /dev/tty.*` (macOS/Linux) 中找到正确的串口号
ser = serial.Serial(
port='COM3', # 串口号
baudrate=9600, # 波特率,必须和设备端设置的一致
parity=serial.PARITY_NONE, # 校验位
stopbits=serial.STOPBITS_ONE, # 停止位
bytesize=serial.EIGHTBITS, # 数据位
timeout=1 # 超时时间(秒),1秒内没有读到数据就返回
)
print(f"串口 {ser.name} 已打开")
# --- 2. 发送命令并读取响应 ---
# 假设我们向设备发送 "GET_DATA\n" 来请求一行数据
command = "GET_DATA\n".encode('utf-8') # Python 3中,串口发送和接收的都是字节,所以需要编码
ser.write(command)
# 等待一小段时间,让设备有时间处理并发送数据
time.sleep(0.5)
# 读取一行数据,直到遇到换行符或超时
if ser.in_waiting > 0: # 检查是否有数据可读
response_line = ser.readline()
# 将字节流解码为字符串,并去除两端的空白字符(如换行符)
print("接收到数据:", response_line.decode('utf-8').strip())
else:
print("没有收到数据。")
# --- 3. 关闭串口 ---
ser.close()
print("串口已关闭。")
示例 2:持续监听并显示实时数据(最常见)
这个例子适用于设备持续不断发送数据(每秒发送一次传感器读数),我们需要实时显示在屏幕上。
关键点:使用一个 while 循环来持续读取。一定要在循环外正确关闭串口,所以通常会使用 try...finally 结构。
import serial
import time
ser = serial.Serial('COM3', 9600, timeout=1)
print(f"串口 {ser.name} 已打开,开始监听...")
try:
while True:
# 检查是否有数据到达
if ser.in_waiting > 0:
# 读取一行数据
line = ser.readline()
# 确保读取到的不是空数据
if line:
# 解码并打印
print(line.decode('utf-8').strip())
# 为了不让CPU占用率过高,可以加一个微小的延时
# time.sleep(0.01)
except KeyboardInterrupt:
# 当用户按下 Ctrl+C 时,捕获异常并退出
print("\监听被用户中断。")
finally:
# 确保无论如何都会执行关闭操作
ser.close()
print("串口已关闭。")
常见问题与解决方案
Q1: 如何找到正确的串口号?
- Windows: 打开“设备管理器”,展开“端口 (COM 和 LPT)”,查看你的设备对应的 COM 端口。
- Linux (Ubuntu, etc.): 打开终端,运行
ls /dev/tty*,USB转串口设备会是/dev/ttyUSB0,/dev/ttyUSB1等,而板载串口是/dev/ttyS0,树莓派的串口可能是/dev/ttyAMA0。 - macOS: 打开终端,运行
ls /dev/tty.*,通常会是/dev/cu.usbserial-XXXX这样的名字。
Q2: serial.SerialException: could not open port 'COM3': [Errno 2] No such file or directory
- 原因: 串口号错误,你的电脑上没有
COM3这个端口。 - 解决: 按照上面的方法,找到你设备正确的串口号并修改代码。
Q3: 读取到的数据是乱码,或者没有数据。
- 原因:
- 波特率不匹配:这是最常见的原因,请确保 Python 脚本中的
baudrate和你设备(如 Arduino)代码中的Serial.begin(9600)设置的波特率完全一致。 - 数据格式问题:
- 换行符: 设备是否发送了换行符(
\n)?ser.readline()默认以换行符为结束标志,如果设备发送的是data1,data2,data3而没有换行符,readline()会一直等待直到超时。 - 编码:
decode('utf-8')是最常见的解码方式,如果你的数据是二进制(如图片、传感器原始值),你可能不需要解码,直接处理字节流即可。
- 换行符: 设备是否发送了换行符(
- 超时时间太短: 如果设备发送数据的间隔大于
timeout设置,你可能总是读取不到数据,可以适当增大timeout值,或者使用ser.in_waiting来检查。
- 波特率不匹配:这是最常见的原因,请确保 Python 脚本中的
Q4: python 和 Python 有什么区别?
这是一个很好的问题!在编程语境下,它们通常指的是同一个东西——Python 编程语言。
python: 通常是指在命令行中启动 Python 解释器的命令,你在终端输入python script.py来运行一个脚本,在一些系统(如 Linux)上,这个命令指向的是 Python 2.x 版本。python: 语言的名称。Python: 也是语言的名称,首字母大写,在写文章或正式文档时,通常使用Python,在命令行中,你几乎总是使用小写的python。
在你的代码和日常讨论中,python 和 Python 可以互换使用,都指代这门语言。注意区分大小写的是你代码中的变量名(如 MyVar 和 myvar 是不同的),而不是语言名称本身。

高级技巧:多线程处理
如果你的主程序需要做其他事情,但又不想阻塞串口数据的读取,可以使用多线程。
import serial
import threading
import time
# 用于存储数据的队列
data_queue = []
def serial_read_thread(ser):
"""一个专门用于读取串口数据的线程函数"""
print("串口监听线程已启动...")
while True:
if ser.in_waiting > 0:
line = ser.readline()
if line:
decoded_line = line.decode('utf-8').strip()
data_queue.append(decoded_line)
print(f"[监听线程] 接收到: {decoded_line}")
time.sleep(0.1) # 线程小休,避免CPU空转
# 主程序
if __name__ == '__main__':
ser = serial.Serial('COM3', 9600, timeout=1)
print(f"串口 {ser.name} 已打开")
# 创建并启动串口读取线程
read_thread = threading.Thread(target=serial_read_thread, args=(ser,), daemon=True)
read_thread.start()
try:
# 主线程可以做其他事情,比如定期处理队列中的数据
while True:
if data_queue:
# 从队列头部取出一条数据
data = data_queue.pop(0)
print(f"[主线程] 处理数据: {data}")
# 在这里可以对数据进行处理...
time.sleep(1) # 模拟主线程的其他工作
except KeyboardInterrupt:
print("\n程序被用户中断。")
finally:
ser.close()
print("串口已关闭。")
这个例子中,一个线程专门负责从串口读取数据并存入队列,另一个主线程则从队列中取出数据进行处理,两者互不干扰。
希望这份详细的指南能帮助你成功地在 Python 中实现串口通信和数据显示!
