QModbusClient

来源:互联网 发布:国内高薪职业 知乎 编辑:程序博客网 时间:2024/06/08 00:00

QModbusClient

以使用Modbus Tcp为例看看客户端怎么写程序

首先连接到服务端

QModbusTcpClient *client = new QModbusTcpClient();client->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "192.168.0.1");client->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);client->connectDevice();

这样就连接上服务端了,下面可以发送请求了

发送读或写请求到服务端

写请求

QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 40003, 1); // write 1 value in address 40003writeUnit.setValue(0, 0x253); //这里先建好QModbusDataUnitif (auto *reply = client->sendWriteRequest(writeUnit, 1))//发送写请求{    if (!reply->isFinished())    {        connect(reply, &QModbusReply::finished, this, [this, reply]()         {            if (reply->error() != QModbusDevice::NoError)                                   // error in reply                reply->deleteLater();            });    }    else    {        if (reply->error() != QModbusDevice::NoError)                       // error in reply        // broadcast replies return immediately        reply->deleteLater();    }}else{    // error in request}

先建个QModbusDataUnit,下面是Qt帮助文档中的介绍
QModbusDataUnit is a container class representing single bit and 16 bit word entries in the Modbus register.QModbusDataUnit can be used for read and write operations
给QModbusDataUnit赋好值后发送写请求sendWriteRequest,写到相应寄存器中的相应位置
如果没有发生错误的话sendWriteRequest将返回一个QModbusReply,否则返回空指针。
当reply完成或放弃后reply->isFinished()将返回true。

读请求

QModbusDataUnit readUnit(QModbusDataUnit::InputRegisters, 40006, 1); // just read input register 40006 if (auto *reply = client->sendReadRequest(readUnit, 255)) // client id 255{    if (!reply->isFinished())    {        // connect the finished signal of the request to your read slot        connect(reply, &QModbusReply::finished, this, &YourClass::readReady);    }    else    {        delete reply; // broadcast replies return immediately    }}else{    // request error}YourClass::readReady{    QModbusReply *reply = qobject_cast<QModbusReply *>(sender());    if (!reply)        return;    if (reply->error() == QModbusDevice::NoError)    {        const QModbusDataUnit unit = reply->result();        int startAddress = unit.startAddress(); // the start address, here 40006        int value = unit.value(0); // value of the start address + 0        ...     }    else    {        // reply error    }    reply->deleteLater(); // delete the reply }

应该注意的问题

看看QModbusClient帮助文档中的一句话
QModbusClient has an asynchronous API. When the finished slot is called, the parameter it takes is the QModbusReply object containing the PDU as well as meta-data (Addressing, etc.).
这意味着

The API of the QModbusDevice classes are asynchronous. That means when you callclient->connectDevice() your client is not “really” connected to your server. The function just send an event to the event loop. When the application enters the event loop the event will be executed.The QModbusDevice class has some signals to control your connection state and error message.

所以我们应该

Check the client state with yout slot. Before reading registers ensure that the client is in connected state.

因此所有代码在一个函数中是不对的,像这样

YourClass::connect(){QModbusTcpClient *client=new QModbusTcpClient();client->setConnectionParameter(QModbusDevice::NetworkAddressParameter,"192.168.0.201");client->setConnectionParameter(QModbusDevice::NetworkPortParameter,502);client->connectDevice();QModbusDataUnit readUnit(QModbusDataUnit::Coils,00000,4);if (auto *reply=client->sendReadRequest(readUnit,255)){...}

应该

MyClass::connectToModbusServer(){   QModbusTcpClient *client=new QModbusTcpClient();   client->setConnectionParameter(QModbusDevice::NetworkAddressParameter,"192.168.0.201");   client->setConnectionParameter(QModbusDevice::NetworkPortParameter,502);   if (client->connectDevice())   {      connect(client, &QModbusTcpClient::stateChanged, this, &MyClass::onStateChanged);       connect(client, &QModbusTcpClient::errorOccurred, this, &MyClass::onErrorOccurred);    }   else      qDebug() << client->errorString();}MyClass::readCoil(){   QModbusDataUnit readUnit(QModbusDataUnit::Coils,00000,4);

本文内容摘自这里

原创粉丝点击