串口调试小助手

This commit is contained in:
Irony 2018-11-06 22:50:57 +08:00
parent 23aae36c2a
commit d8301f296a
7 changed files with 640 additions and 0 deletions

View file

@ -6,6 +6,8 @@ encoding//\u5176\u5B83/QRC\u8D44\u6E90\u6587\u4EF6\u4F7F\u7528/qrctest1.py=utf-8
encoding//\u5176\u5B83/QRC\u8D44\u6E90\u6587\u4EF6\u4F7F\u7528/qrctest2.py=utf-8
encoding//\u5176\u5B83/QRC\u8D44\u6E90\u6587\u4EF6\u4F7F\u7528/res_rc.py=utf-8
encoding//\u5176\u5B83/QRC\u8D44\u6E90\u6587\u4EF6\u4F7F\u7528/textread.py=utf-8
encoding//\u5176\u5B83/\u4E32\u53E3\u8C03\u8BD5\u5C0F\u52A9\u624B/UiSerialPort.py=utf-8
encoding//\u5176\u5B83/\u4E32\u53E3\u8C03\u8BD5\u5C0F\u52A9\u624B/\u4E32\u53E3\u8C03\u8BD5\u5C0F\u52A9\u624B.py=utf-8
encoding//\u5176\u5B83/\u4EBA\u8138\u63CF\u70B9\u68C0\u6D4B/OpencvWidget.py=utf-8
encoding//\u5176\u5B83/\u5168\u5C40\u70ED\u952E/HotKey.py=utf-8
encoding//\u5176\u5B83/\u53F3\u4E0B\u89D2\u5F39\u51FA\u6846/WindowNotify.py=utf-8

View file

@ -185,6 +185,7 @@
1. [右下角弹出框](其它/右下角弹出框)
1. [消息提示](其它/消息提示)
1. [字体测试](其它/字体测试)
1. [串口调试小助手](其它/串口调试小助手)
# QQ群

View file

@ -0,0 +1,14 @@
# 串口调试小助手
用`QSerialPort`写了个类似串口调试小助手的工具, 这个类的官方资料: http://doc.qt.io/qt-5/qserialport.html
1. 通过`QSerialPortInfo.availablePorts()` 获取所有可用的串口
1. `QSerialPort.setPortName` 设置串口名
1. `QSerialPort.setBaudRate` 设置波特率
1. `QSerialPort.setParity` 设置校验位
1. `QSerialPort.setDataBits` 设置数据位
1. `QSerialPort.setStopBits` 设置停止位
1. `QSerialPort.setFlowControl` 设置流控制
![截图](ScreenShot/串口调试小助手.gif)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View file

