串网直通车——串口篇(Python+serial+threading)

本文详细介绍了如何使用Python的pyserial库实现串口通信功能,包括串口的打开、关闭、数据接收和发送。文中提供了一个完整的串口调试助手的实现代码,特别强调了接收函数的优化,以避免在快速传输时出现错误。同时,给出了测试和拓展信息,帮助读者更好地理解和应用串口通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        完整代码链接:https://download.youkuaiyun.com/download/qq_34162147/54904655

        本章节是续上一篇(界面篇)。如未搭建界面,请查阅以下链接。


串网直通车——界面篇_不尽之野火-优快云博客


        本章节主要是实现串口功能,实现串口收发。类似串口调试助手。如未安装串口模块,可在Python根目录通过命令pip install pyserial进行安装。

1、打开串口

        Python使用串口功能以及线程功能,需要在开头引入。结合前篇(界面篇),需要在开头引入全局变量。

import serial       #串口
import threading    #线程

# 全局变量
global ser
global com_text
global trans_cu

        将以下代码替换到界面篇的com_ctrl函数。整体替换。

        这个函数中cn_var,cp_var,cr_var,cl_var,p0,p1都是通过按钮操作传递过来,读取下拉菜单的值。

        cn_var是按钮控件名 

        cp_var是端口号

        cr_var是波特率

        cl_var是指示灯控件

        p0是红灯图片

        p1是绿灯图片

       函数中,recv_com_data是用来定义接收线程。接收函数是thread_com_recv,后续有讲解。创建线程是为了实现接收一直起作用,程序并与界面显示并行运行。

        代码经过优化,经测试达到0错误。代码中多次使用if和else pass组合。是因为参考其他程序时,发现有错误,无法正常停止串口。而且在else之后绑定串口的ser无法继续使用。如有大神能够知道原因,请在评论区告知,在此感谢!

# 串口打开关闭函数
def  com_ctrl(cn_var,cp_var,cr_var,cl_var,p0,p1):

    global ser
    global com_state
    global com_text
    
    if cn_var.get() == "打开串口":
        ser = serial.Serial(
            port = cp_var,
            baudrate=int(cr_var),
            bytesize=serial.EIGHTBITS, 
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE, 
            timeout=0.2,
            xonxoff=False, 
            rtscts=False,           
            interCharTimeout=None
            )

        if ser.is_open:
            com_state=1
        else:
            ser.open()
            com_state=1

        com_text.delete(1.0,END)


        recv_com_data = threading.Thread(target=thread_com_recv)#创建接收线程
        recv_com_data.start()

    else :
        pass

    if ser.is_open and cn_var.get() == "关闭串口":
        com_state=0
        ser.close()  # 关闭传口
        cn_var.set("打开串口")
        cl_var.configure(image=p0) 
    else:
        pass

    if ser.is_open :
        cn_var.set("关闭串口")
        cl_var.configure(image=p1) 
    else:
        pass   

2、接收

        接收函数整体添加即可。这部分对应打开串口的thread_com_recv函数。

        特别注意:read_com = ser.read_all()后面是read_all,而不是readall。其他地方很多代码都存在这个问题。如果写成readall,可以使用。但是快速传输时,每包数据小于500ms,问题就暴露了,接收出错。实际官方是read_all。

        代码中com_text.see(END),see是用于ScrolledText滚动条文本框控件的光标移动,使得滚动条随着接收数据的增多而移动至最后。此部分结合界面篇带滚动条文本框部分。

        代码中使用了try和except Exception:break的组合,作用在于接收时,防止接收函数read_all()导致出错。出错时会有退出机制。其他网上代码存在此部分不完善的地方。这部分导致停止运行时无法正常停止。必须强制关闭运行进程。

        代码中“停止接收线程”备注那部分,作用是点击按钮关闭时,能够跳出线程,并终止。因为接收代码运行时,一直在while循环。其他网上代码存在此部分不完善的地方。必须强制关闭运行进程,否则串口一直出错而占用。

        代码中的decode是解码,用于串口接收到十六进制ACSII码的解码。

        此部分代码提到的com_send函数,后续会讲解到。只测试接收时,可以先屏蔽。

        特别注意:此部分代码测试时,不能直接点击窗口右上角关闭,必须优先点击关闭串口按钮,关闭窗口。

# 串口数据接收线程
def thread_com_recv():
    global ser
    global com_text
    global com_state
    global trans_cu
    while True:
        try:
            read_com = ser.read_all()
            if len(read_com) > 0:
                trans_cu=bytes(read_com).decode('ascii')           
                com_text.insert(END,trans_cu)
                com_text.insert(END,'\n')
                com_text.see(END)#滚动条移动到最新输入位置           
                # net_send(trans_cu) 
                com_send('I have received your data')       
                print("COM 接收到的数据:%s" % read_com)
                print("COM 接收到的数据:%s" % trans_cu)
            else:
                pass 
        except Exception:
            break  

        if(com_state==0):
            break   #停止wihile循环,停止接收线程
        else:
            pass

