【发布时间】:2020-11-25 18:21:30
【问题描述】:
我正在尝试运行一个简单的 Modbus,但我遇到了命令序列问题。
我首先想到的是,我不能在一个函数中运行多个函数。如果我这样做,那么它看起来像是建立了连接,但它失败了。如果我创建 2 个按钮(“连接”、“读取”)并单击第一个连接然后读取,则连接成功并且我能够读取响应。
那么如何更改代码,使其连接到 TCP Modbus,读取一些数据,然后使用一个功能/按钮关闭连接?
这是我的代码示例:
在 modbusmaster.hpp 文件中:
#ifndef MODBUSMASTER_HPP
#define MODBUSMASTER_HPP
#include <QMainWindow>
#include <QModbusTcpClient>
#include <QModbusDevice>
#include <QModbusDataUnit>
#include <QDebug>
#include <QUrl>
class QModbusClient;
class ModbusMaster : public QMainWindow
{
Q_OBJECT
public:
explicit ModbusMaster(QWidget *parent = nullptr);
QModbusClient *_modbus = nullptr;
QModbusClient *modbusDevice = nullptr;
bool open(QString host, int port);
bool read(QModbusDataUnit::RegisterType type, int startAddress, quint16 count);
void readReady();
signals:
};
#endif // MODBUSMASTER_HPP
在 modbusmaster.cpp 文件中:
#include "modbusmaster.hpp"
ModbusMaster::ModbusMaster(QWidget *parent) : QMainWindow(parent)
{
}
bool ModbusMaster::open(QString host, int port)
{
if (_modbus) {
_modbus->disconnectDevice();
delete _modbus;
_modbus = nullptr;
}
_modbus = new QModbusTcpClient(this);
connect(_modbus, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) {
qDebug() << _modbus->errorString();
});
if(!_modbus) {
qDebug() << "Could not create Modbus Client.";
} else {
qDebug() << "Modbus Client is created.";
}
if (_modbus->state() != QModbusDevice::ConnectedState) {
_modbus->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
_modbus->setConnectionParameter(QModbusDevice::NetworkAddressParameter, host);
_modbus->setTimeout(1000);
_modbus->setNumberOfRetries(3);
if (!_modbus->connectDevice()) {
qDebug() << "Connect failed: " << _modbus->errorString();
} else {
qDebug() << "Modbus Client is Connected";
return true;
}
}
return false;
}
bool ModbusMaster::read(QModbusDataUnit::RegisterType type, int startAddress, quint16 count)
{
if (!_modbus) {
qDebug() << "!_modbus";
return false;
}
if (_modbus->state() != QModbusDevice::ConnectedState){
qDebug() << "Modbus Client is not Connected in read section";
return false;
}
QModbusDataUnit req(type, startAddress, count);
if (auto *reply = _modbus->sendReadRequest(req, 1))
{
qDebug() << "auto *reply = _modbus->sendReadRequest(req, 1)";
if (!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &ModbusMaster::readReady);
else
delete reply;
return true;
}
return false;
}
void ModbusMaster::readReady()
{
auto reply = qobject_cast<QModbusReply *>(sender());
if (!reply) return;
reply->deleteLater();
if (reply->error() == QModbusDevice::NoError)
{
qDebug() << reply;
}
else if (reply->error() == QModbusDevice::ProtocolError)
{
qDebug() << QString("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()).
arg(reply->rawResult().exceptionCode(), -1, 16);
} else {
qDebug() << QString("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()).
arg(reply->error(), -1, 16);
}
}
在 mainwindow.cpp 文件中:
#include "modbusmaster.hpp"
.......
void mainwindow::on_button_clicked()
{
ModbusMaster test;
test.open("172.19.1.54", 54);
test.read(QModbusDataUnit::HoldingRegisters, 0, 10);
}
.......
“on_button_clicked”不起作用。它只显示 qDebug() 结果:
Modbus Client is created.
Modbus Client is Connected
Modbus Client is not Connected in read section
如果我使用 2 个按钮,一个用于 test.open,另一个用于 test.read,那么没关系。
那么我在这里错过了什么?
【问题讨论】:
-
应更新问题以包含所需行为、特定问题或错误以及重现问题所需的最短代码。
-
这里的问题是:如何连接到Modbus,读取一些数据并一键关闭连接?上面的代码已经非常简短,以显示我正在尝试做的事情,但足以重现问题。我真的希望有人能够帮助我。在搜索和了解更多关于 Modbus 和 Qt ist 之后,我可能会遇到线程问题?
-
上面的代码已经很短了你在任何地方都使用
modbusDevice吗? -
您可能还想使用QModbusDevice::stateChanged。
-
@scopchanov 你的意思是这一行:QModbusClient *modbusDevice = nullptr; ??没有,忘记删了。将检查 stateChanged 部分。我真的很想念一个很好的文档,里面有简单的例子和 QModbus TCP 东西的声明......而不仅仅是 Qt-Welcome 区域中的一个“巨大”示例
标签: c++ qt modbus-tcp