Modbus Tcp Demo的QT实现

1. 测试界面

2.工程文件

#-------------------------------------------------
#
# Project created by QtCreator 2023-04-02T22:39:29
#
#-------------------------------------------------

QT       += core gui serialbus

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = ModbusTcp
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 += \
        cmodbustcp.cpp \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        cmodbustcp.h \
        mainwindow.h

FORMS += \
        mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

3.ModbusTcp类的设计与实现

1)cmodbustcp.h

#ifndef CMODBUSTCP_H
#define CMODBUSTCP_H

#include <QObject>
#include <QModbusTcpClient>

class QModbusClient;
class QModbusReply;

class CModbusTcp : public QObject
{
    Q_OBJECT
public:

public:
    explicit CModbusTcp(QObject *parent = nullptr);
    ~CModbusTcp();

    QString m_strReceived;
    QModbusClient *m_pmodbusDevice = nullptr;


public:

signals:
    void signalStateChanged(bool bConnected);
    void signalDataReceived(QString strDataReceived);

public slots:
    void onReadReady();
    void onModbusStateChanged(QModbusDevice::State state);

    void coilRead(int nStartAddress,uint16_t numbers,int ServerID);
    void coilWrite(int nStartAddress,QString strCoilToWrite,int ServerID);
    void discreteInputRead();
    void inputRegisterRead();
    void holdingRegsiterRead();
    void holdingRegisterWrite(QString strHoldingRegisterToWrite);

    bool connect2Server(QString strIP = "127.0.0.1", QString strPort = "502");
    void disconnectFromServer();

};

#endif // CMODBUSTCP_H

2)cmodbustcp.cpp

#include "cmodbustcp.h"


#include <QThread>
#include <QDebug>

#define DELETE_AND_SET_NULL(pointer) if(pointer != nullptr) { delete pointer; pointer = nullptr;};
#define DELETE_AND_SET_NULL_ARRAY(pointer) if(pointer != nullptr) { delete[] pointer; pointer = nullptr;};

CModbusTcp::CModbusTcp(QObject *parent) :
    QObject(parent)
{
    m_pmodbusDevice = new QModbusTcpClient(this);

    connect(m_pmodbusDevice, &QModbusClient::stateChanged,this, &CModbusTcp::onModbusStateChanged);
}

CModbusTcp::~CModbusTcp()
{
    DELETE_AND_SET_NULL(m_pmodbusDevice);
}

bool CModbusTcp::connect2Server(QString strIP, QString strPort)
{
    bool bRet= false;

    m_pmodbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, strIP);
    m_pmodbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, strPort.toInt());
    m_pmodbusDevice->setTimeout(1000);
    m_pmodbusDevice->setNumberOfRetries(3);

    bRet = m_pmodbusDevice->connectDevice();
    if(bRet)
    {
        qDebug()<< "connect to PLC OK";
    } else {
        qDebug()<< "connect to PLC Fail";
    }

    return bRet;
}

void CModbusTcp::disconnectFromServer()
{
    if(m_pmodbusDevice) m_pmodbusDevice->disconnectDevice();
}

void CModbusTcp::coilRead(int nStartAddress,uint16_t numbers,int ServerID)
{
    if(m_pmodbusDevice)
    {
        QModbusDataUnit data(QModbusDataUnit::Coils, nStartAddress, numbers);
        auto reply = m_pmodbusDevice->sendReadRequest(data, ServerID);
        if(nullptr == reply)
        {
            qDebug() << "faile to send request data: " << m_pmodbusDevice->errorString();
        } else {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &CModbusTcp::onReadReady);

            }
            else
            {
                delete reply;
            }
        }
    }
}

