QModbusClient

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 40003
writeUnit.setValue(0, 0x253); 
//这里先建好QModbusDataUnit

if (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);

本文内容摘自这里

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值