4. 串口热插拔检测

任务说明

本案例实现一个串口热插拔检测工具,能够实时监测系统中串口设备的插入与拔出事件,并动态更新可用串口列表。程序启动时扫描当前所有串口设备并显示,随后持续监听系统串口变化,每当有新串口接入或已有串口移除时,自动刷新列表并打印事件信息。

实现方案

使用 pyserial 提供的 serial.tools.list_ports 模块获取当前串口列表,通过轮询方式周期性对比前后两次扫描结果,从而识别新增与移除的设备。轮询间隔设为1秒,兼顾实时性与系统资源占用。程序运行期间持续监听,直到用户按下 Ctrl+C 退出。

代码实现


import serial.tools.list_ports
import time

def get_serial_devices():
    """返回当前系统中所有可用串口设备列表"""
    ports = serial.tools.list_ports.comports()
    return {port.device: port.description for port in ports}

def main():
    print("串口热插拔检测已启动,按 Ctrl+C 退出...")
    print("-" * 50)

    # 初始扫描
    previous = get_serial_devices()
    if previous:
        print(f"当前检测到 {len(previous)} 个串口设备:")
        for dev, desc in previous.items():
            print(f"  {dev} - {desc}")
    else:
        print("当前未检测到串口设备")

    try:
        while True:
            time.sleep(1)  # 轮询间隔 1 秒
            current = get_serial_devices()

            # 检测新增设备
            added = set(current.keys()) - set(previous.keys())
            for dev in added:
                print(f"[插入] 检测到新串口: {dev} - {current[dev]}")

            # 检测移除设备
            removed = set(previous.keys()) - set(current.keys())
            for dev in removed:
                print(f"[拔出] 串口已移除: {dev} - {previous[dev]}")

            # 若有变化则更新列表并打印当前状态
            if added or removed:
                previous = current
                if current:
                    print(f"当前可用串口 ({len(current)} 个):")
                    for dev, desc in current.items():
                        print(f"  {dev} - {desc}")
                else:
                    print("当前无可用串口")
                print("-" * 50)

    except KeyboardInterrupt:
        print("\n检测已停止")

if __name__ == "__main__":
    main()

运行与验证

依赖安装:本程序仅需 pyserial 库,执行以下命令安装:

pip install pyserial

运行方式:在终端中执行:

python hotplug_detect.py

验证步骤与判定标准:

  1. 程序启动后,应打印当前系统中已连接的串口设备列表(若无设备则提示“当前未检测到串口设备”)。
  2. 插入一个USB转串口适配器,1秒内程序应打印 [插入] 信息,并刷新显示当前可用串口列表。
  3. 拔出该适配器,1秒内程序应打印 [拔出] 信息,并刷新列表。
  4. 按 Ctrl+C 程序正常退出,无异常报错。

满足以上行为即判定热插拔检测功能实现正确。

检测逻辑说明


┌─────────────────────────────────────────────────────────────┐
│                    串口热插拔检测流程                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌──────────┐     ┌──────────────┐     ┌──────────────┐   │
│   │ 初始扫描  │────▶│  轮询等待1秒  │────▶│  获取当前列表  │   │
│   └──────────┘     └──────────────┘     └──────┬───────┘   │
│                                                 │           │
│                                                 ▼           │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              与上一次列表对比                        │   │
│   └───────┬─────────────────────┬───────────────────────┘   │
│           │                     │                           │
│           ▼                     ▼                           │
│   ┌──────────────┐     ┌──────────────┐                     │
│   │ 有新增设备?   │     │ 有移除设备?   │                     │
│   └──────┬───────┘     └──────┬───────┘                     │
│           │                   │                             │
│           ▼                   ▼                             │
│   ┌─────────────────────────────────────────────┐           │
│   │  打印事件信息,更新列表并显示当前串口状态      │           │
│   └─────────────────────────────────────────────┘           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

该轮询方案不依赖操作系统底层事件通知机制,通过周期性对比串口列表快照实现插拔检测,具备良好的跨平台兼容性(Windows/Linux/macOS均可运行),且代码简洁、易于理解与扩展。