init commit

Работа с сериальной шиной и макросами
This commit is contained in:
2026-02-10 11:32:38 +03:00
commit c287274588
5 changed files with 1341 additions and 0 deletions

203
mainterm.py Normal file
View 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()