【开源】一款PyQT+Pyserial开发的串口调试工具

【开源】PyQT+Pyserial开发的串口调试工具

串口调试工具是我们做嵌入式开发常用的工具,市面上已经有很多串口调试工具了,博主写这款串口调试工具一方面是为了学习Python PyQT Pyserial 相关的知识,另一方面是也是可以为后续基于此设计更多的串口自动化工具。所以本文会详细介绍如何使用PyQT+Pyserial实现一款串口调试工具。

1. 安装开发环境

首先安装Python 3 环境,然后使用pip安装pyqt5 pyserial pyside2等需要的库

pip install pyqt5 pyserial PySide2

2. 设计UI

开发环境安装完成后,就可以进行GUI设计了,首先进入PySide2库的本地安装路径下

在这里插入图片描述

双击designer.exe文件,打开QT设计师

在这里插入图片描述

选择Main Window 或者Widget都可以。

接下来绘制QT界面,这部分不过多介绍,就是QT的常规使用。下面附上我的QT界面ui文件

https://download.csdn.net/download/hesuping/86750748

完成ui文件后,需要使用pyuic5命令将ui文件转化成python文件,这样才可以被python调用,转化的方式也很简单。PyQt 5安装成功后,pyuic5命令默认安装在Python安装包目录Scripts文件下, 执行如下命令,就可以将uart_ui.ui文件妆花成python文件uart_ui.py。

pyuic5 -o uart_ui.py uart_ui.ui

3. 串口逻辑实现

3.1 实例化类

使用面向对象思想,创建一个串口的类,并进行实例化。

if __name__ == '__main__':

	app = QApplication(sys.argv)

	ex = SerialTool()

	ex.show()

	sys.exit(app.exec_())

3.2 初始化程序

在SerialTool 类中的初始化中,分别执行初始化UI界面,刷新并初始化串口, 关键UI事件等操作,并创建定时发送的定时器。

	def __init__(self):
		super().__init__()

		self.setupUi(self)
		self.refreshPort()
		tmp = open('logo.png', 'wb')
		tmp.write(base64.b64decode(img))
		tmp.close()

		self.setWindowIcon(QIcon('logo.png'))
		os.remove('logo.png')

		self.InitUIEvent()
		self.initCOM()

		self.signalRecieve.connect(self.uart_receive_display)

		# #创建定时发送定时器
		self.timer_send= QTimer(self)
		self.timer_send.timeout.connect(self.UartSend)

3.3 串口刷新程序

	def refreshPort(self):
		self.com_list = []
		port_list = list(serial.tools.list_ports.comports())
		self.Combo_COM.clear()
		if len(port_list) > 0:
			for port_com in port_list:
				port_serial = list(port_com)[0]
				self.Combo_COM.addItem(port_serial)
				self.com_list.append(port_serial)
		else:
			self.Combo_COM.addItem('')

3.4 串口初始化程序

	def initCOM(self):
		self.l_serial = serial.Serial()
		if(len(self.com_list)):
			self.l_serial.port = self.com_list[0]
		self.l_serial.baudrate = int(self.Combo_Baudrate.currentText())
		self.l_serial.bytesize = int(self.Combo_Data_bit.currentText())
		self.l_serial.stopbits = int(self.Combo_Stop_bit.currentText())
		self.l_serial.parity = self.Combo_Parity.currentText()
		# serial.PARITY_NONE
		self.l_serial.timeout = 0.2

3.5 打开/关闭串口程序

	def StartComActivated(self):

		if self.l_serial.isOpen():
			self.timer_send.stop()
			# self.thread_read.join()
			self.l_serial.close()
			self.Button_Onoff_com.setText("打开串口")

			self.Combo_COM.setEnabled(True)
			self.Combo_Baudrate.setEnabled(True)
			self.Combo_Data_bit.setEnabled(True)
			self.Combo_Stop_bit.setEnabled(True)
			self.Combo_Parity.setEnabled(True)
		else:
			self.l_serial.open()
			self.Button_Onoff_com.setText("关闭串口")

			self.Combo_COM.setEnabled(False)
			self.Combo_Baudrate.setEnabled(False)
			self.Combo_Data_bit.setEnabled(False)
			self.Combo_Stop_bit.setEnabled(False)
			self.Combo_Parity.setEnabled(False)

			self.thread_read = None
			self.thread_read = threading.Thread(target=self.UartRead)
			self.thread_read.setDaemon(True)
			self.thread_read.start()

3.6 串口读取程序

	def UartRead(self):
		while self.l_serial.isOpen():
			num = self.l_serial.inWaiting()
			if num: 
				self.data = self.l_serial.read(num)
				if self.Box_Display_hex.checkState():        # 16进制接收
					hex_data=''
					for i in range(0, len(self.data)):
						hex_data = hex_data + '{:02X}'.format(self.data[i]) + ' '
					# self.Textbrowser_Receive.append(hex_data.strip())
					self.signalRecieve.emit(hex_data)
				else :
					# self.Textbrowser_Receive.append(data.decode().strip())
					# self.Textbrowser_Receive.insertPlainText(data.decode('utf-8',"ignore"))
					self.signalRecieve.emit(self.data)

			time.sleep(0.1)

