QT 使用ModBus

发送离散数据
标准设备 0xFF00 
非标准设备 0x0001 / 0x0100


创建

QModbusClient *modbusDevice = new QModbusRtuSerialClient(this);
modbusDevice->setNumberOfRetries(1);//设置超时后只读取去一次

//设置ModBus
bool getData::configModBus(QString port)
{
    modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, port);
    modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud9600);     //波特率:9600
    modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);        //数据位:8位
    modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);      //停止位:1位
    modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);

    return modbusDevice->connectDevice();
}

//--------------读取离散数据 功能码(2) modbus地址01

 // 创建读取请求(离散输入)
    int slaveAddress = 1;     // 从站地址 0x01
    int startAddress = 513;   // 起始地址 0x0201 (513)
    int numInputs = 16;        // 读取数量 0x0008 (8)

    QModbusDataUnit request(QModbusDataUnit::DiscreteInputs, startAddress, numInputs);

    // 发送请求
    if (QModbusReply *reply = modbusDevice->sendReadRequest(request, slaveAddress)) {
        if (!reply->isFinished()) {
            // 处理响应
            connect(reply, &QModbusReply::finished, this, [this, reply]() {
                QList<bool> DODataInitDO = getDOData();
                bool state;
                if (reply->error() == QModbusDevice::NoError) {
                    const QModbusDataUnit unit = reply->result();
                    // 打印读取结果
                    for (int i = 0; i < unit.valueCount(); ++i) {
                        state = unit.value(i) ? true : false;
            qDebug()<<state ;
                    }
                } else if (reply->error() == QModbusDevice::ProtocolError) {
                    qDebug() << "读取离散数据 Modbus异常码: 0x" << reply->rawResult().exceptionCode();
                } else {
                    qDebug() << "读取离散数据 modbus地址01 错误:" << reply->errorString();
                    sendDigitalDOTimer->stop();
                }
                reply->deleteLater();
            });
        } else {
            delete reply; // 立即删除
        }
    } else {
        qDebug() << "发送请求失败  modbus地址01):" << modbusDevice->errorString();
    }
}
//----------------------------------------------------------


//--------------发送离散数据 功能码(5) modbus地址02
   

int slaveAddress = 2;      // 从机地址
    uint coilAddress  = 256 + index.toInt();      // 线圈地址(对应设备地址 00005)

    QModbusRequest request(QModbusRequest::WriteSingleCoil);
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::BigEndian);

    quint16 modbusAddress = coilAddress;

    // 尝试不同值格式
    quint16 value;
    value = valuex.toInt() ? 0x0001 : 0x0000; // 某些设备变体
    stream << modbusAddress << value;
    request.setData(data);

    // 发送请求
    QModbusReply *reply = modbusDevice->sendRawRequest(request, slaveAddress);

    // 处理响应
    connect(reply, &QModbusReply::finished, this, [this, reply]() {
        if (reply->error() == QModbusDevice::NoError) {
            qDebug() << " Write successful!";
        } else {
            auto exceptionCode = reply->rawResult().exceptionCode();
            if(exceptionCode != 255) {
                qDebug() << "Modbus Exception:" << exceptionCode;
            }else {
                setDoComState(1);
                QTimer::singleShot(100,this,[=] {
                    setDoComState(0);
                });     //收到数据闪一下
            }
        }
        reply->deleteLater();
    });
//----------------------------------------------------------

//--------------接收数据 功能码(3) modbus地址03

// 创建读取请求
    const int slaveAddress = 3;       // 从站地址
    const int startAddress = 768 + index;     // 起始地址 (0x0301)
    const int numRegisters = 1;       // 读取数量

    QModbusDataUnit request(QModbusDataUnit::HoldingRegisters, startAddress, numRegisters);

    // 发送请求
    if (QModbusReply *reply = modbusDevice->sendReadRequest(request, slaveAddress)) {
        if (!reply->isFinished()) {
            connect(reply, &QModbusReply::finished, this, [=]() {
                QList<QString> AODataTemp = getAOData();
                QString valueStr;

                if (reply->error() == QModbusDevice::NoError) {
                    const QModbusDataUnit unit = reply->result();
                    // qDebug()<<("AO 数据 读取成功!");
                    valueStr = QString("%1").arg(unit.value(0));
        qDebug()<<valueStr;
                } else if (reply->error() == QModbusDevice::ProtocolError) {
                    quint8 exCode = reply->rawResult().exceptionCode();
                    qDebug()<<(QString("Modbus异常: 0x%1").arg(exCode, 2, 16, QLatin1Char('0')));

                    // 显示异常信息
                    switch (exCode) {
                    case 0x01: qDebug()<<("异常: 不支持的功能码"); break;
                    case 0x02: qDebug()<<("异常: 无效的寄存器地址"); break;
                    case 0x03: qDebug()<<("异常: 无效的数据值"); break;
                    case 0x04: qDebug()<<("异常: 从站设备故障"); break;
                    default: qDebug()<<("未知异常");
                    }
                } else {
                    qDebug()<<("读取错误: " + reply->errorString());
                }
                reply->deleteLater();
            });
        } else {
            delete reply;
        }
    } else {
        qDebug()<<("发送请求失败: " + modbusDevice->errorString());
    }
