杰瑞科技汇

Python串口读取数据如何实现?

Python Serial Read终极指南:从零开始掌握串口数据读取(附代码+避坑)

** 还在为Python读取串口数据发愁?本文手把手教你使用pyserial库,解决卡顿、乱码、数据丢失等常见难题,并提供项目级实战案例。

Python串口读取数据如何实现?-图1
(图片来源网络,侵删)

(Meta Description)

想学习如何用Python读取串口数据吗?本文是您最全面的Python Serial Read教程,我们将深入讲解pyserial库的安装、配置、数据读取方法(阻塞/非阻塞),并提供完整代码示例,助您轻松解决数据读取中的常见问题,立即上手串口通信项目!


引言:为什么Python Serial Read如此重要?

在物联网、嵌入式系统开发、工业自动化以及各类硬件交互项目中,串口通信(Serial Communication)是一种稳定、可靠且广泛使用的数据传输方式,而Python,凭借其简洁的语法和强大的库支持,成为了连接硬件与上层应用的首选语言。

“Python serial read”是无数工程师和爱好者在百度搜索框中输入的关键词,无论你是想读取Arduino传感器的数据,还是与PLC进行通信,掌握Python串口读取都是一项必备技能,本文将带你彻底搞懂pyserial,让你不再为“读不到数据”、“数据乱码”等问题而烦恼。


第一步:环境准备 - 安装Pyserial库

pyserial是Python中最流行、功能最全面的串口通信库,在开始之前,我们需要先安装它。

Python串口读取数据如何实现?-图2
(图片来源网络,侵删)

打开你的命令行工具(CMD、PowerShell或Terminal),执行以下命令:

pip install pyserial

安装完成后,你就可以在Python脚本中导入并使用它了。

import serial

【SEO小贴士】:在文章开头就解决用户的第一个实际问题——“怎么安装?”,能快速建立信任感,降低跳出率。


第二步:核心配置 - 打开并配置串口

读取数据的第一步是“打开”串口,这就像打开一扇门,你需要知道门的地址(串口号)以及如何使用这扇门(波特率、数据位等参数)。

Python串口读取数据如何实现?-图3
(图片来源网络,侵删)

查找可用串口

在连接设备前,最好先确认你的电脑上有哪些串口可用。

import serial.tools.list_ports
# 列出所有可用串口
ports = serial.tools.list_ports.comports()
print("可用串口列表:")
for port in ports:
    print(f"设备: {port.device}, 描述: {port.description}, 制造商: {port.manufacturer}")

运行这段代码,你将看到类似 COM3/dev/ttyUSB0 的输出,这就是你的设备地址。

打开并配置串口

serial.Serial() 是核心函数,用于打开并配置一个串口连接。

import serial
# --- 配置参数 ---
PORT = 'COM3'  # Windows系统使用 'COMx',Linux/macOS使用 '/dev/ttyUSBx' 或 '/dev/tty.SLAB_USBtoUART'
BAUDRATE = 9600  # 波特率,必须与发送端设备设置一致
BYTESIZE = serial.EIGHTBITS  # 数据位
PARITY = serial.PARITY_NONE  # 校验位
STOPBITS = serial.STOPBITS_ONE  # 停止位
TIMEOUT = 1  # 超时时间(秒)
try:
    # 创建串口对象
    ser = serial.Serial(
        port=PORT,
        baudrate=BAUDRATE,
        bytesize=BYTESIZE,
        parity=PARITY,
        stopbits=STOPBITS,
        timeout=TIMEOUT
    )
    if ser.is_open:
        print(f"串口 {ser.name} 打开成功!")
        # ... 在这里进行数据读取 ...
        # 操作完成后,务必关闭串口
        ser.close()
        print("串口已关闭。")
except serial.SerialException as e:
    print(f"无法打开串口 {PORT}: {e}")

【关键参数解释】

  • port: 串口号,这是最重要的参数,务必写对。
  • baudrate (波特率): 数据传输速率,如 9600, 115200必须与你的硬件设备保持一致!
  • timeout (超时): 这是一个极其重要的参数,它决定了read()方法等待数据的时间。
    • timeout=0: 非阻塞模式,read()会立即返回,读取到多少数据就返回多少。
    • timeout=1: 阻塞模式,read()最多等待1秒,如果1秒内没有数据,则返回空字节。这是最常用和推荐的设置。
    • timeout=None: 永久阻塞模式,read()会一直等待,直到有数据到达。请谨慎使用,可能导致程序卡死。

第三步:数据读取 - 三种核心方法

串口配置好了,现在终于到了最核心的“读取”环节。pyserial提供了三种主要的读取方法,适用于不同的场景。

ser.read(size=1) - 读取指定字节数

这是最基础的读取方法,它会从串口缓冲区中读取指定size数量的字节。

if ser.is_open:
    # 读取1个字节
    byte_data = ser.read(1)
    print(f"读取到1个字节: {byte_data}, 类型: {type(byte_data)}")
    # 读取10个字节
    ten_bytes = ser.read(10)
    print(f"读取到10个字节: {ten_bytes}")

适用场景:当你确切知道每次数据包的固定大小时,例如读取一个16位的传感器数据。

ser.readline() - 读取一行数据

readline()会持续读取,直到遇到换行符(\n)或回车符(\r)为止,然后返回整行数据。

注意:发送端的数据必须包含换行符,否则readline()会一直阻塞(根据timeout设置)。