3.7 串口显示程序

	def uart_receive_display(self,obj):
		now_time = datetime.now()  # 获取当前时间
		new_time = now_time.strftime('[%H:%M:%S:%f]')
		if self.Box_Display_hex.checkState():         # hex显示
			if(self.Box_Display_time.checkState()):   # 显示时间
				self.recv_data = '\r\n'+ new_time + obj.strip()
			else:
				self.recv_data = obj.strip()
			if self.Box_Display_send.checkState():    # 显示发送
				self.recv_data = '\r\n' + '[Receive]:' + self.recv_data

			if self.Box_Auto_wrap.checkState():
				self.Textbrowser_Receive.append(self.recv_data)
			else:
				self.Textbrowser_Receive.insertPlainText(self.recv_data)
				# self.Textbrowser_Receive.append(self.recv_data)
		else:
			if self.Box_Display_time.checkState():
				self.recv_data = '\r\n' + new_time + obj.decode('utf-8',"ignore")
			else:
				self.recv_data = obj.decode('utf-8',"ignore")

			if self.Box_Display_send.checkState():
				self.recv_data = '\r\n' + '[Receive]:' + self.recv_data

			if self.Box_Auto_wrap.checkState():
				self.Textbrowser_Receive.append(self.recv_data)
			else:
				self.Textbrowser_Receive.insertPlainText(self.recv_data)

		self.Textbrowser_Receive.moveCursor(self.Textbrowser_Receive.textCursor().End)  #文本框显示到底部

3.8 串口发送程序

	def UartSend(self):
		InputStr = self.TextEdit_Send.toPlainText()
		if InputStr == "":
			return

		if self.Box_Display_send.checkState():
			self.recv_data = '[Send]:'+ InputStr
			self.Textbrowser_Receive.append(self.recv_data)

		if self.Box_Hex_send.checkState():
			#发送十六进制数据
			InputStr = InputStr.strip() #删除前后的空格
			send_list=[]
			while InputStr != '':
				try:
					num = int(InputStr[0:2], 16)
					
				except ValueError:
					QMessageBox.critical(self, 'pycom','请输入十六进制数据,以空格分开!')
					return None
				
				InputStr = InputStr[2:]
				InputStr = InputStr.strip()
				
				#添加到发送列表中
				send_list.append(num)
			InputStr = bytes(send_list)

			self.l_serial.write(InputStr)
		else :
			self.l_serial.write(InputStr.encode())

4. 串口工具

完成后的串口工具如下图:

在这里插入图片描述

界面中显示的功能都已经完成,其他的功能还在陆续开发中。 欢迎大家关注及提意见。 目前该工具功能还很基础和粗糙,但是很适合用于学习。工具的全部源码我也已经放在了github中,欢迎STAR及留言。

github地址: https://github.com/HESUPING/IOT_COM

