基于Python的Windows串口通信工具

基于Python的Windows串口通信工具

在工业控制、嵌入式开发和物联网应用中,串口通信是设备调试和数据交互的重要方式。本文将详细介绍如何使用Python开发一个功能完善的串口通信工具,支持串口参数配置、数据收发、实时监控等功能,并提供完整的代码示例和使用说明。

1. 环境准备

1.1 安装依赖库

  • pySerial:用于串口通信的核心库。
    安装命令:
  pip install pyserial
  • Tkinter:Python内置的图形用户界面(GUI)库,无需额外安装。

1.2 开发环境

  • 操作系统:Windows 7/10/11(支持COM端口)。
  • Python版本:3.8及以上(推荐使用最新稳定版)。

2. 功能需求分析

目标开发一个具备以下功能的串口通信工具:

  1. 串口扫描:自动检测当前可用的串口设备。
  2. 参数配置:设置波特率、数据位、停止位、校验位等参数。
  3. 数据收发
  • 支持文本和十六进制模式发送数据。
  • 实时接收并显示数据(支持文本和十六进制显示)。
  1. 多线程处理:确保串口接收数据时界面不卡顿。
  2. 错误处理:捕获串口操作中的异常并提示用户。

3. 代码实现

3.1 导入依赖库

import serial
import serial.tools.list_ports
import threading
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox

3.2 主窗口类定义

class SerialTool:
    def __init__(self, root):
        self.root = root
        self.root.title("Python串口通信工具")
        self.serial_port = None
        self.receive_thread = None
        self.running = False

        # 初始化UI
        self.create_widgets()

3.3 UI布局设计

    def create_widgets(self):
        # 串口参数设置区域
        param_frame = ttk.LabelFrame(self.root, text="串口参数")
        param_frame.grid(row=0, column=0, padx=10, pady=10, sticky="ew")

        # 串口选择
        ttk.Label(param_frame, text="串口:").grid(row=0, column=0, padx=5, pady=5)
        self.port_combobox = ttk.Combobox(param_frame, width=10)
        self.port_combobox.grid(row=0, column=1, padx=5, pady=5)
        self.update_ports()

        # 波特率
        ttk.Label(param_frame, text="波特率:").grid(row=0, column=2, padx=5, pady=5)
        self.baudrate_combobox = ttk.Combobox(param_frame, values=["9600", "115200", "230400", "921600"], width=10)
        self.baudrate_combobox.set("115200")
        self.baudrate_combobox.grid(row=0, column=3, padx=5, pady=5)

        # 打开/关闭按钮
        self.open_button = ttk.Button(param_frame, text="打开串口", command=self.toggle_serial)
        self.open_button.grid(row=0, column=4, padx=5, pady=5)

        # 数据收发区域
        io_frame = ttk.Frame(self.root)
        io_frame.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")

        # 接收数据框
        self.receive_text = scrolledtext.ScrolledText(io_frame, height=15, state='disabled')
        self.receive_text.pack(side="top", fill="both", expand=True)

        # 发送数据区域
        send_frame = ttk.Frame(io_frame)
        send_frame.pack(side="bottom", fill="x")

        ttk.Label(send_frame, text="发送数据:").pack(side="left")
        self.send_entry = ttk.Entry(send_frame, width=50)
        self.send_entry.pack(side="left", fill="x", expand=True)

        self.send_button = ttk.Button(send_frame, text="发送", command=self.send_data)
        self.send_button.pack(side="right", padx=5)

        # 显示模式切换
        self.display_mode = tk.StringVar(value="text")
        ttk.Radiobutton(send_frame, text="文本模式", variable=self.display_mode, value="text").pack(side="left")
        ttk.Radiobutton(send_frame, text="十六进制模式", variable=self.display_mode, value="hex").pack(side="left")

