Modbus サーバー
この例は Modbus サーバー・アプリケーションを実装します。
サンプルは Modbus サーバとして動作します。標準 Modbus 要求を受信し、要求に基づいて内部状態を調整し、適切な応答で応答します。
この例はModbus クライアント例と一緒に使用する必要があります。この例は、Modbus クライアント例が開始される前に開始し、リッスン状態にする必要があります。Modbus プロトコルを使用します。
この例で使用される主なクラス
QModbusServer の作成
通信を行うにはQModbusServer のインスタンスが必要です。指定された接続タイプに応じて、QModbusRtuSerialServer (シリアル通信用)またはQModbusTcpServer (TCP ベースの通信用)をインスタンス化することができます。
auto type = static_cast<ModbusConnection>(index); if (type == Serial) { #if QT_CONFIG(modbus_serialport) modbusDevice = new QModbusRtuSerialServer(this); // Try to fill in the first available serial port name if the line edit // is empty, or contains a url (assume that ':' is only a part of url). const auto ports = QSerialPortInfo::availablePorts(); const auto currentText = ui->portEdit->text(); if (!ports.isEmpty() && (currentText.isEmpty() || currentText.contains(u':'))) ui->portEdit->setText(ports.front().portName()); #endif } else if (type == Tcp) { modbusDevice = new QModbusTcpServer(this); const QUrl currentUrl = QUrl::fromUserInput(ui->portEdit->text()); // Check if we already have <ip address>:<port> if (currentUrl.port() <= 0) ui->portEdit->setText(QLatin1String("127.0.0.1:50200")); }
サーバーが作成されると、QModbusServer::setMap ()メソッドを使用してレジスタ・マップが設定される。このレジスタ・マップは、クライアント・アプリケーションがサーバー・データの読み書きに使用します。
QModbusDataUnitMap reg; reg.insert(QModbusDataUnit::Coils, { QModbusDataUnit::Coils, 0, 10 }); reg.insert(QModbusDataUnit::DiscreteInputs, { QModbusDataUnit::DiscreteInputs, 0, 10 }); reg.insert(QModbusDataUnit::InputRegisters, { QModbusDataUnit::InputRegisters, 0, 10 }); reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, 10 }); modbusDevice->setMap(reg);
その後、通信パラメータとサーバー・アドレスが指定される。通信パラメータは通信タイプによって異なる:
if (static_cast<ModbusConnection>(ui->connectType->currentIndex()) == Serial) { modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, ui->portEdit->text()); #if QT_CONFIG(modbus_serialport) modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, m_settingsDialog->settings().parity); modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_settingsDialog->settings().baud); modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, m_settingsDialog->settings().dataBits); modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, m_settingsDialog->settings().stopBits); #endif } else { const QUrl url = QUrl::fromUserInput(ui->portEdit->text()); modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, url.port()); modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, url.host()); } modbusDevice->setServerAddress(ui->serverEdit->text().toInt());
サーバーが作成され、すべてのパラメータが指定されたら、QModbusServer::connectDevice() を使用して Modbus ネットワークに接続します。
ローカル値の変更
この例では、提供されているコンボボックスまたは行編集を使用して、サポートされているすべてのregister types の値を変更できます。UI で値が更新されると、QModbusServer::setData() メソッドを使用してサーバー上の実際の値が更新されます:
void MainWindow::bitChanged(int id, QModbusDataUnit::RegisterType table, bool value) { if (!modbusDevice) return; if (!modbusDevice->setData(table, quint16(id), value)) statusBar()->showMessage(tr("Could not set data: ") + modbusDevice->errorString(), 5000); } void MainWindow::setRegister(const QString &value) { if (!modbusDevice) return; const QString objectName = QObject::sender()->objectName(); if (registers.contains(objectName)) { bool ok = true; const quint16 id = quint16(QObject::sender()->property("ID").toUInt()); if (objectName.startsWith(QStringLiteral("inReg"))) { const auto uval = value.toUShort(&ok, 16); if (ok) ok = modbusDevice->setData(QModbusDataUnit::InputRegisters, id, uval); } else if (objectName.startsWith(QStringLiteral("holdReg"))) { const auto uval = value.toUShort(&ok, 16); if (ok) ok = modbusDevice->setData(QModbusDataUnit::HoldingRegisters, id, uval); } if (!ok) statusBar()->showMessage(tr("Could not set register: ") + modbusDevice->errorString(), 5000); } }
リモート書き込みの処理
Modbus クライアントは書き込み要求を送信することでCoils とHoldingRegisters を更新することができます。このようなリクエストを使用してサーバー側で値が更新されると、QModbusServer::dataWritten() シグナルが発信されます。
connect(modbusDevice, &QModbusServer::dataWritten, this, &MainWindow::updateWidgets);
Modbus サーバー・サンプルはこのシグナルに接続し、更新された値を抽出し、それに応じて UI を更新します:
void MainWindow::updateWidgets(QModbusDataUnit::RegisterType table, int address, int size) { for (int i = 0; i < size; ++i) { quint16 value; QString text; switch (table) { case QModbusDataUnit::Coils: modbusDevice->data(QModbusDataUnit::Coils, quint16(address + i), &value); coilButtons.button(address + i)->setChecked(value); break; case QModbusDataUnit::HoldingRegisters: modbusDevice->data(QModbusDataUnit::HoldingRegisters, quint16(address + i), &value); registers.value(QStringLiteral("holdReg_%1").arg(address + i))->setText(text .setNum(value, 16)); break; default: break; } } }
例の実行
サンプルを実行するには Qt Creatorからサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Exampleを参照してください。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.