• 用QT的modbus相关类编写ModbusTcp主站


    目标程序运行界面,

     

    1.新建Qwiget工程,工程文件如下,

    #-------------------------------------------------
    #
    # Project created by QtCreator 2022-09-28T14:53:02
    #
    #-------------------------------------------------
     
    
    QT       += core gui
    QT       += serialbus serialport
     
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
     
    
    TARGET = ModbusExample001
    TEMPLATE = app
     
    
    # The following define makes your compiler emit warnings if you use
    # any feature of Qt which has been marked as deprecated (the exact warnings
    # depend on your compiler). Please consult the documentation of the
    # deprecated API in order to know how to port your code away from it.
    DEFINES += QT_DEPRECATED_WARNINGS
     
    
    # You can also make your code fail to compile if you use deprecated APIs.
    # In order to do so, uncomment the following line.
    # You can also select to disable deprecated APIs only up to a certain version of Qt.
    #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
     
    
    CONFIG += c++11
     
    
    SOURCES += \
            main.cpp \
            widget.cpp
     
    
    HEADERS += \
            widget.h
     
    
    FORMS += \
            widget.ui
     
    
    # Default rules for deployment.
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
     
    

    2.主程序main.cpp

    #include "widget.h"
    #include 
     
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget w;
        w.show();
     
    
        return a.exec();
    }
     
    

    3. 主窗口程序

    1)widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
     
    
    #include 
     
    
    class QModbusClient;
    class QModbusReply;
     
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACE
     
    
    class Widget : public QWidget
    {
        Q_OBJECT
     
    
    public:
        Widget(QWidget *parent = nullptr);
        ~Widget();
     
    
    private:
        Ui::Widget *ui;
     
    
        QString m_strReceived;
        bool m_clickedbtnCoilRead;
        bool m_clickedbtnDiscreteInputs;
        bool m_clickedbtnInputRegisters;
        bool m_clickedbtnHoldingRegisters;
     
    
        QModbusClient *modbusDevice = nullptr;
     
    
     
    
    private slots:
        void onReadReady();
        void onModbusStateChanged(int state);
        void on_btnConnect_clicked();
        void on_btnDiscreteInputs_clicked();
        void on_btnInputRegisters_clicked();
        void on_btnHoldingRegisters_clicked();
        void on_btnHoldingRegisters_2_clicked();
        void on_btnCoilRead_clicked();
        void on_btnCoilWrite_clicked();
        void on_btnExit_clicked();
    };
    #endif // WIDGET_H
     
    

    2)widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include 
    #include 
    #include 
     
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
        , m_clickedbtnCoilRead(false)
        , m_clickedbtnDiscreteInputs(false)
        , m_clickedbtnInputRegisters(false)
        , m_clickedbtnHoldingRegisters(false)
    {
        ui->setupUi(this);
     
    
        modbusDevice = new QModbusTcpClient(this);
     
    
        ui->btnCoilRead->setEnabled(false);
        ui->btnDiscreteInputs->setEnabled(false);
        ui->btnHoldingRegisters->setEnabled(false);
        ui->btnInputRegisters->setEnabled(false);
     
    
        ui->btnCoilWrite->setEnabled(false);
        ui->btnHoldingRegisters_2->setEnabled(false);
     
    
        connect(modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) {
            qDebug() << "new Error: " << modbusDevice->errorString();
        });
     
    
        if (nullptr == modbusDevice)
        {
            qDebug() << "Cannot Create Modbus Client";
        }
        else
        {
            connect(modbusDevice, &QModbusClient::stateChanged,
                    this, &Widget::onModbusStateChanged);
        }
     
    
     
    
    }
     
    
    Widget::~Widget()
    {
        if (modbusDevice)
        {
            modbusDevice->disconnectDevice();
        }
     
    
        delete modbusDevice;
     
    
        delete ui;
    }
     
    
     
    
    void Widget::onReadReady()
    {
        auto reply = qobject_cast(sender());
        if (nullptr == reply)
        {
            return;
        }
     
    
        if (reply->error() == QModbusDevice::NoError)
        {
            const QModbusDataUnit responseData = reply->result();
     
    
            qDebug() << "data receive: " << responseData.values();
     
    
            m_strReceived = "";
            for(auto value: responseData.values())
            {
                m_strReceived += tr("%1 ").arg(value);
            }
     
    
            if (m_clickedbtnCoilRead) ui->lineEditCoil->setText(m_strReceived);
            if (m_clickedbtnDiscreteInputs) ui->lineEditDiscreteInputs->setText(m_strReceived);
            if (m_clickedbtnInputRegisters) ui->lineEditInputRegieters->setText(m_strReceived);
            if (m_clickedbtnHoldingRegisters) ui->lineEditHodingReg->setText(m_strReceived);
        }
        else if (reply->error() == QModbusDevice::ProtocolError)
        {
            qDebug() << "Read response Protocol error: " << reply->errorString();
        }
        else
        {
            qDebug() << "Read response Error: " << reply->errorString();
        }
     
    
     
    
        reply->deleteLater();
    }
     
    
     
    
    void Widget::onModbusStateChanged(int state)
    {
        if (state == QModbusDevice::UnconnectedState)
        {
            qDebug() << "TCP Client connect to Server: unconnected";
            ui->lblConnectStatus->setText("unconnected");
            ui->btnConnect->setText(tr("Connect"));
     
    
            ui->btnCoilRead->setEnabled(false);
            ui->btnDiscreteInputs->setEnabled(false);
            ui->btnHoldingRegisters->setEnabled(false);
            ui->btnInputRegisters->setEnabled(false);
     
    
            ui->btnCoilWrite->setEnabled(false);
            ui->btnHoldingRegisters_2->setEnabled(false);
     
    
        }
        else if (state == QModbusDevice::ConnectingState)
        {
            qDebug() << "TCP Client connecting to Server";
            ui->lblConnectStatus->setText("connecting to server");
        }
        else if (state == QModbusDevice::ConnectedState)
        {
            qDebug() << "TCP Client connected to Server";
            ui->lblConnectStatus->setText("connected");
            ui->btnConnect->setText(tr("disconnect"));
     
    
            ui->btnCoilRead->setEnabled(true);
            ui->btnDiscreteInputs->setEnabled(true);
            ui->btnHoldingRegisters->setEnabled(true);
            ui->btnInputRegisters->setEnabled(true);
     
    
            ui->btnCoilWrite->setEnabled(true);
            ui->btnHoldingRegisters_2->setEnabled(true);
     
    
     
    
        }
        else if (state == QModbusDevice::ClosingState)
        {
            qDebug() << "device closed";
            ui->lblConnectStatus->setText("device closed");
        }
    }
     
    
    void Widget::on_btnConnect_clicked()
    {
        if (!modbusDevice)
        {
            return;
        }
     
    
        if (modbusDevice->state() != QModbusDevice::ConnectedState)
        {
            modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");
            modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);
     
    
            modbusDevice->setTimeout(1000);
            modbusDevice->setNumberOfRetries(3);
     
    
            bool ok = modbusDevice->connectDevice();
            if (!ok)
            {
                qDebug() << "modbusDevice->connectDevice failed";
                ui->lblConnectStatus->setText("Fail to connect");
            }
        }
        else
        {
            modbusDevice->disconnectDevice();
            ui->btnConnect->setText(tr("connect"));
     
    
            ui->btnCoilRead->setEnabled(false);
            ui->btnDiscreteInputs->setEnabled(false);
            ui->btnHoldingRegisters->setEnabled(false);
            ui->btnInputRegisters->setEnabled(false);
            ui->btnCoilWrite->setEnabled(false);
            ui->btnHoldingRegisters_2->setEnabled(false);
        }
     
    
    }
     
    
    void Widget::on_btnDiscreteInputs_clicked()
    {
        m_clickedbtnCoilRead = false;
        m_clickedbtnDiscreteInputs = true;
        m_clickedbtnInputRegisters = false;
        m_clickedbtnHoldingRegisters = false;
     
    
        QModbusDataUnit data(QModbusDataUnit::DiscreteInputs, 0, 10);
     
    
        auto reply = modbusDevice->sendReadRequest(data, 0x1);
        if (nullptr == reply)
        {
            qDebug() << "fail to send data: " << modbusDevice->errorString();
        }
        else
        {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &Widget::onReadReady);
    //            ui->lineEditDiscreteInputs->setText(m_strReceived);
            }
            else
            {
                //broadcast replies return immediately
                delete reply;
            }
        }
    }
     
    
    void Widget::on_btnInputRegisters_clicked()
    {
        m_clickedbtnCoilRead = false;
        m_clickedbtnDiscreteInputs = false;
        m_clickedbtnInputRegisters = true;
        m_clickedbtnHoldingRegisters = false;
     
    
        QModbusDataUnit data(QModbusDataUnit::InputRegisters, 0, 10);
     
    
        auto reply = modbusDevice->sendReadRequest(data, 0x1);
        if (nullptr == reply)
        {
            qDebug() << "failed to send data: " << modbusDevice->errorString();
        }
        else
        {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &Widget::onReadReady);
    //            ui->lineEditInputRegieters->setText(m_strReceived);
            }
            else
            {
                //broadcast replies return immediately
                delete reply;
            }
        }
    }
     
    
    void Widget::on_btnHoldingRegisters_clicked()
    {
        m_clickedbtnCoilRead = false;
        m_clickedbtnDiscreteInputs = false;
        m_clickedbtnInputRegisters = false;
        m_clickedbtnHoldingRegisters = true;
     
    
        QModbusDataUnit data(QModbusDataUnit::HoldingRegisters, 0, 10);
     
    
        auto reply = modbusDevice->sendReadRequest(data, 0x1);
        if (nullptr == reply)
        {
            qDebug() << "failed to send request data: " << modbusDevice->errorString();
        }
        else
        {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &Widget::onReadReady);
    //            ui->lineEditHodingReg->setText(m_strReceived);
            }
            else
            {
                //broadcast replies return immediately
                delete reply;
            }
        }
    }
     
    
    void Widget::on_btnHoldingRegisters_2_clicked()
    {
        QModbusDataUnit writeData(QModbusDataUnit::HoldingRegisters, 0, 10);
        for (int i = 0; i < writeData.valueCount(); i++)
        {
            writeData.setValue(i, i * i);
        }
     
    
        qDebug() << "data sent: " << writeData.values();
     
    
        QModbusReply* reply = modbusDevice->sendWriteRequest(writeData, 1);
        if (reply)
        {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, [this, reply](){
                    if (reply->error() == QModbusDevice::ProtocolError)
                    {
                        qDebug() << "data written error: " << reply->errorString();
                    }
                    else if (reply->error() != QModbusDevice::NoError)
                    {
                        qDebug() << "data written error: " << reply->errorString();
                    }
                    else
                    {
                        const QModbusDataUnit data = reply->result();
     
    
                        qDebug() << "count of messages: " << data.valueCount() << " :" << data.values();
     
    
                    }
     
    
                    reply->deleteLater();
                });
            }
            else
            {
                reply->deleteLater();
            }
        }
        else
        {
            qDebug() << "sendWriteRequest Error: " << reply->errorString();
        }
    }
     
    
    void Widget::on_btnCoilRead_clicked()
    {
        m_clickedbtnCoilRead = true;
        m_clickedbtnDiscreteInputs = false;
        m_clickedbtnInputRegisters = false;
        m_clickedbtnHoldingRegisters = false;
     
    
        QModbusDataUnit data(QModbusDataUnit::Coils, 0, 10);
     
    
        auto reply = modbusDevice->sendReadRequest(data, 0x1);
        if (nullptr == reply)
        {
            qDebug() << "faile to send request data: " << modbusDevice->errorString();
        }
        else
        {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &Widget::onReadReady);
     
    
            }
            else
            {
                //broadcast replies return immediately
                delete reply;
            }
        }
    }
     
    
    void Widget::on_btnCoilWrite_clicked()
    {
        QModbusDataUnit writeData(QModbusDataUnit::Coils, 0, 10);
        QString tmpString =  ui->lineEditCoil->text();
        if (tmpString.length() < writeData.valueCount() * 2)
        {
            qDebug() << "data sent less than required";
            return;
        }
     
    
        for (int i = 0; i < writeData.valueCount(); i++)
        {
            writeData.setValue(i, tmpString.at(2*i).unicode() - '0');
        }
     
    
        qDebug() << "data sent is: " << writeData.values();
     
    
        QModbusReply* reply = modbusDevice->sendWriteRequest(writeData, 1);
        if (reply)
        {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, [this, reply](){
                    if (reply->error() == QModbusDevice::ProtocolError)
                    {
                        qDebug() << "data written error: " << reply->errorString();
                    }
                    else if (reply->error() != QModbusDevice::NoError)
                    {
                        qDebug() << "data written error: " << reply->errorString();
                    }
                    else
                    {
                        const QModbusDataUnit data = reply->result();
     
    
                        qDebug() << "count of messages: " << data.valueCount() << " :" << data.values();
     
    
                    }
     
    
                    reply->deleteLater();
                });
            }
            else
            {
                reply->deleteLater();
            }
        }
        else
        {
            qDebug() << "sendWriteRequest Error: " << reply->errorString();
        }
    }
     
    
    void Widget::on_btnExit_clicked()
    {
        this->close();
    }
     
    

  • 相关阅读:
    首个校园招聘年度盛宴,数百万人关注,牛客2022青年人才招聘峰会来啦!
    Spring 5 学习整理
    【SQL语法基础】游标:当我们需要逐条处理数据时,该怎么做?
    02:项目二:感应开关盖垃圾桶
    计算机毕业设计Java影院网上售票系统(系统+程序+mysql数据库+Lw文档)
    汉字风格迁移篇----EasyFont:一个基于风格学习的系统,可以轻松构建大规模手写字体
    QT学习_15_线程间通信以及注意事项
    01-go基础-06-切片(声明切片、初始化切片、切片赋值、切片长度、切片容量、空切片、append、copy)
    基于Flume+Kafka+Hbase+Flink+FineBI的实时综合案例(四)实时计算需求及技术方案
    prim算法的实现
  • 原文地址:https://blog.csdn.net/zkmrobot/article/details/127094754