超级好用的Python QT GUI串口调试助手


目录

前言

一、软件概要:

二、软件界面:

1.App动态演示

2.其他扩展展示

三、main.py源码:

1.PyQt5_Serial_Debug_Assistant_V1.0源码

四、获取 >> 源码以及Git记录:

总结


前言

Python串口调试助手支持常用的50bps - 10Mbps波特率,能设置校验、数据位和停止位,能以ASCII码或十六进制接收或发送任何数据或字符,可以任意设定自动发送周期,并能将接收数据实时保存成文本文件,能发送任意大小的数据或字符。

备注: V1.0为简单Demo,适合初级用户使用,V1.1可用于工程应用

高级版: 【博客9】缤果PyQt5串口调试助手V2.0(高级篇)_pyqt 串口助手_Bingo缤果的博客-CSDN博客


英文名:PyQt5_Serial_Debug_Assistant_V1.1
支持:常用的50bps ~ 10Mbps波特率
类型:串口调试助手
软件大小:18M
软件版本:V1.1
软件下载&更新:百度网盘链接_提取码 6666

一、软件概要:

一款强大而稳定的PyQt串口调试助手,支持常用的110-921600bps波特率及自定义波特率,波特率最高可支持8000000(串口硬件有关),可适应于非标准波特率。支持动态修改串口和波特率,保存当前日志,打开当前日志以及实时保存日志(默认按每小时分包保存日志,100M自动清空接收窗口,防止UI阻塞)。

二、软件界面:

1.App动态演示

2.其他扩展展示

PyQt5_Serial_Debug_Assistant_V1.1

PyQt5_Serial_Debug_Assistant_V1.1_串口UI布局

PyQt5_Serial_Debug_Assistant_V1.0

三、main.py源码:

1.PyQt5_Serial_Debug_Assistant_V1.0源码

代码如下(示例):

