杰瑞科技汇

Python与Python串口显示有何区别?

什么是串口通信?

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

Python与Python串口显示有何区别?-图1
(图片来源网络,侵删)

准备工作:安装必要的库

Python 本身没有内置串口通信的模块,我们需要借助第三方库,最常用、最稳定的是 pyserial

安装 pyserial 打开你的终端或命令提示符,运行以下命令:

pip install pyserial

串口显示的核心步骤

使用 Python 进行串口通信并显示数据,通常遵循以下步骤:

  1. 导入 serialimport serial
  2. 打开串口serial.Serial(),指定串口号、波特率等参数。
  3. 读取数据ser.read()ser.readline()
  4. 处理和显示数据:将读取到的字节流解码成字符串,并打印到控制台。
  5. 关闭串口ser.close(),这是一个好习惯,确保资源被释放。

代码示例

示例 1:最简单的“一问一答”模式

这个例子适用于你向设备发送一个命令,然后设备返回一行数据的场景。

Python与Python串口显示有何区别?-图2
(图片来源网络,侵删)
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: 读取到的数据是乱码,或者没有数据。

  • 原因:
    1. 波特率不匹配:这是最常见的原因,请确保 Python 脚本中的 baudrate 和你设备(如 Arduino)代码中的 Serial.begin(9600) 设置的波特率完全一致。
    2. 数据格式问题
      • 换行符: 设备是否发送了换行符(\n)?ser.readline() 默认以换行符为结束标志,如果设备发送的是 data1,data2,data3 而没有换行符,readline() 会一直等待直到超时。
      • 编码: decode('utf-8') 是最常见的解码方式,如果你的数据是二进制(如图片、传感器原始值),你可能不需要解码,直接处理字节流即可。
    3. 超时时间太短: 如果设备发送数据的间隔大于 timeout 设置,你可能总是读取不到数据,可以适当增大 timeout 值,或者使用 ser.in_waiting 来检查。

Q4: pythonPython 有什么区别?

这是一个很好的问题!在编程语境下,它们通常指的是同一个东西——Python 编程语言

  • python: 通常是指在命令行中启动 Python 解释器的命令,你在终端输入 python script.py 来运行一个脚本,在一些系统(如 Linux)上,这个命令指向的是 Python 2.x 版本。
  • python: 语言的名称。
  • Python: 也是语言的名称,首字母大写,在写文章或正式文档时,通常使用 Python,在命令行中,你几乎总是使用小写的 python

在你的代码和日常讨论中,pythonPython 可以互换使用,都指代这门语言。注意区分大小写的是你代码中的变量名(如 MyVarmyvar 是不同的),而不是语言名称本身。

Python与Python串口显示有何区别?-图3
(图片来源网络,侵删)

高级技巧:多线程处理

如果你的主程序需要做其他事情,但又不想阻塞串口数据的读取,可以使用多线程。

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 中实现串口通信和数据显示!

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