void CModbusTcp::coilWrite(int nStartAddress,QString strCoilToWrite,int ServerID)
{
    if(m_pmodbusDevice)
    {
        int nstrLength = strCoilToWrite.length();
        if(nstrLength == 0)
        {
            qDebug() << "Warnning:Coil String to send is Null!";
            return;
        }

        QModbusDataUnit writeData(QModbusDataUnit::Coils, nStartAddress, (nstrLength >> 1) + (nstrLength & 1));

        for (uint i = 0; i < writeData.valueCount(); i++)
        {
            writeData.setValue(i, strCoilToWrite.at(2*i).unicode() - '0');
        }

        qDebug() << "data sent is: " << writeData.values();

        QModbusReply* reply = m_pmodbusDevice->sendWriteRequest(writeData, ServerID);
        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() << "data written: " << data.values();

                        m_strReceived = "";
                        for(auto value: data.values())
                        {
                            m_strReceived += tr("%1 ").arg(value);
                        }

                        emit signalDataReceived(m_strReceived);

                    }

                    reply->deleteLater();
                });
            }
            else
            {
                reply->deleteLater();
            }
        }
        else
        {
            qDebug() << "sendWriteRequest Error: " << reply->errorString();
        }
    }
}

void CModbusTcp::discreteInputRead()
{
    if(m_pmodbusDevice)
    {
        QModbusDataUnit data(QModbusDataUnit::DiscreteInputs, 0, 10);

        auto reply = m_pmodbusDevice->sendReadRequest(data, 0x1);
        if (nullptr == reply)
        {
            qDebug() << "fail to send data: " << m_pmodbusDevice->errorString();
        }
        else
        {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &CModbusTcp::onReadReady);
            }
            else
            {
                delete reply;
            }
        }
    }
}

void CModbusTcp::inputRegisterRead()
{
    qDebug() << "enter input register Read";
    qDebug() << "CPLCCommunicationAgent:" <<QThread::currentThreadId() << QThread::currentThread();
    if(m_pmodbusDevice)
    {
        QModbusDataUnit data(QModbusDataUnit::InputRegisters, 201, 1);

        QModbusReply* reply = m_pmodbusDevice->sendReadRequest(data, 0x1);
        if (nullptr == reply)
        {
            qDebug() << "failed to send data: " << m_pmodbusDevice->errorString();
        }
        else
        {
            qDebug() << "input register Read command have sent";

            if (!reply->isFinished())
            {
                qDebug() << "input register Read command is running";
                connect(reply, &QModbusReply::finished, this, &CModbusTcp::onReadReady);
            }
            else
            {
                qDebug() << "input register Read command immediately reply";
                delete reply;
            }
        }
    }
}

void CModbusTcp::holdingRegsiterRead()
{
    if(m_pmodbusDevice)
    {
        QModbusDataUnit data(QModbusDataUnit::HoldingRegisters, 0, 10);

        auto reply = m_pmodbusDevice->sendReadRequest(data, 0x1);
        if (nullptr == reply)
        {
            qDebug() << "failed to send request data: " << m_pmodbusDevice->errorString();
        }
        else
        {
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, &CModbusTcp::onReadReady);
            }
            else
            {
                delete reply;
            }
        }
    }
}

void CModbusTcp::holdingRegisterWrite(QString strHoldingRegisterToWrite)
{
    if(m_pmodbusDevice)
    {
        QModbusDataUnit writeData(QModbusDataUnit::HoldingRegisters, 210, 10);
        for (uint i = 0; i < writeData.valueCount(); i++)

        qDebug() << "data sent: " << writeData.values();

        QModbusReply* reply = m_pmodbusDevice->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() << "data written: " << data.values();

                        m_strReceived = "";
                        for(auto value: data.values())
                        {
                            m_strReceived += tr("%1 ").arg(value);
                        }

                        emit signalDataReceived(m_strReceived);

                    }

                    reply->deleteLater();
                });
            }
            else
            {
                reply->deleteLater();
            }
        }
        else
        {
            qDebug() << "sendWriteRequest Error: " << reply->errorString();
        }
    }
}