@ -0,0 +1,175 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'UiSerialPort.ui'
#
# Created by: PyQt5 UI code generator 5.10.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_FormSerialPort(object):
def setupUi(self, FormSerialPort):
FormSerialPort.setObjectName("FormSerialPort")
FormSerialPort.resize(721, 597)
FormSerialPort.setStyleSheet("#labelStatus {\n"
" border-radius: 13px;\n"
" background-color: gray;\n"
"}\n"
"#labelStatus[isOn=\"true\"] {\n"
" background-color: green;\n"
"}")
self.gridLayout = QtWidgets.QGridLayout(FormSerialPort)
self.gridLayout.setObjectName("gridLayout")
self.groupBox = QtWidgets.QGroupBox(FormSerialPort)
self.groupBox.setTitle("")
self.groupBox.setObjectName("groupBox")
self.formLayout = QtWidgets.QFormLayout(self.groupBox)
self.formLayout.setLabelAlignment(QtCore.Qt.AlignCenter)
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(self.groupBox)
self.label.setObjectName("label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label)
self.comboBoxPort = QtWidgets.QComboBox(self.groupBox)
self.comboBoxPort.setObjectName("comboBoxPort")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.comboBoxPort)
self.label_2 = QtWidgets.QLabel(self.groupBox)
self.label_2.setObjectName("label_2")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_2)
self.comboBoxBaud = QtWidgets.QComboBox(self.groupBox)
self.comboBoxBaud.setObjectName("comboBoxBaud")
self.comboBoxBaud.addItem("")
self.comboBoxBaud.addItem("")
self.comboBoxBaud.addItem("")
self.comboBoxBaud.addItem("")
self.comboBoxBaud.addItem("")
self.comboBoxBaud.addItem("")
self.comboBoxBaud.addItem("")
self.comboBoxBaud.addItem("")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.comboBoxBaud)
self.label_3 = QtWidgets.QLabel(self.groupBox)
self.label_3.setObjectName("label_3")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_3)
self.comboBoxParity = QtWidgets.QComboBox(self.groupBox)
self.comboBoxParity.setObjectName("comboBoxParity")
self.comboBoxParity.addItem("")
self.comboBoxParity.addItem("")
self.comboBoxParity.addItem("")
self.comboBoxParity.addItem("")
self.comboBoxParity.addItem("")
self.comboBoxParity.addItem("")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.comboBoxParity)
self.label_4 = QtWidgets.QLabel(self.groupBox)
self.label_4.setObjectName("label_4")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_4)
self.comboBoxData = QtWidgets.QComboBox(self.groupBox)
self.comboBoxData.setObjectName("comboBoxData")
self.comboBoxData.addItem("")
self.comboBoxData.addItem("")
self.comboBoxData.addItem("")
self.comboBoxData.addItem("")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.comboBoxData)
self.label_5 = QtWidgets.QLabel(self.groupBox)
self.label_5.setObjectName("label_5")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_5)
self.comboBoxStop = QtWidgets.QComboBox(self.groupBox)
self.comboBoxStop.setObjectName("comboBoxStop")
self.comboBoxStop.addItem("")
self.comboBoxStop.addItem("")
self.comboBoxStop.addItem("")
self.comboBoxStop.addItem("")
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.comboBoxStop)
self.buttonConnect = QtWidgets.QPushButton(self.groupBox)
self.buttonConnect.setObjectName("buttonConnect")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.buttonConnect)
self.labelStatus = QtWidgets.QLabel(self.groupBox)
self.labelStatus.setProperty("isOn", False)
self.labelStatus.setObjectName("labelStatus")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.labelStatus)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.formLayout.setItem(6, QtWidgets.QFormLayout.FieldRole, spacerItem)
self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1)
self.textBrowser = QtWidgets.QTextBrowser(FormSerialPort)
self.textBrowser.setObjectName("textBrowser")
self.gridLayout.addWidget(self.textBrowser, 0, 1, 2, 1)
self.widget = QtWidgets.QWidget(FormSerialPort)
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton_2 = QtWidgets.QPushButton(self.widget)
self.pushButton_2.setObjectName("pushButton_2")
self.verticalLayout.addWidget(self.pushButton_2)
self.checkBoxHexView = QtWidgets.QCheckBox(self.widget)
self.checkBoxHexView.setObjectName("checkBoxHexView")
self.verticalLayout.addWidget(self.checkBoxHexView)
self.gridLayout.addWidget(self.widget, 1, 0, 1, 1)
self.widget_2 = QtWidgets.QWidget(FormSerialPort)
self.widget_2.setObjectName("widget_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget_2)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.buttonSend = QtWidgets.QPushButton(self.widget_2)
self.buttonSend.setObjectName("buttonSend")
self.verticalLayout_2.addWidget(self.buttonSend)
self.checkBoxHexSend = QtWidgets.QCheckBox(self.widget_2)
self.checkBoxHexSend.setObjectName("checkBoxHexSend")
self.verticalLayout_2.addWidget(self.checkBoxHexSend)
self.gridLayout.addWidget(self.widget_2, 2, 0, 1, 1)
self.plainTextEdit = QtWidgets.QPlainTextEdit(FormSerialPort)
self.plainTextEdit.setObjectName("plainTextEdit")
self.gridLayout.addWidget(self.plainTextEdit, 2, 1, 1, 1)
self.gridLayout.setColumnStretch(1, 2)
self.gridLayout.setRowStretch(0, 3)
self.retranslateUi(FormSerialPort)
self.comboBoxBaud.setCurrentIndex(3)
self.comboBoxData.setCurrentIndex(3)
self.pushButton_2.clicked.connect(self.textBrowser.clear)
QtCore.QMetaObject.connectSlotsByName(FormSerialPort)
def retranslateUi(self, FormSerialPort):
_translate = QtCore.QCoreApplication.translate
FormSerialPort.setWindowTitle(_translate("FormSerialPort", "串口调试小助手"))
self.label.setText(_translate("FormSerialPort", "端 口"))
self.label_2.setText(_translate("FormSerialPort", "波特率"))
self.comboBoxBaud.setItemText(0, _translate("FormSerialPort", "1200"))
self.comboBoxBaud.setItemText(1, _translate("FormSerialPort", "2400"))
self.comboBoxBaud.setItemText(2, _translate("FormSerialPort", "4800"))
self.comboBoxBaud.setItemText(3, _translate("FormSerialPort", "9600"))
self.comboBoxBaud.setItemText(4, _translate("FormSerialPort", "19200"))
self.comboBoxBaud.setItemText(5, _translate("FormSerialPort", "38400"))
self.comboBoxBaud.setItemText(6, _translate("FormSerialPort", "57600"))
self.comboBoxBaud.setItemText(7, _translate("FormSerialPort", "115200"))
self.label_3.setText(_translate("FormSerialPort", "校验位"))
self.comboBoxParity.setItemText(0, _translate("FormSerialPort", "No"))
self.comboBoxParity.setItemText(1, _translate("FormSerialPort", "Even"))
self.comboBoxParity.setItemText(2, _translate("FormSerialPort", "Odd"))
self.comboBoxParity.setItemText(3, _translate("FormSerialPort", "Space"))
self.comboBoxParity.setItemText(4, _translate("FormSerialPort", "Mark"))
self.comboBoxParity.setItemText(5, _translate("FormSerialPort", "Unknown"))
self.label_4.setText(_translate("FormSerialPort", "数据位"))
self.comboBoxData.setItemText(0, _translate("FormSerialPort", "5"))
self.comboBoxData.setItemText(1, _translate("FormSerialPort", "6"))
self.comboBoxData.setItemText(2, _translate("FormSerialPort", "7"))
self.comboBoxData.setItemText(3, _translate("FormSerialPort", "8"))
self.label_5.setText(_translate("FormSerialPort", "停止位"))
self.comboBoxStop.setItemText(0, _translate("FormSerialPort", "OneStop"))
self.comboBoxStop.setItemText(1, _translate("FormSerialPort", "OneAndHalfStop"))
self.comboBoxStop.setItemText(2, _translate("FormSerialPort", "TwoStop"))
self.comboBoxStop.setItemText(3, _translate("FormSerialPort", "UnknownStopBits"))
self.buttonConnect.setText(_translate("FormSerialPort", "打开串口"))
self.labelStatus.setText(_translate("FormSerialPort", " "))
self.pushButton_2.setText(_translate("FormSerialPort", "清空接收区"))
self.checkBoxHexView.setText(_translate("FormSerialPort", "十六进制显示"))
self.buttonSend.setText(_translate("FormSerialPort", "手动发送"))
self.checkBoxHexSend.setText(_translate("FormSerialPort", "十六进制发送"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
FormSerialPort = QtWidgets.QWidget()
ui = Ui_FormSerialPort()
ui.setupUi(FormSerialPort)
FormSerialPort.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,305 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FormSerialPort</class>
<widget class="QWidget" name="FormSerialPort">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>721</width>
<height>597</height>
</rect>
</property>
<property name="windowTitle">
<string>串口调试小助手</string>
</property>
<property name="styleSheet">
<string notr="true">#labelStatus {
border-radius: 13px;
background-color: gray;
}
#labelStatus[isOn=&quot;true&quot;] {
background-color: green;
}</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="3,0,0" columnstretch="0,2">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string/>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="labelAlignment">
<set>Qt::AlignCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>端 口</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxPort"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>波特率</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxBaud">
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>1200</string>
</property>
</item>
<item>
<property name="text">
<string>2400</string>
</property>
</item>
<item>
<property name="text">
<string>4800</string>
</property>
</item>
<item>
<property name="text">
<string>9600</string>
</property>
</item>
<item>
<property name="text">
<string>19200</string>
</property>
</item>
<item>
<property name="text">
<string>38400</string>
</property>
</item>
<item>
<property name="text">
<string>57600</string>
</property>
</item>
<item>
<property name="text">
<string>115200</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>校验位</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxParity">
<item>
<property name="text">
<string>No</string>
</property>
</item>
<item>
<property name="text">
<string>Even</string>
</property>
</item>
<item>
<property name="text">
<string>Odd</string>
</property>
</item>
<item>
<property name="text">
<string>Space</string>
</property>
</item>
<item>
<property name="text">
<string>Mark</string>
</property>
</item>
<item>
<property name="text">
<string>Unknown</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>数据位</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboBoxData">
<property name="currentIndex">
<number>3</number>
</property>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
<item>
<property name="text">
<string>8</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>停止位</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="comboBoxStop">
<item>
<property name="text">
<string>OneStop</string>
</property>
</item>
<item>
<property name="text">
<string>OneAndHalfStop</string>
</property>
</item>
<item>
<property name="text">
<string>TwoStop</string>
</property>
</item>
<item>
<property name="text">
<string>UnknownStopBits</string>
</property>
</item>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="buttonConnect">
<property name="text">
<string>打开串口</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelStatus">
<property name="text">
<string> </string>
</property>
<property name="isOn" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" rowspan="2">
<widget class="QTextBrowser" name="textBrowser"/>
</item>
<item row="1" column="0">
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>清空接收区</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxHexView">
<property name="text">
<string>十六进制显示</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QWidget" name="widget_2" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="buttonSend">
<property name="text">
<string>手动发送</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxHexSend">
<property name="text">
<string>十六进制发送</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QPlainTextEdit" name="plainTextEdit"/>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>pushButton_2</sender>
<signal>clicked()</signal>
<receiver>textBrowser</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>136</x>
<y>328</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>236</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,143 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2018年11月6日
@author: Irony
@site: https://pyqt5.com, https://github.com/892768447
@email: 892768447@qq.com
@file: 串口调试小助手
@description:
"""
from PyQt5.QtCore import pyqtSlot, QIODevice, QByteArray
from PyQt5.QtSerialPort import QSerialPortInfo, QSerialPort
from PyQt5.QtWidgets import QWidget
from UiSerialPort import Ui_FormSerialPort # @UnresolvedImport
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = 'Copyright (c) 2018 Irony'
__Version__ = 1.0
class Window(QWidget, Ui_FormSerialPort):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.setupUi(self)
self._serial = QSerialPort(self) # 用于连接串口的对象
self._serial.readyRead.connect(self.onReadyRead) # 绑定数据读取信号
# 首先获取可用的串口列表
self.getAvailablePorts()
@pyqtSlot()
def on_buttonConnect_clicked(self):
# 打开或关闭串口按钮
if self._serial.isOpen():
# 如果串口是打开状态则关闭
self._serial.close()
self.textBrowser.append('串口已关闭')
self.buttonConnect.setText('打开串口')
self.labelStatus.setProperty('isOn', False)
self.labelStatus.style().polish(self.labelStatus) # 刷新样式
return
# 根据配置连接串口
port = self._ports[self.comboBoxPort.currentText()]
# self._serial.setPort(port)
# 根据名字设置串口(也可以用上面的函数)
self._serial.setPortName(port.systemLocation())
# 设置波特率
self._serial.setBaudRate( # 动态获取,类似QSerialPort::Baud9600这样的吧
getattr(QSerialPort, 'Baud' + self.comboBoxBaud.currentText()))
# 设置校验位
self._serial.setParity( # QSerialPort::NoParity
getattr(QSerialPort, self.comboBoxParity.currentText() + 'Parity'))
# 设置数据位
self._serial.setDataBits( # QSerialPort::Data8
getattr(QSerialPort, 'Data' + self.comboBoxData.currentText()))
# 设置停止位
self._serial.setStopBits( # QSerialPort::Data8
getattr(QSerialPort, self.comboBoxStop.currentText()))
# NoFlowControl 没有流程控制
# HardwareControl 硬件流程控制(RTS/CTS)
# SoftwareControl 软件流程控制(XON/XOFF)
# UnknownFlowControl 未知控制
self._serial.setFlowControl(QSerialPort.NoFlowControl)
# 读写方式打开串口
ok = self._serial.open(QIODevice.ReadWrite)
if ok:
self.textBrowser.append('打开串口成功')
self.buttonConnect.setText('关闭串口')
self.labelStatus.setProperty('isOn', True)
self.labelStatus.style().polish(self.labelStatus) # 刷新样式
else:
self.textBrowser.append('打开串口失败')
self.buttonConnect.setText('打开串口')
self.labelStatus.setProperty('isOn', False)
self.labelStatus.style().polish(self.labelStatus) # 刷新样式
@pyqtSlot()
def on_buttonSend_clicked(self):
# 发送消息按钮
if not self._serial.isOpen():
print('串口未连接')
return
text = self.plainTextEdit.toPlainText()
if not text:
return
text = QByteArray(text.encode('gb2312')) # emmm windows 测试的工具貌似是这个编码
if self.checkBoxHexSend.isChecked():
# 如果勾选了hex发送
text = text.toHex()
# 发送数据
print('发送数据:', text)
self._serial.write(text)
def onReadyRead(self):
# 数据接收响应
if self._serial.bytesAvailable():
# 当数据可读取时
# 这里只是简答测试少量数据,如果数据量太多了此处readAll其实并没有读完
# 需要自行设置粘包协议
data = self._serial.readAll()
if self.checkBoxHexView.isChecked():
# 如果勾选了hex显示
data = data.toHex()
data = data.data()
# 解码显示(中文啥的)
try:
self.textBrowser.append('我收到了: ' + data.decode('gb2312'))
except:
# 解码失败
self.textBrowser.append('我收到了: ' + repr(data))
def getAvailablePorts(self):
# 获取可用的串口
self._ports = {} # 用于保存串口的信息
infos = QSerialPortInfo.availablePorts()
infos.reverse() # 逆序
for info in infos:
# 通过串口名字-->关联串口变量
self._ports[info.portName()] = info
self.comboBoxPort.addItem(info.portName())
def closeEvent(self, event):
if self._serial.isOpen():
self._serial.close()
super(Window, self).closeEvent(event)
if __name__ == '__main__':
import sys
import cgitb
sys.excepthook = cgitb.enable(1, None, 5, '')
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())