import sys
import serial  # 导入模块  #安装: pip3 install pyserial
import serial.tools.list_ports
import webbrowser
import time
import datetime# 导入Ui设计
from PyQt5.QtWidgets import QApplication, QMainWindow # 串口Ui文件
from PyQt5.QtWidgets import QMessageBox, QLabel, QFileDialog
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QIconimport Serial_Ui_Designer  # 串口UI文件# PyQt5程序打包
# 1.使用PyInstaller来打包:
# 安装:pip3 install PyInstaller
# 打包:pyinstaller -F -w -i=Com.ico main.py  #单文件打包-优缺点:只生成exe文件,但文件大,打开软件时加载时间长
# 打包:pyinstaller -D -w -i=Com.ico main.py  #多文件打包-优缺点:生成exe关联包,可删除无效库,文件小,运行顺畅# 主窗口
class PyQt5_Serial(QMainWindow, Serial_Ui_Designer.Ui_MainWindow):# 初始化程序def __init__(self):super(PyQt5_Serial, self).__init__()self.setupUi(self)self.Init()self.Qt5_Ui_Init()# 初始化def Init(self):self.ser = serial.Serial()self.port_check()self.baudrateBox.setCurrentIndex(5)  # 921600-20 9600-5self.dataBitsBox.setCurrentIndex(3)   # 8# 设置Logo和标题self.setWindowIcon(QIcon('Com.ico'))self.setWindowTitle("PyQt5_串口调试助手_V1.0")#self.setWindowTitle("PyQt5_Serial_Debug_Assistant_V1.0")# 发送数据和接收数据数目置零self.data_num_sended = 0self.label_Tx.setText(str(self.data_num_sended))self.data_num_received = 0self.label_Rx.setText(str(self.data_num_received))# 串口关闭按钮使能关闭self.sendButton.setEnabled(0)self.checkBox_autoSend.setEnabled(0)# 发送框、文本框清除self.sendTextEdit.setText("")self.recvTextEdit.setText("")# 建立控件信号与槽关系def Qt5_Ui_Init(self):# 串口检测按钮self.pushButton_Refresh.clicked.connect(self.port_check)# 串口打开按钮self.pushButton_Open_Close.clicked.connect(self.port_open_close)# 定时发送数据self.timer_send = QTimer()self.timer_send.timeout.connect(self.data_send)self.checkBox_autoSend.stateChanged.connect(self.data_send_timer)# 发送数据按钮self.sendButton.clicked.connect(self.data_send)# 保存日志self.pushButton_saveLog.clicked.connect(self.savefiles)# 加载文件self.pushButton_openLog.clicked.connect(self.openfiles)# 跳转链接self.commandLinkButton.clicked.connect(self.link)# 清除发送按钮self.pushButton_ClearSend.clicked.connect(self.send_data_clear)# 清除接收按钮self.pushButton_ClearRecive.clicked.connect(self.receive_data_clear)# RTSself.checkBox_RTS.clicked.connect(self.rts_handle)# DTRself.checkBox_DTR.clicked.connect(self.dtr_handle)# 串口检测def port_check(self):# 检测所有存在的串口,将信息存储在字典中self.Com_Dict = {}port_list = list(serial.tools.list_ports.comports())self.portNameBox.clear()for port in port_list:self.Com_Dict["%s" % port[0]] = "%s" % port[1]self.portNameBox.addItem(port[0])# 无串口判断if len(self.Com_Dict) == 0:self.portNameBox.addItem("无串口")# 打开/关闭串口def port_open_close(self):if self.pushButton_Open_Close.text() == "打开串口":self.port_open()else:self.port_close()# 打开串口def port_open(self):port = self.portNameBox.currentText()# print("port:", port)baudrate = int(self.baudrateBox.currentText())# print("baudrate:", baudrate)bytesize = int(self.dataBitsBox.currentText()) # 数据位# print("bytesize:", bytesize)parity = self.ParityBox.currentText()  # 校验位# print("parity:", parity)stopbits = self.stopBitsBox.currentText() # 停止位# print("stopbits:", stopbits)flowctrl = self.flowControlBox.currentText()  # 流控self.ser.port = portself.ser.baudrate = baudrate# print("bytesize:", bytesize)if bytesize == 5:self.ser.bytesize = serial.FIVEBITSelif bytesize == 6:self.ser.bytesize = serial.SIXBITSelif bytesize == 7:self.ser.bytesize = serial.SEVENBITSelif bytesize == 8:self.ser.bytesize = serial.EIGHTBITSelse:self.ser.bytesize = serial.EIGHTBITS# print("parity:", parity)if parity == "None":self.ser.parity = serial.PARITY_NONEelif parity == "Even":self.ser.parity = serial.PARITY_EVENelif parity == "Odd":self.ser.parity = serial.PARITY_ODDelif parity == "Space":self.ser.parity = serial.PARITY_SPACEelif parity == "Mark":self.ser.parity = serial.PARITY_MARKelse:self.ser.parity = serial.PARITY_NONE# print("stopbits:", stopbits)if stopbits == "1":self.ser.stopbits = serial.STOPBITS_ONEelif stopbits == "1.5":self.ser.parity = serial.STOPBITS_ONE_POINT_FIVEelif stopbits == "2":self.ser.parity = serial.STOPBITS_TWOelse:self.ser.stopbits = serial.STOPBITS_ONEself.ser.xonxoff = False  # 软件流控self.ser.rtscts  = False  # 硬件流控 RTSself.ser.dsrdtr  = False  # 硬件流控 DTR# print("flowctrl:", flowctrl)if flowctrl == "OFF":self.ser.xonxoff = False  # 软件流控self.ser.rtscts  = False  # 硬件流控 RTSself.ser.dsrdtr  = False  # 硬件流控 DTRelif flowctrl == "Hardware":if self.checkBox_DTR.isChecked():self.ser.dsrdtr = True  #硬件流控 DTRif self.checkBox_RTS.isChecked():self.ser.rtscts = True  #硬件流控 RTSelif flowctrl == "Software":self.ser.xonxoff = True   # 软件流控self.ser.rtscts  = False  # 硬件流控 RTSself.ser.dsrdtr  = False  # 硬件流控 DTR# print(self.ser)# Serial < id = 0x4883040, open = False > (port='COM1', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)try:self.ser.open()except:QMessageBox.critical(self, "串口异常", "串口打开失败! 错误: 拒绝访问(被占用).")return None# 串口打开后,切换开关串口按钮使能状态,防止失误操作if self.ser.isOpen():self.pushButton_Open_Close.setText("关闭串口")self.portNameBox.setEnabled(0)self.baudrateBox.setEnabled(0)self.dataBitsBox.setEnabled(0)self.ParityBox.setEnabled(0)self.stopBitsBox.setEnabled(0)self.flowControlBox.setEnabled(0)self.pushButton_Refresh.setEnabled(0)self.sendButton.setEnabled(1)self.checkBox_autoSend.setEnabled(1)# 定时器接收数据self.timer = QTimer()self.timer.timeout.connect(self.data_receive)# 打开串口接收定时器,周期为1msself.timer.start(1)# 关闭串口def port_close(self):try:self.timer.stop()self.timer_send.stop()self.ser.close()self.pushButton_Open_Close.setText("打开串口")self.portNameBox.setEnabled(1)self.baudrateBox.setEnabled(1)self.dataBitsBox.setEnabled(1)self.ParityBox.setEnabled(1)self.stopBitsBox.setEnabled(1)self.flowControlBox.setEnabled(1)self.pushButton_Refresh.setEnabled(1)self.sendButton.setEnabled(0)self.checkBox_autoSend.setEnabled(0)except:QMessageBox.critical(self, '串口异常', '关闭串口失败,请重启程序!')return None# 定时发送数据def data_send_timer(self):try:if 1<= int(self.spinBox_timeDly.text()) <= 300000:  # 定时时间1ms~30s内if self.checkBox_autoSend.isChecked():self.timer_send.start(int(self.spinBox_timeDly.text()))self.spinBox_timeDly.setEnabled(False)else:self.timer_send.stop()self.spinBox_timeDly.setEnabled(True)else:QMessageBox.critical(self, '定时发送数据异常', '定时发送数据周期仅可设置在300秒内!')except:QMessageBox.critical(self, '定时发送数据异常', '请设置正确的数值类型!')# 发送数据def data_send(self):if self.ser.isOpen():input_s = self.sendTextEdit.toPlainText()# 判断是否为非空字符串if input_s != "":# 时间显示if self.checkBox_displayTime.isChecked():if self.checkBox_displaySend.isChecked():self.recvTextEdit.insertPlainText(self.get_datetime())# HEX发送if self.checkBox_hexSend.isChecked():#input_s = input_s.strip() #strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。input_s = input_s.replace(" ", "")send_list = []while input_s != '':try:num = int(input_s[0:2], 16) # 没有步长的简单切片#print( hex(num) )except ValueError:QMessageBox.critical(self, '数据异常', '请输入规范的十六进制数据!')return Noneinput_s = input_s[2:]send_list.append(num)if self.checkBox_CR_LF.isChecked():send_list.append(0x0D)send_list.append(0x0A)input_s = bytes(send_list)# ASCII发送else:if self.checkBox_CR_LF.isChecked():input_s += '\r\n'input_s = (input_s).encode('utf-8')# HEX接收显示if self.checkBox_hexReceive.isChecked():out_s = ''for i in range(0, len(input_s)):out_s = out_s + '{:02X}'.format(input_s[i]) + ' 'if self.checkBox_displaySend.isChecked():self.recvTextEdit.insertPlainText(out_s)# ASCII接收显示else:if self.checkBox_displaySend.isChecked():self.recvTextEdit.insertPlainText(input_s.decode('utf-8'))# 接收换行if self.checkBox_AutoLineBreak.isChecked():if self.checkBox_displaySend.isChecked():self.recvTextEdit.insertPlainText('\r\n')# 获取到Text光标textCursor = self.recvTextEdit.textCursor()# 滚动到底部textCursor.movePosition(textCursor.End)# 设置光标到Text中去self.recvTextEdit.setTextCursor(textCursor)# 统计发送字符数量num = self.ser.write(input_s)self.data_num_sended += numself.label_Tx.setText(str(self.data_num_sended))else:pass# 接收数据def data_receive(self):try:num = self.ser.inWaiting()# if num > 0:#     time.sleep(0.1) #100ms#     num = self.ser.inWaiting()  # 延时,再读一次数据,确保数据完整性except:# QMessageBox.critical(self, '串口异常', '串口接收数据异常,请重新连接设备!')# self.port_close()return Noneif num > 0:data = self.ser.read(num)num = len(data)# HEX显示数据if self.checkBox_hexReceive.checkState():# 时间显示if self.checkBox_displayTime.isChecked():self.recvTextEdit.insertPlainText(self.get_datetime())out_s = ''for i in range(0, len(data)):out_s = out_s + '{:02X}'.format(data[i]) + ' 'self.recvTextEdit.insertPlainText(out_s)# 接收换行if self.checkBox_AutoLineBreak.isChecked():self.recvTextEdit.insertPlainText('\r\n')# ASCII显示数据else:try:if self.checkBox_displayTime.isChecked():displayStr = self.get_datetime()displayStr += data.decode('utf-8',"ignore")displayStr = displayStr.replace("\n", "\n" + self.get_datetime())# 接收换行if self.checkBox_AutoLineBreak.isChecked():displayStr += "\r\n"  # 接收换行self.recvTextEdit.insertPlainText(displayStr)else:self.recvTextEdit.insertPlainText(data.decode('utf-8',"ignore"))# 接收换行if self.checkBox_AutoLineBreak.isChecked():self.recvTextEdit.insertPlainText('\r\n')except Exception as e:print("接收数据异常,波特率错误,请重新配置!\n", e)# 获取到text光标textCursor = self.recvTextEdit.textCursor()# 滚动到底部textCursor.movePosition(textCursor.End)# 设置光标到text中去self.recvTextEdit.setTextCursor(textCursor)# 统计接收字符的数量self.data_num_received += numself.label_Rx.setText(str(self.data_num_received))else:pass# 保存日志def savefiles(self):dlg = QFileDialog()filename = self.portNameBox.currentText() + time.strftime("_%Y-%m-%d_%H_%M_%S", time.localtime())filenames = dlg.getSaveFileName(None, "保存日志文件", filename, "Txt files(*.txt)")try:with open(file = filenames[0], mode='w', encoding='utf-8') as file:file.write(self.recvTextEdit.toPlainText())except:#QMessageBox.critical(self, '日志异常', '保存日志文件失败!')pass# 加载日志def openfiles(self):dlg = QFileDialog()filenames = dlg.getOpenFileName(None, "加载日志文件", None, "Txt files(*.txt)")try:with open(file = filenames[0], mode='r', encoding='utf-8') as file:self.sendTextEdit.setPlainText(file.read())except:# QMessageBox.critical(self, '日志异常', '加载日志文件失败!')pass# 打开博客链接def link(self):webbrowser.open('https://blog.csdn.net/santu5234?type=blog')# 清除发送数据显示def send_data_clear(self):self.sendTextEdit.setText("")self.data_num_sended = 0self.label_Tx.setText(str(self.data_num_sended))# 清除接收数据显示def receive_data_clear(self):self.recvTextEdit.setText("")self.data_num_received = 0self.label_Rx.setText(str(self.data_num_received))self.data_num_sended = 0self.label_Tx.setText(str(self.data_num_sended))# 时间格式def get_datetime(self):time_now = datetime.datetime.now()# print(str(time_now)[:-3])time_now = "[" + str(time_now)[:-3] + "] "  # 转为字符串后切片return time_now# RTSdef rts_handle(self):if self.ser.isOpen():if self.checkBox_RTS.isChecked():self.ser.setRTS(1)else:self.ser.setRTS(0)# DTRdef dtr_handle(self):if self.ser.isOpen():if self.checkBox_DTR.isChecked():self.ser.setDTR(1)else:self.ser.setDTR(0)# 主函数
def main():print("Hello, I'm PyQt5_Serial_Debug_Assistant_V1.0")# 1、创建QApplication类的实例对象app = QApplication(sys.argv)# 2、创建一个 PyQt5_Serial 实例对象myMainWindow = PyQt5_Serial()# 3、显示主窗口myMainWindow.show()# 4、进入程序的主循环、并通过exit函数确保主循环安全结束sys.exit(app.exec_())if __name__ == '__main__':main()

