Modbus-Client
Das Beispiel implementiert eine Modbus-Client-Anwendung.
Das Beispiel fungiert als Modbus-Client, der Modbus-Anfragen über eine serielle Schnittstelle oder TCP sendet. Der angezeigte Dialog ermöglicht die Definition von Standardanfragen und zeigt eingehende Antworten an.
Das Beispiel muss in Verbindung mit dem Modbus-Server-Beispiel oder einem anderen Modbus-Gerät verwendet werden, das entweder über TCP oder einen seriellen Anschluss verbunden ist.
Wichtige Klassen, die in diesem Beispiel verwendet werden:

Erstellen eines QModbusClient
Für die Kommunikation ist eine Instanz von ` QModbusClient ` erforderlich. Je nach angegebenem Verbindungstyp kann das Beispiel eine Instanz von ` QModbusRtuSerialClient ` (für serielle Kommunikation) oder von ` QModbusTcpClient ` (für TCP-basierte Kommunikation) erstellen.
auto type = static_cast<ModbusConnection>(index);
if (type == Serial) {
#if QT_CONFIG(modbus_serialport)
modbusDevice = new QModbusRtuSerialClient(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 QModbusTcpClient(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"));
}Sobald der Client erstellt ist, verwenden Sie die Methode ` setConnectionParameter()` zur Festlegung der Verbindungsparameter. Die Parameter variieren je nach Kommunikationstyp:
const auto settings = m_settingsDialog->settings();
if (static_cast<ModbusConnection>(ui->connectType->currentIndex()) == Serial) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
ui->portEdit->text());
#if QT_CONFIG(modbus_serialport)
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
settings.parity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
settings.baud);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
settings.dataBits);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
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->setTimeout(settings.responseTime);
modbusDevice->setNumberOfRetries(settings.numberOfRetries);Nachdem der Client erstellt und alle Parameter festgelegt wurden, stellen Sie mithilfe von QModbusClient::connectDevice() eine Verbindung zum Modbus-Netzwerk her.
Daten lesen
Um Daten vom Modbus-Server zu lesen, muss der Client eine Serveradresse sowie die Parameter der Objekte angeben, die er lesen möchte:
Die Objektparameter werden durch die Klasse ` QModbusDataUnit ` dargestellt:
QModbusDataUnit MainWindow::readRequest() const
{
const auto table = ui->writeTable->currentData().value<QModbusDataUnit::RegisterType>();
int startAddress = ui->readAddress->value();
Q_ASSERT(startAddress >= 0 && startAddress < 10);
// do not go beyond 10 entries
quint16 numberOfEntries = qMin(ui->readSize->currentText().toUShort(),
quint16(10 - startAddress));
return QModbusDataUnit(table, startAddress, numberOfEntries);
}Sobald die Parameter erfasst sind, wird die Methode ` sendReadRequest()` verwendet, um die eigentliche Anfrage zu senden. Die Methode gibt ein ` QModbusReply ` zurück, das asynchron verarbeitet werden sollte; daher wird das Signal ` QModbusReply::finished()` verwendet, um zu prüfen, wann die Antwort bereitsteht.
if (auto *reply = modbusDevice->sendReadRequest(readRequest(), ui->serverEdit->value())) {
if (!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &MainWindow::onReadReady);
else
delete reply; // broadcast replies return immediately
} else {
statusBar()->showMessage(tr("Read error: %1").arg(modbusDevice->errorString()), 5000);
}Sobald das Signal „ QModbusReply::finished()“ empfangen wurde, kann das Antwortobjekt verwendet werden, um die Daten abzurufen oder auf Lesefehler zu prüfen:
void MainWindow::onReadReady()
{
auto reply = qobject_cast<QModbusReply *>(sender());
if (!reply)
return;
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
for (qsizetype i = 0, total = unit.valueCount(); i < total; ++i) {
const QString entry = tr("Address: %1, Value: %2").arg(unit.startAddress() + i)
.arg(QString::number(unit.value(i),
unit.registerType() <= QModbusDataUnit::Coils ? 10 : 16));
ui->readValue->addItem(entry);
}
} else if (reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Modbus exception: 0x%2)").
arg(reply->errorString()).
arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
} else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()).
arg(reply->error(), -1, 16), 5000);
}
reply->deleteLater();
}Daten schreiben
Um die Daten an den Modbus-Server zu schreiben, muss der Client die Serveradresse sowie die Parameter der Objekte angeben, die er schreiben möchte. Wie beim Lesen der Daten wird die Klasse ` QModbusDataUnit ` verwendet, um die Informationen über die zu schreibenden Daten darzustellen. Diesmal enthalten die Daten auch den gewünschten ` values`. Die Methode ` sendWriteRequest()` wird verwendet, um die gewünschten Daten zu schreiben:
QModbusDataUnit writeUnit = writeRequest();
QModbusDataUnit::RegisterType table = writeUnit.registerType();
for (qsizetype i = 0, total = writeUnit.valueCount(); i < total; ++i) {
const auto addr = i + writeUnit.startAddress();
if (table == QModbusDataUnit::Coils)
writeUnit.setValue(i, writeModel->m_coils[addr]);
else
writeUnit.setValue(i, writeModel->m_holdingRegisters[addr]);
}
if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, ui->serverEdit->value())) {
if (!reply->isFinished()) {
connect(reply, &QModbusReply::finished, this, [this, reply]() {
const auto error = reply->error();
if (error == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Write response error: %1 (Modbus exception: 0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
5000);
} else if (error != QModbusDevice::NoError) {
statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(error, -1, 16), 5000);
}
reply->deleteLater();
});
} else {
// broadcast replies return immediately
reply->deleteLater();
}
} else {
statusBar()->showMessage(tr("Write error: %1").arg(modbusDevice->errorString()), 5000);
}Wie beim Lesen der Daten wird das zurückgegebene ` QModbusReply `-Objekt verwendet, um auf Schreibfehler zu prüfen.
Ausführen des Beispiels
Sie können das Beispiel wie folgt ausführen:
- Qt Creator
Öffnen Sie den Modus „ Welcome “ und wählen Sie das Beispiel unter „ Examples “ aus. Weitere Informationen finden Sie unter „Qt Creator “: Tutorial: Erstellen und Ausführen.
- Qt Extension for Visual Studio Code
Führen Sie den Befehl „ Qt: Open Qt examples “ über „ Command Palette “ aus und wählen Sie das Beispiel aus der Liste aus. Weitere Informationen finden Sie unter Qt Extension for Visual Studio Code: Tutorial: Erstellen und Ausführen.
© 2026 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.