init commit
Работа с сериальной шиной и макросами
This commit is contained in:
203
mainterm.py
Normal file
203
mainterm.py
Normal file
@@ -0,0 +1,203 @@
|
||||
import sys
|
||||
import serial.tools.list_ports
|
||||
from PySide2.QtWidgets import *
|
||||
from PySide2.QtCore import *
|
||||
from PySide2.QtGui import *
|
||||
|
||||
from rawprotocol import RawProtocol, RawProtocolWidget
|
||||
from serialbus import SerialBus, SerialTab
|
||||
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
"""Главное окно приложения"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# Создаем низкоуровневый протокол
|
||||
self.raw_protocol = RawProtocol()
|
||||
# Создаем высокоуровневый протокол, передавая ему low-level
|
||||
self.serial_bus = SerialBus(self.raw_protocol)
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
self.setWindowTitle("Терминал")
|
||||
self.setGeometry(100, 100, 800, 600)
|
||||
|
||||
# Главный виджет и компоновка
|
||||
main_widget = QWidget()
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
# Центральный виджет с вкладками
|
||||
self.tab_widget = QTabWidget()
|
||||
|
||||
# Виджет для RAW протокола (всегда внизу)
|
||||
self.raw_widget = RawProtocolWidget(self.raw_protocol)
|
||||
|
||||
# Вкладка для серийной шины
|
||||
self.serial_tab = SerialTab(self.serial_bus, self.raw_protocol, self.raw_widget)
|
||||
self.tab_widget.addTab(self.serial_tab, "Серийная шина")
|
||||
|
||||
main_layout.addWidget(self.tab_widget)
|
||||
|
||||
main_layout.addWidget(self.raw_widget)
|
||||
|
||||
main_widget.setLayout(main_layout)
|
||||
self.setCentralWidget(main_widget)
|
||||
|
||||
# Создание меню
|
||||
self.create_menu()
|
||||
|
||||
# Создание панели инструментов
|
||||
self.create_toolbar()
|
||||
|
||||
def create_menu(self):
|
||||
menubar = self.menuBar()
|
||||
|
||||
# Меню Файл
|
||||
file_menu = menubar.addMenu("Файл")
|
||||
|
||||
exit_action = QAction("Выход", self)
|
||||
exit_action.triggered.connect(self.close)
|
||||
file_menu.addAction(exit_action)
|
||||
|
||||
# Меню Помощь
|
||||
help_menu = menubar.addMenu("Помощь")
|
||||
|
||||
protocol_action = QAction("Информация о протоколе", self)
|
||||
protocol_action.triggered.connect(self.show_protocol_info)
|
||||
help_menu.addAction(protocol_action)
|
||||
|
||||
def create_toolbar(self):
|
||||
toolbar = self.addToolBar("Подключение")
|
||||
|
||||
# Выбор COM порта
|
||||
toolbar.addWidget(QLabel("COM порт:"))
|
||||
|
||||
self.port_combo = QComboBox()
|
||||
self.port_combo.setMinimumWidth(150)
|
||||
self.refresh_ports()
|
||||
toolbar.addWidget(self.port_combo)
|
||||
|
||||
# Кнопка обновления портов
|
||||
refresh_btn = QToolButton()
|
||||
refresh_btn.setText("⟳")
|
||||
refresh_btn.setToolTip("Обновить список портов")
|
||||
refresh_btn.clicked.connect(self.refresh_ports)
|
||||
toolbar.addWidget(refresh_btn)
|
||||
|
||||
# Кнопка подключения/отключения
|
||||
self.connect_btn = QPushButton("Подключить")
|
||||
self.connect_btn.clicked.connect(self.toggle_connection)
|
||||
toolbar.addWidget(self.connect_btn)
|
||||
|
||||
# Индикатор статуса
|
||||
self.status_label = QLabel("Отключено")
|
||||
self.status_label.setStyleSheet("color: red;")
|
||||
toolbar.addWidget(self.status_label)
|
||||
|
||||
toolbar.addSeparator()
|
||||
|
||||
# Настройки скорости
|
||||
toolbar.addWidget(QLabel("Скорость:"))
|
||||
self.baud_combo = QComboBox()
|
||||
self.baud_combo.addItems(["9600", "19200", "38400", "57600", "115200", "230400", "460800", "921600"])
|
||||
self.baud_combo.setCurrentText("115200")
|
||||
toolbar.addWidget(self.baud_combo)
|
||||
|
||||
def refresh_ports(self):
|
||||
"""Обновление списка доступных COM портов"""
|
||||
self.port_combo.clear()
|
||||
ports = serial.tools.list_ports.comports()
|
||||
for port in ports:
|
||||
self.port_combo.addItem(f"{port.device} - {port.description}")
|
||||
|
||||
if not ports:
|
||||
self.port_combo.addItem("Порты не найдены")
|
||||
|
||||
def toggle_connection(self):
|
||||
"""Подключение/отключение от COM порта"""
|
||||
if self.raw_protocol.is_connected:
|
||||
# Отключение
|
||||
self.raw_protocol.disconnect()
|
||||
self.connect_btn.setText("Подключить")
|
||||
self.status_label.setText("Отключено")
|
||||
self.status_label.setStyleSheet("color: red;")
|
||||
|
||||
# Блокировка элементов управления
|
||||
self.serial_tab.bus_write_btn.setEnabled(False)
|
||||
self.serial_tab.bus_read_btn.setEnabled(False)
|
||||
self.raw_widget.raw_send_btn.setEnabled(False)
|
||||
self.raw_widget.raw_read_btn.setEnabled(False)
|
||||
else:
|
||||
# Подключение
|
||||
port_text = self.port_combo.currentText()
|
||||
if " - " in port_text:
|
||||
port_name = port_text.split(" - ")[0]
|
||||
else:
|
||||
port_name = port_text
|
||||
|
||||
try:
|
||||
baudrate = int(self.baud_combo.currentText())
|
||||
if self.raw_protocol.connect(port_name, baudrate):
|
||||
self.connect_btn.setText("Отключить")
|
||||
self.status_label.setText("Подключено")
|
||||
self.status_label.setStyleSheet("color: green;")
|
||||
|
||||
# Разблокировка элементов управления
|
||||
self.serial_tab.bus_write_btn.setEnabled(True)
|
||||
self.serial_tab.bus_read_btn.setEnabled(True)
|
||||
self.raw_widget.raw_send_btn.setEnabled(True)
|
||||
self.raw_widget.raw_read_btn.setEnabled(True)
|
||||
else:
|
||||
QMessageBox.warning(self, "Ошибка", "Не удалось подключиться к порту")
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Ошибка", f"Ошибка подключения: {e}")
|
||||
|
||||
def show_protocol_info(self):
|
||||
"""Показать информацию о протоколе"""
|
||||
info = """
|
||||
ИНФОРМАЦИЯ О ПРОТОКОЛЕ:
|
||||
|
||||
На основе кода контроллера:
|
||||
|
||||
1. ФОРМАТ СООБЩЕНИЙ:
|
||||
[адрес][команда][данные][CRC16-IBM]
|
||||
|
||||
2. КЛЮЧЕВЫЕ АДРЕСА:
|
||||
- 0x200A: Регистр данных шины (запись)
|
||||
- 0x200B: Регистр управления шиной
|
||||
- 0x200F: Регистр данных шины (чтение)
|
||||
|
||||
3. ПРОТОКОЛ ШИНЫ:
|
||||
ЗАПИСЬ:
|
||||
1. POKE 0x200A <данные>
|
||||
2. POKE 0x200B 0x80A0 | (адрес << 4)
|
||||
|
||||
ЧТЕНИЕ:
|
||||
1. POKE 0x200B 0x00A0 | (адрес << 4)
|
||||
2. PEEK 0x200F
|
||||
|
||||
4. ЧТО НУЖНО УТОЧНИТЬ:
|
||||
- Точные коды команд CMD_RS232_PEEK и CMD_RS232_POKE
|
||||
- Длину полей в сообщениях
|
||||
- Формат ответов от контроллера
|
||||
"""
|
||||
|
||||
QMessageBox.information(self, "Информация о протоколе", info)
|
||||
|
||||
|
||||
def main():
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# Установка стиля
|
||||
app.setStyle("Fusion")
|
||||
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user