//----------------------------------------------------------

//--------------发送数据 功能码(6) modbus地址03

int slaveAddress = 4;
    int registerAddress = 768 + index.toInt();
    int valuec = valuex.toInt();
    quint16 sendData = 0;

    // 创建写入请求
    QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters , registerAddress, 1);
    writeUnit.setValue(0,sendData);
    // 发送请求
    if (QModbusReply *reply = modbusDevice->sendWriteRequest(writeUnit, slaveAddress)) {
        if (!reply->isFinished()) {
            connect(reply, &QModbusReply::finished, this, [=]() {
                if (reply->error() == QModbusDevice::NoError) {
                    const QModbusDataUnit unit = reply->result();
                    qDebug()<<("写入成功!");
                    // 显示写入的寄存器信息
                    QString msg = QString("写入寄存器 %1 值: %2 (0x%3)")
                                      .arg(unit.startAddress())
                                      .arg(unit.value(0))
                                      .arg(unit.value(0), 4, 16, QLatin1Char('0'));
                    qDebug()<<(msg);
                } else if (reply->error() == QModbusDevice::ProtocolError) {
                    quint8 exCode = reply->rawResult().exceptionCode();
                    qDebug()<<(QString("Modbus异常: 0x%1").arg(exCode, 2, 16, QLatin1Char('0')));

                    // 显示异常信息
                    switch (exCode) {
                    case 0x01: qDebug()<<("异常: 不支持的功能码"); break;
                    case 0x02: qDebug()<<("异常: 无效的寄存器地址"); break;
                    case 0x03: qDebug()<<("异常: 无效的数据值"); break;
                    case 0x04: qDebug()<<("异常: 从站设备故障"); break;
                    default: qDebug()<<("未知异常");
                    }
                } else {
                    qDebug()<<("写入错误: " + reply->errorString());
                }
                reply->deleteLater();
            });
        } else {
            delete reply;
        }
    } else {
        qDebug()<<("发送请求失败: " + modbusDevice->errorString());
    }
//----------------------------------------------------------


 

### 如何在Qt中实现Modbus通信 #### 使用QtModbus库简化Modbus通信 为了便于开发者在Qt环境中进行Modbus通信,存在一个名为QtModbus的工具[^1]。此工具不仅提供了一个基于libModbusQt5 Modbus示例项目,还充当了libModbus DLL的一个简单包装器,使得开发者可以更轻松地理解如何利用libModbus执行基本操作。 #### 准备工作 确保开发环境已安装Qt,并具备一定的Qt编程基础是必要的前提条件之一[^2]。这有助于更好地理解和应用后续的具体编码过程。 #### 创建Modbus TCP客户端实例 对于希望构建Modbus TCP应用程序的人来说,有一个具体的例子可供参考——即基于QT5 QWidget创建的ModbusTCP主机客户端通信程序[^3]。该程序实现了多种实用功能,比如断线自动重连机制、允许用户自定义服务器IP地址及端口设置等特性;除此之外,它也能够处理较为复杂的数据类型交换需求(如浮点数和带符号整数),并且提供了对物理设备输入输出状态的操作接口。 #### 编程入门指南 如果想要快速上手,在Qt6里边做最基础版本的Modbus通讯的话,则可以从学习几个核心函数入手[^4]。这里不会深入探讨协议本身细节而是专注于实际编写代码时需要用到的技术要点。 ```cpp // 初始化串口参数 (针对RTU模式) QSerialPort *serial; serial->setBaudRate(QSerialPort::Baud9600); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); // 或者初始化网络连接 (针对TCP模式) QTcpSocket *socket; // 发送请求报文给远程节点 QByteArray request; request.append(/* 构造具体命令 */); if (useTcp){ socket->write(request); }else{ serial->write(request); } // 接收响应数据包并解析结果... ``` 上述片段展示了两种不同传输层下的初始配置方法以及发送消息的一般流程。当然这只是非常初步的内容概述而已,真正完整的解决方案还需要考虑更多因素,例如错误处理逻辑的设计等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值