安装包:https://github.com/HESUPING/IOT_COM/releases/download/V1.0/IOT_COM.exe

  • 13
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
以下是使用Python3、PyQT5和Pyserial实现串口工具的方法: 1. 安装PyserialPyQT5库 在终端或命令行中输入以下命令来安装PyserialPyQT5: ``` pip install pyserial pip install pyqt5 ``` 2. 创建GUI界面 使用PyQT5创建一个简单的GUI界面。在这个界面中,你需要添加一个下拉菜单来选择串口、一个文本框来显示串口数据和一些按钮来打开/关闭串口和发送数据。 下面是一个简单的PyQT5串口工具界面: ```python import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QComboBox, QTextEdit, QPushButton, QHBoxLayout, QVBoxLayout, QWidget class SerialTool(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): # 设置窗口大小 self.setGeometry(100, 100, 400, 300) # 设置窗口标题 self.setWindowTitle('Serial Tool') # 添加下拉菜单 self.portComboBox = QComboBox(self) self.portComboBox.move(10, 10) self.portComboBox.resize(180, 30) # 添加文本框 self.textEdit = QTextEdit(self) self.textEdit.move(10, 50) self.textEdit.resize(380, 180) # 添加按钮 self.openButton = QPushButton('Open', self) self.openButton.move(10, 240) self.openButton.resize(80, 30) self.closeButton = QPushButton('Close', self) self.closeButton.move(100, 240) self.closeButton.resize(80, 30) self.sendButton = QPushButton('Send', self) self.sendButton.move(190, 240) self.sendButton.resize(80, 30) self.clearButton = QPushButton('Clear', self) self.clearButton.move(280, 240) self.clearButton.resize(80, 30) # 添加布局管理器 hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(self.openButton) hbox.addWidget(self.closeButton) hbox.addWidget(self.sendButton) hbox.addWidget(self.clearButton) vbox = QVBoxLayout() vbox.addWidget(self.portComboBox) vbox.addLayout(hbox) widget = QWidget() widget.setLayout(vbox) self.setCentralWidget(widget) ``` 3. 实现串口操作 使用Pyserial库来创建串口连接。在打开串口之前,你需要获取可用的串口列表并将它们添加到下拉菜单中。在发送数据之前,你需要从文本框中获取数据。 下面是一个简单的Pyserial串口操作代码: ```python import serial class SerialTool(QMainWindow): def __init__(self): super().__init__() self.initUI() self.initSerial() def initSerial(self): # 获取可用串口列表 ports = serial.tools.list_ports.comports() # 将可用串口添加到下拉菜单中 for port in ports: self.portComboBox.addItem(port.device) # 创建串口连接 self.ser = serial.Serial() def openSerial(self): # 设置串口参数 port = self.portComboBox.currentText() baudrate = 9600 bytesize = serial.EIGHTBITS parity = serial.PARITY_NONE stopbits = serial.STOPBITS_ONE self.ser.port = port self.ser.baudrate = baudrate self.ser.bytesize = bytesize self.ser.parity = parity self.ser.stopbits = stopbits # 打开串口连接 try: self.ser.open() self.ser.flushInput() self.ser.flushOutput() self.textEdit.append('Serial port is open.') except Exception as e: self.textEdit.append(str(e)) def closeSerial(self): # 关闭串口连接 try: self.ser.close() self.textEdit.append('Serial port is closed.') except Exception as e: self.textEdit.append(str(e)) def sendSerial(self): # 发送数据 data = self.textEdit.toPlainText() try: self.ser.write(data.encode()) self.textEdit.clear() self.textEdit.append('Data is sent: ' + data) except Exception as e: self.textEdit.append(str(e)) ``` 4. 运行程序 将GUI界面和串口操作代码组合起来,并在主函数中运行程序。 下面是一个完整的PyQT5串口工具代码: ```python import sys import serial from PyQt5.QtWidgets import QApplication, QMainWindow, QComboBox, QTextEdit, QPushButton, QHBoxLayout, QVBoxLayout, QWidget class SerialTool(QMainWindow): def __init__(self): super().__init__() self.initUI() self.initSerial() def initUI(self): # 设置窗口大小 self.setGeometry(100, 100, 400, 300) # 设置窗口标题 self.setWindowTitle('Serial Tool') # 添加下拉菜单 self.portComboBox = QComboBox(self) self.portComboBox.move(10, 10) self.portComboBox.resize(180, 30) # 添加文本框 self.textEdit = QTextEdit(self) self.textEdit.move(10, 50) self.textEdit.resize(380, 180) # 添加按钮 self.openButton = QPushButton('Open', self) self.openButton.move(10, 240) self.openButton.resize(80, 30) self.closeButton = QPushButton('Close', self) self.closeButton.move(100, 240) self.closeButton.resize(80, 30) self.sendButton = QPushButton('Send', self) self.sendButton.move(190, 240) self.sendButton.resize(80, 30) self.clearButton = QPushButton('Clear', self) self.clearButton.move(280, 240) self.clearButton.resize(80, 30) # 添加布局管理器 hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(self.openButton) hbox.addWidget(self.closeButton) hbox.addWidget(self.sendButton) hbox.addWidget(self.clearButton) vbox = QVBoxLayout() vbox.addWidget(self.portComboBox) vbox.addLayout(hbox) widget = QWidget() widget.setLayout(vbox) self.setCentralWidget(widget) # 绑定按钮事件 self.openButton.clicked.connect(self.openSerial) self.closeButton.clicked.connect(self.closeSerial) self.sendButton.clicked.connect(self.sendSerial) self.clearButton.clicked.connect(self.textEdit.clear) def initSerial(self): # 获取可用串口列表 ports = serial.tools.list_ports.comports() # 将可用串口添加到下拉菜单中 for port in ports: self.portComboBox.addItem(port.device) # 创建串口连接 self.ser = serial.Serial() def openSerial(self): # 设置串口参数 port = self.portComboBox.currentText() baudrate = 9600 bytesize = serial.EIGHTBITS parity = serial.PARITY_NONE stopbits = serial.STOPBITS_ONE self.ser.port = port self.ser.baudrate = baudrate self.ser.bytesize = bytesize self.ser.parity = parity self.ser.stopbits = stopbits # 打开串口连接 try: self.ser.open() self.ser.flushInput() self.ser.flushOutput() self.textEdit.append('Serial port is open.') except Exception as e: self.textEdit.append(str(e)) def closeSerial(self): # 关闭串口连接 try: self.ser.close() self.textEdit.append('Serial port is closed.') except Exception as e: self.textEdit.append(str(e)) def sendSerial(self): # 发送数据 data = self.textEdit.toPlainText() try: self.ser.write(data.encode()) self.textEdit.clear() self.textEdit.append('Data is sent: ' + data) except Exception as e: self.textEdit.append(str(e)) if __name__ == '__main__': app = QApplication(sys.argv) serialTool = SerialTool() serialTool.show() sys.exit(app.exec_()) ``` 运行程序后,你应该可以打开串口并发送数据了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网布道师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值