目录
一、软件界面
如图所示,主要由串口设置、显示设置 、发送区、接收区四部分组成:
二、各部分详情
1、串口设置
设置串口、波特率、数据位 、停止位、数据位、停止位、校验位:
def SerialSetting(self):
self.GroupBox_SerialSetting = QGroupBox("串口设置")
self.FormLayout_SerialSetting = QFormLayout()
self.ComboBox_SerialPort = MyComboBox()
self.ComboBox_BaudRate = QComboBox()
self.ComboBox_BaudRate.addItems(['1200', '2400', '4800', '9600', '19200', '38400', '57600'])
self.ComboBox_BaudRate.setCurrentText('9600')
self.ComboBox_DataBytes = QComboBox()
self.ComboBox_DataBytes.addItems(['8', '7', '6', '5'])
self.ComboBox_StopBits = QComboBox()
self.ComboBox_StopBits.addItems(['1', '1.5','2'])
self.ComboBox_Parity = QComboBox()
self.ComboBox_Parity.addItems(['None', 'Even', 'Odd'])
self.FormLayout_SerialSetting.addRow('串口选择:', self.ComboBox_SerialPort)
self.FormLayout_SerialSetting.addRow('波特率:', self.ComboBox_BaudRate)
self.FormLayout_SerialSetting.addRow('数据位:', self.ComboBox_DataBytes)
self.FormLayout_SerialSetting.addRow('停止位:', self.ComboBox_StopBits)
self.FormLayout_SerialSetting.addRow('校验位:', self.ComboBox_Parity)
self.PushButton_OpenCloseSerial = QPushButton("打开串口")
self.PushButton_OpenCloseSerial.setStyleSheet("background-color: white; color: black;")
self.PushButton_OpenCloseSerial.setCheckable(True) # 设置按钮为切换按钮
self.PushButton_OpenCloseSerial.clicked.connect(self.ToggleSerialPort)
self.FormLayout_SerialSetting.addRow(self.PushButton_OpenCloseSerial)
self.FormLayout_SerialSetting.setSpacing(15)
self.GroupBox_SerialSetting.setLayout(self.FormLayout_SerialSetting)
self.ComboBox_SerialPort.clicked.connect(self.DetectSerialPort)
return self.GroupBox_SerialSetting
串口设置函数,用于按照下拉框所选栏目打开或关闭串口:
def ToggleSerialPort(self):
if self.PushButton_OpenCloseSerial.isChecked():
try:
# 打开串口
port_name = self.ComboBox_SerialPort.currentText().split()[0] # 获取选中的串口名称
baud_rate = int(self.ComboBox_BaudRate.currentText())
data_bits_str = self.ComboBox_DataBytes.currentText()
stop_bits_str = self.ComboBox_StopBits.currentText()
parity_str = self.ComboBox_Parity.currentText()
self.oneByteTime = 1 / (float(baud_rate) / (float(data_bits_str) + 2 + float(stop_bits_str)))
# 数据位映射
data_bits_mapping = {
'8': QSerialPort.Data8,
'7': QSerialPort.Data7,
'6': QSerialPort.Data6,
'5': QSerialPort.Data5
}
data_bits = data_bits_mapping.get(data_bits_str, QSerialPort.Data8)
# 停止位映射
stop_bits_mapping = {
'1': QSerialPort.OneStop,
'1.5': QSerialPort.OneAndHalfStop,
'2': QSerialPort.TwoStop
}
stop_bits = stop_bits_mapping.get(stop_bits_str, QSerialPort.OneStop)
# 奇偶校验位映射
parity_mapping = {
'None': QSerialPort.NoParity,
'Even': QSerialPort.EvenParity,
'Odd': QSerialPort.OddParity
}
parity = parity_mapping.get(parity_str, QSerialPort.NoParity)
self.SerialPort.setPortName(port_name)
self.SerialPort.setBaudRate(baud_rate)
self.SerialPort.setDataBits(data_bits)
self.SerialPort.setStopBits(stop_bits)
self.SerialPort.setParity(parity)
if self.SerialPort.open(QSerialPort.ReadWrite):
print("串口打开成功")
self.ComboBox_SerialPort.setEnabled(False)
self.ComboBox_BaudRate.setEnabled(False)
self.ComboBox_DataBytes.setEnabled(False)
self.ComboBox_StopBits.setEnabled(False)
self.ComboBox_Parity.setEnabled(False)
self.Thread.start()
self.SerialPortThread.start()
self.PushButton_OpenCloseSerial.setText("关闭串口")
self.PushButton_OpenCloseSerial.setStyleSheet("background-color: red; color: black;")
else:
print("无法打开串口")
QMessageBox.critical(self, "错误", "无法打开串口")
except Exception as e:
QMessageBox.critical(self, "错误", "请选择串口")
else:
# 关闭串口
self.SerialPort.close()
self.ComboBox_SerialPort.setEnabled(True)
self.ComboBox_BaudRate.setEnabled(True)
self.ComboBox_DataBytes.setEnabled(True)
self.ComboBox_StopBits.setEnabled(True)
self.ComboBox_Parity.setEnabled(True)
self.SerialPortThread.stop()
self.Thread.quit()
self.PushButton_OpenCloseSerial.setText("打开串口")
self.PushButton_OpenCloseSerial.setStyleSheet("background-color: white; color: black;")
2、显示设置
包含对发送区和接收区字符类型的选择以及对清空:
def DisplaySetting(self):
self.GroupBox_DisplaySetting = QGroupBox("显示设置")
self.HBOXLayout_DisplaySetting = QHBoxLayout()
self.VBOXLayout_DisplaySetting = QVBoxLayout()
self.CheckBox_Hex = QCheckBox("HEX")
self.CheckBox_ASCII=QCheckBox("ASCII")
self.CheckBox_Hex.setChecked(True)
self.CheckBox_Hex.toggled.connect(lambda: self.CheckBox_ASCII.setChecked(not self.CheckBox_Hex.isChecked()))
self.CheckBox_ASCII.toggled.connect(lambda: self.CheckBox_Hex.setChecked(not self.CheckBox_ASCII.isChecked()))
self.PushButton_ClearReceive = QPushButton("清空显示区")
self.PushButton_ClearReceive.setObjectName("PushButton_ClearReceive")
self.PushButton_ClearReceive.clicked.connect(self.TextBrowser_Receive.clear)
self.HBOXLayout_DisplaySetting.addWidget(self.CheckBox_Hex)
self.HBOXLayout_DisplaySetting.addWidget(self.CheckBox_ASCII)
self.VBOXLayout_DisplaySetting.addLayout(self.HBOXLayout_DisplaySetting)
self.VBOXLayout_DisplaySetting.addWidget(self.PushButton_ClearReceive)
self.GroupBox_DisplaySetting.setLayout(self.VBOXLayout_DisplaySetting)
return self.GroupBox_DisplaySetting
3、发送区设置
def SendRegion(self):
self.GroupBox_SendRegion = QGroupBox("发送区")
self.VBoxLayout_SendRegion = QVBoxLayout()
self.HBOXLayout_SendRegion = QHBoxLayout()
self.TextEdit_Send = QTextEdit()
self.ToolButton_Send=QToolButton()
self.ToolButton_Send.setIcon(QIcon('icons\send.png'))
self.ToolButton_Send.clicked.connect(self.SendDataProcess)
self.ToolButton_Clear=QToolButton()
self.ToolButton_Clear.setIcon(QIcon('icons\clear.png'))
self.CheckBox_LineFeed=QCheckBox("回车换行")
self.VBox=QVBoxLayout()
self.ToolButton_Clear.clicked.connect(self.TextEdit_Send.clear)
self.VBoxLayout_SendRegion.addWidget(self.CheckBox_LineFeed)
self.VBoxLayout_SendRegion.addWidget(self.ToolButton_Clear)
self.VBoxLayout_SendRegion.addWidget(self.ToolButton_Send)
self.HBOXLayout_SendRegion.addWidget(self.TextEdit_Send)
self.HBOXLayout_SendRegion.addLayout(self.VBoxLayout_SendRegion)
self.GroupBox_SendRegion.setLayout(self.HBOXLayout_SendRegion)
self.GroupBox_SendRegion.setFixedHeight(200)
return self.GroupBox_SendRegion
发送设置函数,用于处理数据发送:
def SendDataProcess(self):
if self.SerialPort.isOpen():
data = self.TextEdit_Send.toPlainText()
if self.CheckBox_LineFeed.isChecked():
data += '\r\n'
try:
process_dict = {
True: lambda data: bytes.fromhex(('0' + data.replace(' ', '')) if len(data.replace(' ', '')) % 2 != 0 else data.replace(' ', '')) if self.CheckBox_Hex.isChecked() else None,
False: lambda data: bytes(data, 'utf-8') if self.CheckBox_ASCII.isChecked() else None
}
data = process_dict[True](data) if self.CheckBox_Hex.isChecked() else process_dict[False](data)
self.SerialPort.write(data)
format_dict = {
True: lambda data: ' '.join([f'{byte:02X}' for byte in bytes(data)]) if self.CheckBox_Hex.isChecked() else None,
False: lambda data: str(data, 'utf-8', errors='ignore') if self.CheckBox_ASCII.isChecked() else None
}
data_str = format_dict[True](data) if self.CheckBox_Hex.isChecked() else format_dict[False](data)
self.TextBrowser_Receive.append(f"发送数据:{data_str}")
except Exception as e:
QMessageBox.critical(self, "错误", "包含非16进制数,发送失败")
4、接收区设置
def ReceiveDataProcess(self):
if self.SerialPort.bytesAvailable():
data = self.SerialPort.readAll()
try:
if self.CheckBox_Hex.isChecked():
data_str = ' '.join([f'{byte:02X}' for byte in bytes(data.data())])
elif self.CheckBox_ASCII.isChecked():
data_str = str(data.data(), 'utf-8', errors='ignore')
else:
data_str = ' '.join([f'{byte:02X}' for byte in bytes(data.data())])
self.TextBrowser_Receive.append(f"接收数据:{data_str}")
except Exception as e:
print("Error:", e)
else:
pass
5、各部分统一
self.SerialPort=QSerialPort()
self.SerialPortThread = SerialPortThread()
self.Thread = QThread()
self.SerialPortThread.moveToThread(self.Thread)
self.SerialPortThread.Receive.connect(self.ReceiveDataProcess)
self.GridLayout = QGridLayout()
self.GridLayout.addWidget(self.SerialSetting(),0, 0, 1 ,1)
self.GridLayout.addWidget(self.DisplaySetting(), 1, 0, 1, 1)
self.GridLayout.addWidget(self.TextBrowser_Receive, 0, 1, 2, 2)
self.GridLayout.addWidget(self.SendRegion(), 2, 0, 1, 3)
self.setLayout(self.GridLayout)
标签:CheckBox,组手,ComboBox,self,SerialPort,PySide6,串口,data
From: https://blog.csdn.net/qq_62113402/article/details/141608489