插节

        如果程序一直运行,不知道什么错误,如图所示,可以强制停止。我用的是VScode+python3.8

3、发送

         这部分的代码直接添加即可。此部分结合接收函数使用测试。

        代码中encode是编码。

def com_send(cs_var):
    s = ser.isOpen()
    if s == True:
        ser.write(cs_var.encode("utf-8"))

4、测试

        可用串口助手与虚拟串口两个小软件配合从测试。测试效果如图所示。

 5、拓展

        在学习过程,参考了不少资料,也填了不少坑。在此感谢各位前辈们的付出。经过整理筛选后,同样将有用的分享给大家!

Python实现串口通信(pyserial) - -零 - 博客园

Python 实现串口调试助手_u011625775的博客-优快云博客_python串口调试助手(此代码需要完善)

python3 字符串、十六进制字符串、数字、字节之间的转换_羊驼的博客笔记-优快云博客

<think>好的,我现在要帮助用户解决如何使用VSCode开发Python上位机程序的问题。首先,我需要回想用户提供的引用内容,看看有没有相关的信息可以引用。 根据引用[3],用户提到在Ubuntu系统上使用VSCode进行Python开发的环境搭建,这可能涉及到安装扩展、配置调试环境等步骤。引用[1][2]分别提到了VSCodePyCharm的下载链接,但用户明确想用VSCode,所以重点在引用[3]的内容。引用[4]是关于Python学习资料,可能可以作为附加建议。 接下来,我需要按照用户的要求分步骤回答,结构要清晰。首先,可能需要安装VSCode,然后配置Python环境,安装必要的扩展,设置调试配置,最后涉及上位机开发的特定库或工具,比如串口通信或GUI框架。 用户的问题是关于上位机程序,通常上位机需要与硬件通信,比如通过串口、USB或络,所以可能需要用到PySerial、Tkinter、PyQt等库。同时,调试代码组织也是关键点。 需要确保回答中提到的步骤正确,例如安装Python扩展、配置launch.json等,这些在引用[3]中有提到。另外,上位机开发可能需要额外的库,这部分可能需要用户自行安装,但应该给出示例代码,比如使用PySerial读取串口数据。 可能还需要提醒用户关于虚拟环境的使用,保持项目依赖的独立性,这在Python开发中很重要。引用[4]的学习资料可以作为补充资源推荐,帮助用户巩固Python基础。 最后,生成相关问题时要围绕VSCode配置、Python库选择、调试技巧、GUI设计以及上位机通信等方面,确保问题有针对性,帮助用户深入理解。</think>以下是使用VSCode开发Python上位机程序的详细步骤: --- ### 一、环境搭建 1. **安装VSCode** 从[官下载VSCode](https://code.visualstudio.com/)并安装[^1]。支持Windows/Linux/macOS系统。 2. **安装Python扩展** 在VSCode扩展商店搜索并安装: - *Python*(语法高亮、调试支持) - *Pylance*(代码补全) - *Jupyter*(交互式开发) 3. **配置Python解释器** - 按`Ctrl+Shift+P` → 输入`Python: Select Interpreter`选择已安装的Python版本 - 推荐使用虚拟环境: ```bash python -m venv .venv ``` --- ### 二、上位机开发核心配置 1. **硬件通信库安装** 根据需求选择以下库(示例使用串口通信): ```bash pip install pyserial # 串口通信 pip install pyusb # USB设备控制 ``` 2. **调试配置** 创建`.vscode/launch.json`,配置调试参数: ```json { "version": "0.2.0", "configurations": [ { "name": "Python: Current File", "type": "python", "request": "launch", "program": "${file}", "console": "integratedTerminal", "args": ["--port", "COM3"] // 传递串口参数 } ] } ``` --- ### 三、上位机功能实现(示例) 1. **串口数据读取** ```python import serial from serial.tools import list_ports # 自动检测可用串口 ports = list_ports.comports() for port in ports: print(f"可用端口: {port.device}") # 连接设备 ser = serial.Serial('COM3', 9600, timeout=1) while True: data = ser.readline().decode('utf-8').strip() if data: print(f"接收数据: {data}") ``` 2. **GUI界面开发** 推荐使用PyQt5或Tkinter: ```python # Tkinter示例 import tkinter as tk from tkinter import ttk class UpperComputerApp: def __init__(self): self.root = tk.Tk() self.setup_ui() def setup_ui(self): self.btn_connect = ttk.Button(self.root, text="连接设备", command=self.connect_device) self.btn_connect.pack(pady=10) def connect_device(self): print("启动设备连接...") if __name__ == "__main__": app = UpperComputerApp() app.root.mainloop() ``` --- ### 四、调试与优化技巧 1. **断点调试** 在代码行号左侧点击设置断点,按`F5`启动调试,支持变量监视单步执行。 2. **代码格式化** 安装*Black Formatter*扩展,保存时自动格式化代码。 3. **单元测试** 创建`tests`目录,使用`pytest`框架编写测试用例: ```bash pip install pytest ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值