四、获取 >> 源码以及Git记录:

PyQt5_Serial_Debug_Assistant_V1.0&V1.1


总结

欢迎下载&更新使用。

【博客8】缤果PyQt5串口调试助手V1.1(初级篇)相关推荐

  1. 【博客4】缤果LabView串口调试助手V1.0 (初级篇)

    目录 超级好用的LabView串口调试助手! 目录 一.软件概要: 二.软件界面: 三.串口功能实现: 3.1 串口初始化 3.2 串口事件处理 3.2.1 打开串口 3.2.2 关闭串口 3.2.3 ...

  2. Windows上 万能的串口调试助手

    之前自己找了很久的串口调试助手,还自己去编写,现在发现了一个非常好用的串口工具:ScriptCommunicator. 这是一个开源软件,功能强大. ScriptCommunicator软件下载地址: ...

  3. C语言写个简单的串口调试助手

    学习单片机或者嵌入式编程常常要用到超级终端–串口调试助手,但有时需要我们自己做一个终端,用来当上位机.最近课设要求我们自己写个终端来处理串口信息,于是乎,接触了一些windows的串口API,做出了一 ...

  4. 使用Qt打造属于自己的串口调试助手

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家. 点击跳转到教程,人工智能编程入门博客 一个专注于嵌入式知识分享,学习路上不迷路的公众号,欢迎关注. 想加技术交流群的 ...

  5. 手把手教你写一个串口调试助手

    硬件攻城狮 2022-05-20 14:05 发表于广东 果果小师弟. 电子信息工程硕士在读,分享单片机.嵌入式linux.物联网等知识,致力于打造最硬核的嵌入式技术公众号. 摘要:前段时间发布了一个 ...

  6. 从零开始,教你写一个串口调试助手

    摘要:相信很多小伙伴都没接触过QT,如果想用QT写一个调试助手,首先是要会一点C++语法.只要能看得懂C++的代码,就能很快的写一个串口调试助手. 下面先推荐两个视频教程,感兴趣的可以看一看! 1.B ...

  7. (串口通信编程) 开源串口调试助手Common (Com Monitor)

    原文地址为: (串口通信编程) 开源串口调试助手Common (Com Monitor) 最新的文档见这里:http://blog.twofei.com/566/ 我写的串口调试助手程序以及源代码. ...

  8. 基于QT的串口调试助手

    大家好,我是KookNut39,在CSDN写文,分享一些自己认为在学习过程中比较重要的东西,致力于帮助初学者入门,希望可以帮助你进步.最近在更新C/C++方面的知识,感兴趣的欢迎关注博主,可以去专栏查 ...

  9. java串口调试助手_基于 QML的 串口调试助手

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_38416696/arti ...