if ser.is_open:
    # 假设发送端发送 "Hello World!\n"
    line_data = ser.readline()
    print(f"读取到一行数据: {line_data}")
    # 如果数据是文本,记得解码
    decoded_line = line_data.decode('utf-8').strip()
    print(f"解码后的文本: {decoded_line}")

适用场景:与人机交互终端(如串口助手)通信,或者发送端以文本行形式发送数据时。

ser.readall() - 读取所有可用数据

readall()会读取串口缓冲区中所有当前可用的数据,然后返回。

if ser.is_open:
    # 假设缓冲区有 "abc" 和 "123"
    all_data = ser.readall()
    print(f"读取到所有数据: {all_data}")

适用场景:较少使用,通常用于一次性读取所有遗留数据,或在非阻塞模式下快速清空缓冲区。


第四步:实战案例 - 实时读取并解析传感器数据

理论讲完了,让我们来一个实战项目,假设我们有一个通过串口持续发送温度数据的传感器,数据格式为:TEMP:25.6\n

我们的目标是:实时读取数据,提取出温度值,并在控制台打印。

import serial
import time
# --- 串口配置 ---
PORT = 'COM3'
BAUDRATE = 9600
try:
    ser = serial.Serial(PORT, BAUDRATE, timeout=1)
    print(f"正在从 {ser.name} 读取数据...")
    while True:
        if ser.in_waiting > 0:  # 检查缓冲区是否有数据
            # 读取一行
            line = ser.readline()
            try:
                # 解码为字符串并去除首尾空白字符
                decoded_line = line.decode('utf-8').strip()
                # 检查是否是我们期望的数据格式
                if decoded_line.startswith("TEMP:"):
                    # 提取温度值
                    temp_str = decoded_line.split(":")[1]
                    temperature = float(temp_str)
                    print(f"当前温度: {temperature} °C")
            except UnicodeDecodeError:
                print(f"接收到无法解码的数据: {line}")
            except ValueError:
                print(f"数据格式错误,无法转换为浮点数: {decoded_line}")
            except IndexError:
                print(f"数据格式不正确: {decoded_line}")
        # 避免CPU空转
        time.sleep(0.1)
except serial.SerialException as e:
    print(f"串口错误: {e}")
finally:
    if 'ser' in locals() and ser.is_open:
        ser.close()
        print("串口已关闭。")

代码解析:

  1. 我们使用一个while True循环来持续监听串口。
  2. ser.in_waiting > 0 是一个高效的非阻塞检查,它告诉我们缓冲区里是否有新数据,避免了无谓的read()调用。
  3. 我们用try-except块来优雅地处理可能发生的错误,如数据乱码(解码错误)或数据格式不正确(索引错误、转换错误)。
  4. time.sleep(0.1)让程序稍微“休息”一下,防止CPU占用率过高。

第五步:常见问题与解决方案 (FAQ)

Q1: 为什么我读取的数据是乱码,或者完全读不到?

A: 这是最常见的问题,通常由以下几个原因造成:

  1. 串口号错误:再次检查list_ports的输出,确保PORT变量设置正确。
  2. 波特率不匹配这是头号杀手! 确认你的设备(如Arduino、ESP32)的代码中设置的Serial.begin()的波特率与Python脚本中的BAUDRATE完全一致。
  3. 设备未连接或未供电:检查硬件连接线和设备电源。
  4. 权限问题 (Linux/macOS):在Linux或macOS上,普通用户可能没有权限访问串口,尝试使用sudo运行你的Python脚本,或将用户添加到dialout组。
    sudo usermod -a -G dialout $USER
    # 然后需要重新登录或重启系统

Q2: 为什么我的程序会卡在 ser.readline()ser.read() 上?

A: 这是因为timeout设置不当。

  • 如果timeout设置得太大或为None,而发送端又没有按时发送数据或发送格式不正确(如缺少换行符),程序就会一直等待。
  • 解决方案:将timeout设置为一个合理的值,如1(秒),如果1秒内没有数据,函数会返回,你的程序可以继续执行其他逻辑。

Q3: 如何处理数据丢失的问题?

A: 数据丢失通常发生在读取速度跟不上数据发送速度时。

  1. 增加读取频率:在while循环中减少time.sleep()的时间,或者使用更高效的读取逻辑。
  2. 增大缓冲区pyserial的缓冲区大小是有限的,如果数据量极大且密集,可以考虑在应用层实现自己的数据缓冲队列。
  3. 优化发送端:如果可能,让发送端降低发送频率,或发送更小的数据包。

总结与展望

恭喜你!现在你已经从零开始,掌握了Python串口数据读取的核心技能,我们回顾一下今天的关键点:

  1. 安装:使用pip install pyserial
  2. 配置:使用serial.Serial()正确配置端口、波特率等参数,timeout至关重要。
  3. 读取:根据场景选择read(size)readline()readall()
  4. 实战:通过一个实时读取传感器数据的案例,将理论付诸实践。
  5. 排错:学会解决“读不到”、“乱码”、“卡死”等常见问题。

串口通信是连接软件与物理世界的桥梁,掌握了python serial read,你就为探索更广阔的物联网和嵌入式开发领域打下了坚实的基础,你可以尝试将读取到的数据存入数据库、绘制成动态图表,或者通过Web界面进行展示。

【行动号召】 现在就动手,连接你的第一个串口设备,用Python读取它的数据吧!如果在实践中遇到任何问题,欢迎在评论区留言讨论。


#Python #串口通信 #pyserial #SerialRead #物联网 #嵌入式开发 #硬件编程 #Python教程

分享:
扫描分享到社交APP
上一篇
下一篇