【Qt QModbus如何监控plc点位】附代码 + 提醒

序言

需要注意的是,如果信号是你写代码发送的,你可以在写入(sendWriteRequest)后,自连接一个信号(&QModbusReply::finished)与槽,实时监控写入后的状态。
如果信号不是你发送的,同时由于QModbus不带有回调函数,你就只能通过轮询的方式来读取这个点位的数据,也就是下面介绍的这种情况!

代码

以下是一个使用 QModbus 定期轮询特定 PLC 点位(例如 x3)的简单 Qt 示例代码。这个示例中,我们假设 x3 是一个保持寄存器(Holding Register),并且我们想要定期读取这个点位的值。

首先,确保你的 Qt 项目文件(.pro 文件)中包含了 Modbus 模块:

QT += modbus

然后,在你的 Qt 应用程序中,你可以添加以下代码:

#include <QCoreApplication>
#include <QModbusTcpClient>
#include <QTimer>
#include <QDebug>

class ModbusPolling : public QObject {
    Q_OBJECT

public:
    ModbusPolling(QObject *parent = nullptr) : QObject(parent) {
        client = new QModbusTcpClient(this);
        connect(client, &QModbusTcpClient::errorOccurred, this, &ModbusPolling::handleError);
        connect(client, &QModbusTcpClient::stateChanged, this, &ModbusPolling::handleStateChanged);
        connect(&timer, &QTimer::timeout, this, &ModbusPolling::pollModbus);
    }

    void startPolling(const QString &ip, quint16 port, quint16 startAddress, quint8 slaveId) {
        this->ip = ip;
        this->port = port;
        this->startAddress = startAddress;
        this->slaveId = slaveId;

        client->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ip);
        client->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
        client->connectDevice();
        timer.start(1000); // Poll every second
    }

private slots:
    void pollModbus() {
        QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, startAddress, 1);
        if (auto reply = client->sendReadRequest(unit, slaveId)) {
            connect(reply, &QModbusReply::finished, this, &ModbusPolling::handleReply);
        }
    }

    void handleReply() {
        QModbusReply *reply = qobject_cast<QModbusReply *>(sender());
        if (reply->error() == QModbusDevice::NoError) {
            QModbusDataUnit unit = reply->result();
            quint16 value = unit.value<quint16>(0);
            qDebug() << "Polled value from x3:" << value;
        } else {
            qDebug() << "Error reading x3:" << reply->errorString();
        }
        reply->deleteLater();
    }

    void handleError(QModbusDevice::Error e) {
        qDebug() << "Modbus error:" << e;
    }

    void handleStateChanged(QModbusDevice::State state) {
        qDebug() << "Modbus state changed:" << state;
    }

private:
    QModbusTcpClient *client;
    QTimer timer;
    QString ip;
    quint16 port;
    quint16 startAddress;
    quint8 slaveId;
};

#include "main.moc"

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    ModbusPolling polling;
    polling.startPolling("192.168.0.100", 502, 1203, 1); // Adjust IP, port, address, and slave ID as needed

    return app.exec();
}

在这个示例中,我们创建了一个 ModbusPolling 类,它负责与 Modbus TCP 服务器建立连接,并定期轮询特定的寄存器点位。我们使用 QTimer 来实现定期轮询,每隔一秒钟发送一次读取请求。

startPolling 方法用于设置 PLC 的 IP 地址、端口号、起始寄存器地址和从站 ID,并启动定时器。

pollModbus 槽函数负责发送读取请求,handleReply 槽函数处理读取请求的回复,handleErrorhandleStateChanged 槽函数分别用于处理错误和状态变化。

main 函数中,我们创建了 ModbusPolling 对象,并调用 startPolling 方法开始定期轮询。请根据您的实际情况调整 IP 地址、端口号、寄存器地址和从站 ID。

注意

注意,你拿到的数据ID和代码中识别的地址是有换算关系的,比如你拿到的可能是16进制或者是8进制的ID,那你在代码中就需要把它换成10进制,代码可以识别的格式。

例:四信
数据ID【y16】 - 起始地址【16】 - 代码识别的地址【14】
数据ID【x2】 - 起始地址【1202】 - 代码识别的地址【1202】

我对这块了解得也比较浅,欢迎大家留言说出自己的见解和遇到的不同公司对这些引脚的要求!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

flos chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值