From 962596f6aca2e0b57b245ebbd8dbb259c14ec240 Mon Sep 17 00:00:00 2001 From: lipengpeng Date: Mon, 11 Aug 2025 14:47:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=E5=AF=84=E5=AD=98=E5=99=A8=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E7=8E=B0=E5=9C=A8=E5=8F=AA=E4=BC=9A=E8=AF=BB=E5=8F=96=E9=9C=80?= =?UTF-8?q?=E8=A6=81=E7=9A=84=E5=AF=84=E5=AD=98=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- editor.pro.user | 2 +- mainwindow.cpp | 2 +- modbusmanager.cpp | 88 +++++++++++++++++++++++++++++++++++++++++----- modbusmanager.h | 4 +-- mygraphicsview.cpp | 25 +++++++++++++ mygraphicsview.h | 4 +-- 6 files changed, 110 insertions(+), 15 deletions(-) diff --git a/editor.pro.user b/editor.pro.user index fefdc6a..56d38d9 100644 --- a/editor.pro.user +++ b/editor.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/mainwindow.cpp b/mainwindow.cpp index 91cc135..bf1556e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -444,7 +444,7 @@ void MainWindow::saveProject() void MainWindow::connection() { modbusManager->connectToDevice("COM1",QSerialPort::BaudRate(9600),QSerialPort::DataBits(8),QSerialPort::EvenParity,QSerialPort::StopBits(1)); - modbusManager->startSimulation(2000); + modbusManager->startSimulation(1000); } void MainWindow::disconnection() diff --git a/modbusmanager.cpp b/modbusmanager.cpp index 9306dce..3b0ba79 100644 --- a/modbusmanager.cpp +++ b/modbusmanager.cpp @@ -65,26 +65,96 @@ void ModbusManager::stopSimulation() pollTimer->stop(); } +//void ModbusManager::readRegisters() +//{ +// if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState) +// return; + +// // 读取所有D寄存器 (保持寄存器) +// readRegisterGroup(QModbusDataUnit::HoldingRegisters, 0, 4000); + +// // 读取所有M寄存器 (线圈) +// readRegisterGroup(QModbusDataUnit::Coils, 0, 4000); +//} + +//void ModbusManager::readRegisterGroup(QModbusDataUnit::RegisterType type, int startAddr, int count) +//{ +// const int MAX_REG_PER_REQUEST = 125; // Modbus RTU限制 + +// for (int addr = startAddr; addr < count; addr += MAX_REG_PER_REQUEST) { +// int readCount = qMin(MAX_REG_PER_REQUEST, count - addr); + +// QModbusDataUnit unit(type, addr, readCount); + +// if (auto *reply = modbusDevice->sendReadRequest(unit, slaveAddress)) { +// QString regType = (type == QModbusDataUnit::HoldingRegisters) ? "D" : "M"; +// pendingRequests[reply] = regType; +// connect(reply, &QModbusReply::finished, this, &ModbusManager::processModbusReply); +// } +// } +//} + void ModbusManager::readRegisters() { if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState) return; - // 读取所有D寄存器 (保持寄存器) - readRegisterGroup(QModbusDataUnit::HoldingRegisters, 0, 4000); + // 获取所有已注册的寄存器ID + QStringList regIds = registerManager->getAllRegisteredRegisters(); + QMap> regMap; // 按类型分组存储地址 + + // 分组寄存器地址 + for (const QString &id : regIds) { + if (id.startsWith("D") || id.startsWith("M")) { + bool ok; + int addr = id.mid(1).toInt(&ok); + if (ok && addr >= 0 && addr <= 4000) { + regMap[id.left(1)].insert(addr); + } + } + } + + // 读取D寄存器 (保持寄存器) + if (regMap.contains("D")) { + readRegisterGroup(QModbusDataUnit::HoldingRegisters, regMap["D"].values()); + } - // 读取所有M寄存器 (线圈) - readRegisterGroup(QModbusDataUnit::Coils, 0, 4000); + // 读取M寄存器 (线圈) + if (regMap.contains("M")) { + readRegisterGroup(QModbusDataUnit::Coils, regMap["M"].values()); + } } -void ModbusManager::readRegisterGroup(QModbusDataUnit::RegisterType type, int startAddr, int count) +void ModbusManager::readRegisterGroup(QModbusDataUnit::RegisterType type, const QList &addresses) { - const int MAX_REG_PER_REQUEST = 125; // Modbus RTU限制 + if (addresses.isEmpty()) return; + + QList sortedAddrs = addresses; + std::sort(sortedAddrs.begin(), sortedAddrs.end()); + + // 合并连续地址范围 + int start = sortedAddrs.first(); + int end = start; + + for (int i = 1; i < sortedAddrs.size(); i++) { + if (sortedAddrs[i] == end + 1) { + end = sortedAddrs[i]; + } else { + readAddressRange(type, start, end - start + 1); + start = sortedAddrs[i]; + end = start; + } + } + readAddressRange(type, start, end - start + 1); +} - for (int addr = startAddr; addr < count; addr += MAX_REG_PER_REQUEST) { - int readCount = qMin(MAX_REG_PER_REQUEST, count - addr); +void ModbusManager::readAddressRange(QModbusDataUnit::RegisterType type, int startAddr, int count) +{ + const int MAX_REG_PER_REQUEST = 120; - QModbusDataUnit unit(type, addr, readCount); + for (int offset = 0; offset < count; offset += MAX_REG_PER_REQUEST) { + int readCount = qMin(MAX_REG_PER_REQUEST, count - offset); + QModbusDataUnit unit(type, startAddr + offset, readCount); if (auto *reply = modbusDevice->sendReadRequest(unit, slaveAddress)) { QString regType = (type == QModbusDataUnit::HoldingRegisters) ? "D" : "M"; diff --git a/modbusmanager.h b/modbusmanager.h index 000870b..d162da5 100644 --- a/modbusmanager.h +++ b/modbusmanager.h @@ -41,6 +41,8 @@ signals: private slots: void readRegisters(); void processModbusReply(); + void readRegisterGroup(QModbusDataUnit::RegisterType type, const QList &addresses); + void readAddressRange(QModbusDataUnit::RegisterType type, int startAddr, int count); private: QModbusRtuSerialMaster *modbusDevice; @@ -48,8 +50,6 @@ private: QTimer* pollTimer; int slaveAddress = 1; // 默认从站地址 QMap pendingRequests; - - void readRegisterGroup(QModbusDataUnit::RegisterType type, int startAddr, int count); }; #endif // MODBUSMANAGER_H diff --git a/mygraphicsview.cpp b/mygraphicsview.cpp index 5085412..e3cef11 100644 --- a/mygraphicsview.cpp +++ b/mygraphicsview.cpp @@ -311,3 +311,28 @@ void MyGraphicsView::mouseReleaseEvent(QMouseEvent *event) } QGraphicsView::mouseReleaseEvent(event); } + +void MyGraphicsView::wheelEvent(QWheelEvent *event) +{ + // 检查是否按下了 Ctrl 键 + if (event->modifiers() & Qt::ControlModifier) { + // 计算缩放因子 (每滚动一步缩放 10%) + const double zoomFactor = 1.1; + double scaleFactor = (event->angleDelta().y() > 0) ? zoomFactor : 1.0 / zoomFactor; + + // 获取鼠标在场景中的位置 + QPointF scenePos = mapToScene(event->position().toPoint()); + + // 执行缩放 + scale(scaleFactor, scaleFactor); + + // 调整视图中心点,使缩放以鼠标位置为中心 + QPointF delta = scenePos - mapToScene(viewport()->rect().center()); + centerOn(scenePos - delta * (scaleFactor - 1)); + + event->accept(); // 表示事件已处理 + } else { + // 没有按下 Ctrl 键,执行默认的滚动行为 + QGraphicsView::wheelEvent(event); + } +} diff --git a/mygraphicsview.h b/mygraphicsview.h index 0b53170..f51b62e 100644 --- a/mygraphicsview.h +++ b/mygraphicsview.h @@ -16,8 +16,7 @@ class MyGraphicsView : public QGraphicsView Q_OBJECT public: explicit MyGraphicsView(QWidget *parent = nullptr); - -protected: +//protected: void dragEnterEvent(QDragEnterEvent *event) override; void dragMoveEvent(QDragMoveEvent *event) override; void dropEvent(QDropEvent *event) override; @@ -27,6 +26,7 @@ protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; + void wheelEvent(QWheelEvent *event) override; signals: void itemBoundToRegister(Item*, QString);