最新文章

  1. react项目部署nginx服务器
  2. 【maven】改造已有项目
  3. python查微信好友是否删除自己_Python + Appium 自动化操作微信查找自己是否被删除...
  4. 【转】Linux将composer的bin目录放到PATH环境变量中
  5. 尽可能地做到无服务器,但不止于此
  6. videojs暂停时显示大按钮_紧急!西安老人扶梯上仰面向后晕倒,这个救命按钮很多人不知道...
  7. node-sass安装报错node-sass@4.12.0 postinstall: `node scripts/build.js`
  8. js 中通过 var 在声明的变量中写方法
  9. Jabber服务器部署
  10. app开发流程:手机软件开发app的6个步骤
  11. Ubuntu安装、更新显卡驱动
  12. 使用腾讯云OCR文字识别
  13. SAP 打印自动导出PDF本地文件(自己做的例子)
  14. Medium之1468.计算税后工资
  15. AutoK3s v0.4.8 发布 与 Harvester 梦幻联动
  16. 如何用html制作彩虹,javascript – 如何使用HTML5画布生成彩虹圈?
  17. [附源码]计算机毕业设计基于Springboot校园运动会管理系统
  18. 经济基础知识(中级)【2】
  19. 联想笔记本桌面计算机不见了,桌面上的图标不见了怎么办,教您桌面上的图标不见了怎么办...
  20. 手游传奇刷元宝_传奇手游如何刷元宝

热门文章

  1. python单片机自动浇花_MicroPython实例之TPYBoardv102自动浇花系统
  2. 记账后,如何查看、修改或删除不需要的收支
  3. 基于树莓派的遥控小车
  4. 黑马程序员Java零基础视频教程(2022最新Java)B站视频学习笔记-Day15-阶段项目(拼图小游戏)(上篇)
  5. 亲测UEFI启动模式的电脑安装Win10和Ubuntu双系统(dell笔记本和hp笔记本)
  6. data单复数一样吗_data和datum谁是单数形式,谁是复数形式?
  7. Kernel panic - not syncing
  8. ZYNQ - 嵌入式Linux开发 -10- ZYNQ启动流程分析
  9. VRF虚拟路由转发实例说明
  10. iPad使用UTM SE装Win7