3.4 串口操作函数

    def update_ports(self):
        """更新可用串口列表"""
        ports = [port.device for port in serial.tools.list_ports.comports()]
        self.port_combobox['values'] = ports
        if ports:
            self.port_combobox.current(0)

    def toggle_serial(self):
        """打开/关闭串口"""
        if not self.serial_port:
            try:
                port = self.port_combobox.get()
                baudrate = int(self.baudrate_combobox.get())
                self.serial_port = serial.Serial(port, baudrate, timeout=1)
                self.open_button.config(text="关闭串口")
                self.running = True
                self.receive_thread = threading.Thread(target=self.receive_data)
                self.receive_thread.start()
            except Exception as e:
                messagebox.showerror("错误", f"无法打开串口: {e}")
        else:
            self.running = False
            self.serial_port.close()
            self.serial_port = None
            self.open_button.config(text="打开串口")

    def send_data(self):
        """发送数据(文本或十六进制)"""
        if not self.serial_port:
            messagebox.showwarning("警告", "请先打开串口!")
            return

        data = self.send_entry.get()
        if not data:
            return

        if self.display_mode.get() == "text":
            self.serial_port.write(data.encode('utf-8'))
        else:
            try:
                hex_data = bytes.fromhex(data.replace(" ", ""))
                self.serial_port.write(hex_data)
            except ValueError:
                messagebox.showerror("错误", "无效的十六进制数据!")

    def receive_data(self):
        """接收数据线程"""
        while self.running:
            if self.serial_port and self.serial_port.in_waiting > 0:
                raw_data = self.serial_port.read(self.serial_port.in_waiting)
                display_data = raw_data
                if self.display_mode.get() == "text":
                    try:
                        display_data = raw_data.decode('utf-8', errors='replace')
                    except:
                        pass
                self.update_receive_text(display_data)

    def update_receive_text(self, data):
        """更新接收数据框(线程安全)"""
        self.root.after(0, lambda: self.receive_text.configure(state='normal'))
        self.root.after(0, lambda: self.receive_text.insert(tk.END, data))
        self.root.after(0, lambda: self.receive_text.configure(state='disabled'))
        self.root.after(0, lambda: self.receive_text.see(tk.END))

3.5 主程序入口

if __name__ == "__main__":
    root = tk.Tk()
    app = SerialTool(root)
    root.mainloop()

4. 使用说明

  1. 启动工具
    运行脚本后,窗口将显示可用的串口列表和默认参数。
  2. 配置串口
  • 选择串口(COM端口)。
  • 设置波特率(如9600、115200等)。
  • 点击“打开串口”按钮建立连接。
  1. 发送数据
  • 在输入框中输入文本或十六进制数据(如48 65 6C 6C 6F表示Hello)。
  • 选择“文本模式”或“十六进制模式”。
  • 点击“发送”按钮。
  1. 接收数据
  • 接收数据会实时显示在上方的滚动文本框中。
  • 支持动态切换显示模式(文本/十六进制)。
  1. 关闭串口
    点击“关闭串口”按钮断开连接并释放资源。

5. 扩展功能建议

  1. 自动刷新串口列表
    增加定时刷新按钮,动态更新可用串口。
  2. 数据保存与日志
    添加“保存日志”功能,将接收数据保存到文件。
  3. 自动发送
    支持定时自动发送预设数据。
  4. 高级参数配置
    增加数据位、停止位、校验位等参数设置选项。
  5. 图形化数据展示
    集成Matplotlib库,将接收的数值数据绘制成图表。

6. 总结

通过本文的实现,我们构建了一个基于Python的Windows串口通信工具,支持基本的串口配置、数据收发和实时监控功能。该工具适用于快速调试硬件设备、验证通信协议或教学演示。结合多线程技术和Tkinter的图形化界面,用户能够高效地进行串口数据交互。对于更复杂的需求,可通过扩展功能进一步增强工具的实用性。

© 版权声明
THE END
喜欢就支持一下吧
点赞13赞赏 分享