[Открытый исходный код] Инструмент последовательной отладки, разработанный PyQT+Pyserial.
Инструменты последовательной отладки — это широко используемые инструменты для разработки встраиваемых систем. На рынке представлено множество инструментов последовательной отладки. Блогер написал этот инструмент последовательной отладки, с одной стороны, для изучения знаний, связанных с Python PyQT Pyserial, а с другой стороны, его также можно использовать. В будущем на основе этого мы разработаем больше инструментов автоматизации последовательных портов. Поэтому в этой статье будет подробно описано, как использовать PyQT+Pyserial для реализации инструмента отладки последовательного порта.
Сначала установите среду Python 3, а затем используйте pip для установки необходимых библиотек, таких как pyqt5, pyserial pyside2.
pip install pyqt5 pyserial PySide2
После установки среды разработки вы можете приступить к разработке графического интерфейса. Сначала введите локальный путь установки библиотеки PySide2.
Вставьте сюда описание изображения
Дважды щелкните файл Designer.exe, чтобы открыть QT Designer.
Вставьте сюда описание изображения
Вы можете выбрать главное окно или виджет.
Далее нарисуйте интерфейс QT. Эта часть не будет представляться слишком подробно, но это обычное использование QT. Ниже прикреплен мой файл пользовательского интерфейса интерфейса QT.
https://download.csdn.net/download/hesuping/86750748
После завершения создания файла пользовательского интерфейса вам нужно использовать команду pyuic5, чтобы преобразовать файл пользовательского интерфейса в файл Python, чтобы его можно было вызывать из Python. Метод преобразования также очень прост. После успешной установки PyQt 5 команда pyuic5 по умолчанию устанавливается в файл Scripts в каталоге установочного пакета Python. Выполните следующую команду, чтобы преобразовать файл uart_ui.ui в файл Python uart_ui.py.
pyuic5 -o uart_ui.py uart_ui.ui
Используя объектно-ориентированное мышление, создайте класс последовательного порта и создайте его экземпляр.
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = SerialTool()
ex.show()
sys.exit(app.exec_())
При инициализации в классе SerialTool выполните такие операции, как инициализация интерфейса пользовательского интерфейса, обновление и инициализация последовательного порта, ключевые события пользовательского интерфейса и т. д., а также создайте таймер для запланированной передачи.
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)
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('')
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
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()
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(): # Получить в шестнадцатеричном формате
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)
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(): # шестнадцатеричный дисплей
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) #Текстовое поле отображается внизу
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())
Готовый инструмент последовательного порта показан ниже:
Вставьте сюда описание изображения
Все функции, отображаемые в интерфейсе, реализованы, остальные функции еще находятся в стадии разработки. В настоящее время функции этого инструмента очень просты и грубы, но он очень подходит для обучения.
адрес github: https://github.com/HESUPING/IOT_COM
Установочный пакет: https://github.com/HESUPING/IOT_COM/releases/download/V1.0/IOT_COM.exe.