void CModbusTcp::onReadReady()
{
    auto reply = qobject_cast<QModbusReply*>(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);
        }

        emit signalDataReceived(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 CModbusTcp::onModbusStateChanged(QModbusDevice::State state)
{
    bool bConnected=false;
    if(state == QModbusDevice::ConnectedState)
    {
        bConnected=true;
    }
    else
    {
        bConnected=false;
    }

    emit signalStateChanged(bConnected);
}

4.主窗口程序

1)windows.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "cmodbustcp.h"
#include <QTextEdit>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButtonConnect_clicked();

    void on_pushButtonDisconnect_clicked();

    void on_pushButtonCoilRead_clicked();

    void on_pushButtonCoilWrite_clicked();

    void on_pushButtonHoldingRegiserRead_clicked();

    void on_pushButtonHoldingRegisterWrite_clicked();

    void on_pushButtondiscreteInputRead_clicked();

    void on_pushButtoninputRegisterRead_clicked();


    void slotDataReceived(QString strData);

private:
    Ui::MainWindow *ui;

    CModbusTcp *m_pModbusTcp;
    QString m_strDataReceived;

    QTextEdit *m_currentTextEdit;
};

#endif // MAINWINDOW_H

2)windows.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>

#define DELETE_AND_SET_NULL(pointer) if(pointer != nullptr) { delete pointer; pointer = nullptr;};
#define DELETE_AND_SET_NULL_ARRAY(pointer) if(pointer != nullptr) { delete[] pointer; pointer = nullptr;};

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_currentTextEdit = nullptr;

    m_pModbusTcp = new CModbusTcp();

    connect(m_pModbusTcp,SIGNAL(signalDataReceived(QString)), this, SLOT(slotDataReceived(QString)));
}

MainWindow::~MainWindow()
{
    delete ui;

    if (m_pModbusTcp) {
        m_pModbusTcp->disconnectFromServer();
        delete m_pModbusTcp;
        m_pModbusTcp = nullptr;
    }
}

void MainWindow::slotDataReceived(QString strData)
{
    m_strDataReceived = strData;
    qDebug() << "slot received string data:" << strData;
    if(m_currentTextEdit != nullptr)
    {
        m_currentTextEdit->clear();
        m_currentTextEdit->append(m_strDataReceived);
    }

}


void MainWindow::on_pushButtonConnect_clicked()
{
    if(m_pModbusTcp != nullptr)
    {
        bool bres = m_pModbusTcp->connect2Server(ui->lineEditIP->text(),ui->lineEditPort->text());
        if(bres)
        {
            ui->textEditConnectStatus->append("PLC connect OK");
        } else {
            ui->textEditConnectStatus->append("PLC connect Fail");
        }
    }
}

void MainWindow::on_pushButtonDisconnect_clicked()
{
    if(m_pModbusTcp != nullptr)
    {
        m_pModbusTcp->disconnectFromServer();
        ui->textEditConnectStatus->append("Disconnect from PLC");
    }
}

void MainWindow::on_pushButtonCoilRead_clicked()
{
    if(m_pModbusTcp != nullptr)
    {
        QString strAddr = ui->lineEditCoilReadAddr->text();
        QString strNum =  ui->lineEditCoilReadNum->text();
        QString strServerID = ui->lineEditServerID->text();
        m_pModbusTcp->coilRead(strAddr.toInt(),strNum.toInt(),strServerID.toInt());

        m_currentTextEdit =  ui->textEditCoilRead;
    }
}

void MainWindow::on_pushButtonCoilWrite_clicked()
{
    if(m_pModbusTcp != nullptr)
    {
        QString strAddr = ui->lineEditCoilWriteAddr->text();
        QString strSentData =  ui->lineEditCoilWriteData->text();
        QString strServerID = ui->lineEditServerID2->text();
        m_pModbusTcp->coilWrite(strAddr.toInt(),strSentData,strServerID.toInt());

        m_currentTextEdit =  ui->textEditCoilWrite;
    }
}

void MainWindow::on_pushButtonHoldingRegiserRead_clicked()
{

}

void MainWindow::on_pushButtonHoldingRegisterWrite_clicked()
{

}

void MainWindow::on_pushButtondiscreteInputRead_clicked()
{

}

void MainWindow::on_pushButtoninputRegisterRead_clicked()
{

}

5. 主程序

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值