Qt下使用ModbusTcp通信协议进行PLC线圈/保持寄存器的读写(32位有符号数)

2024-04-27 1527阅读

系列文章目录

提示:这里是该系列文章的所有文章的目录

第一章:Qt下使用ModbusTcp通信协议进行PLC线圈/保持寄存器的读写(32位有符号数)

第二章:Qt下使用modbus-c库实现PLC线圈/保持寄存器的读写


文章目录

  • 系列文章目录
  • 前言
  • 一、引入Modbus模块
  • 二、Modbus设备的连接
  • 三、各寄存器数据的读取
  • 四、各寄存器数据的写入
  • 五、示例完整代码
  • 总结

    前言

    本文主要讲述了使用Qt的Modbus模块来进行ModbusTcp的通信,实现对PLC的线圈寄存器和保持寄存器的读写,基于TCP/IP的Modbus协议的内容我就不做过多解释了,详见参考文章。在本文示例中采用QModbusTcpClient类作为Modbus客户端(主站),PLC作为从站,封装了一个自己的MyModbus类,希望可以帮助到大家,如有错误之处,欢迎大家批评指正。

    项目效果

    Qt下使用ModbusTcp通信协议进行PLC线圈/保持寄存器的读写(32位有符号数)


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、引入Modbus模块

    1.这里我实现了自己的MyModbus类的封装,使用了pri子模块的方式,也是方便日后进行此模块的复用

    pri中引入Modbus模块:

    MyModbus.pri

    QT   += serialbus serialport
    

    MyModbus类中添加相关头文件

    #include 
    #include 
    

    二、Modbus设备的连接

    1.ModbusTcp的连接只需要配置好连接参数IP+Port

    //判断当前连接状态是否为断开状态
    if(myClient->state() != QModbusDevice::ConnectedState)
    {
        //配置ModbusTcp的连接参数IP+Port
        myClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter,ip);
        myClient->setConnectionParameter(QModbusDevice::NetworkPortParameter,port);
        myClient->connectDevice();
    }
    

    三、各寄存器数据的读取

    1.Modbus中有4种操作对象,这4种都能进行读取操作:线圈、离散输入、保持寄存器、输入寄存器

    //读取modbus设备各寄存器数据
    //typeNum:1_线圈 2_离散输入 3_保持 4_输入
    bool MyModbus::readModbusData(int typeNum,int startAdd,quint16 numbers)
    {
        if(myClient->state() != QModbusDevice::ConnectedState)
        {
            return false;
        }
        //确定寄存器类型
        QModbusDataUnit ReadUnit;
        if(typeNum == 1)
        {
            ReadUnit = QModbusDataUnit(QModbusDataUnit::Coils,startAdd,numbers);
        }
        else if(typeNum == 2)
        {
            ReadUnit = QModbusDataUnit(QModbusDataUnit::DiscreteInputs,startAdd,numbers);
        }
        else if(typeNum == 3)
        {
            ReadUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters,startAdd,numbers);
        }
        else if(typeNum == 4)
        {
            ReadUnit = QModbusDataUnit(QModbusDataUnit::InputRegisters,startAdd,numbers);
        }
        else
        {
            LOGDEBUG
            if(!reply-isFinished())
            {
                if((typeNum == 1) || (typeNum == 2))
                {
                    QObject::connect(reply,&QModbusReply::finished,this,&MyModbus::slot_readReadyCoils);   //读取线圈
                }
                if((typeNum == 3) || (typeNum == 4))
                {
                    QObject::connect(reply,&QModbusReply::finished,this,&MyModbus::slot_readReadyRegisters);   //读取寄存器
                }
                //reply-deleteLater();
                return true;
            }
            else
            {
                reply-deleteLater();
                return false;
            }
        }
        else
        {
            LOGDEBUG
        if(myClient-state() != QModbusDevice::ConnectedState)
        {
            return false;
        }
        //确定寄存器类型
        QModbusDataUnit writeUnit;
        if(typeNum == 1)
        {
            writeUnit = QModbusDataUnit(QModbusDataUnit::Coils,startAdd,1);   //写入一个数据
            writeUnit.setValue(0,writeNum);
            //单写
            //bool ok;
            //quint16 hexData = writeData.toInt(&ok,16);   //转16进制
        }
        else if(typeNum == 2)
        {
            writeUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters,startAdd,2);   //写入两个数据
            quint16 uData16[2] = {0};
            uData16[0] = writeNum & 0xffff;
            uData16[1] = (writeNum  16) & 0xffff;
            writeUnit.setValue(0,uData16[0]);
            writeUnit.setValue(1,uData16[1]);
            //LOGDEBUG
            LOGDEBUG
            if(!reply-isFinished())
            {
                connect(reply,&QModbusReply::finished,this,[reply]()
                {
                    if(reply-error() == QModbusDevice::NoError)
                    {
                        reply-deleteLater();
                        return true;
                    }
                    else
                    {
                        LOGDEBUG
                reply-deleteLater();
                return false;
            }
        }
        else
        {
            LOGDEBUGTARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    
        Q_OBJECT
    public:
        explicit MyModbus(QObject *parent = nullptr);
        ~MyModbus();
        void initModbus();
        void connectToModbus(QString ip,int port);
        bool readModbusData(int typeNum,int startAdd,quint16 numbers);
        bool writeModbusData(int typeNum,int startAdd,int writeNum);
    signals:
        void signal_stateChanged(bool flag);
        void signal_readCoils(QVector
        this-initModbus();
    }
    MyModbus::~MyModbus()
    {
    }
    //初始化
    void MyModbus::initModbus()
    {
        myClient = new QModbusTcpClient();
        //connect(myClient,SIGNAL(stateChanged()),this,SLOT(slot_stateChanged()));
        connect(myClient,&QModbusClient::stateChanged,this,&MyModbus::slot_stateChanged);
    }
    //连接到modbus设备
    void MyModbus::connectToModbus(QString ip,int port)
    {
        if(!myClient)
        {
            return;
        }
        //判断当前连接状态是否为断开状态
        if(myClient-state() != QModbusDevice::ConnectedState)
        {
            //配置ModbusTcp的连接参数IP+Port
            myClient-setConnectionParameter(QModbusDevice::NetworkAddressParameter,ip);
            myClient-setConnectionParameter(QModbusDevice::NetworkPortParameter,port);
            myClient-connectDevice();
        }
        //else
        //{
        //    myClient-disconnectDevice();
        //}
    }
    //读取modbus设备各寄存器数据
    //typeNum:1_线圈 2_离散输入 3_保持 4_输入
    bool MyModbus::readModbusData(int typeNum,int startAdd,quint16 numbers)
    {
        if(myClient-state() != QModbusDevice::ConnectedState)
        {
            return false;
        }
        //确定寄存器类型
        QModbusDataUnit ReadUnit;
        if(typeNum == 1)
        {
            ReadUnit = QModbusDataUnit(QModbusDataUnit::Coils,startAdd,numbers);
        }
        else if(typeNum == 2)
        {
            ReadUnit = QModbusDataUnit(QModbusDataUnit::DiscreteInputs,startAdd,numbers);
        }
        else if(typeNum == 3)
        {
            ReadUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters,startAdd,numbers);
        }
        else if(typeNum == 4)
        {
            ReadUnit = QModbusDataUnit(QModbusDataUnit::InputRegisters,startAdd,numbers);
        }
        else
        {
            LOGDEBUG
            if(!reply-isFinished())
            {
                if((typeNum == 1) || (typeNum == 2))
                {
                    QObject::connect(reply,&QModbusReply::finished,this,&MyModbus::slot_readReadyCoils);   //读取线圈
                }
                if((typeNum == 3) || (typeNum == 4))
                {
                    QObject::connect(reply,&QModbusReply::finished,this,&MyModbus::slot_readReadyRegisters);   //读取寄存器
                }
                //reply-deleteLater();
                return true;
            }
            else
            {
                reply-deleteLater();
                return false;
            }
        }
        else
        {
            LOGDEBUG
        if(myClient-state() != QModbusDevice::ConnectedState)
        {
            return false;
        }
        //确定寄存器类型
        QModbusDataUnit writeUnit;
        if(typeNum == 1)
        {
            writeUnit = QModbusDataUnit(QModbusDataUnit::Coils,startAdd,1);   //写入一个数据
            writeUnit.setValue(0,writeNum);
            //单写
            //bool ok;
            //quint16 hexData = writeData.toInt(&ok,16);   //转16进制
        }
        else if(typeNum == 2)
        {
            writeUnit = QModbusDataUnit(QModbusDataUnit::HoldingRegisters,startAdd,2);   //写入两个数据
            quint16 uData16[2] = {0};
            uData16[0] = writeNum & 0xffff;
            uData16[1] = (writeNum  16) & 0xffff;
            writeUnit.setValue(0,uData16[0]);
            writeUnit.setValue(1,uData16[1]);
            //LOGDEBUG
            LOGDEBUG
            if(!reply-isFinished())
            {
                connect(reply,&QModbusReply::finished,this,[reply]()
                {
                    if(reply-error() == QModbusDevice::NoError)
                    {
                        reply-deleteLater();
                        return true;
                    }
                    else
                    {
                        LOGDEBUG
                reply-deleteLater();
                return false;
            }
        }
        else
        {
            LOGDEBUG
        LOGDEBUG
            emit signal_stateChanged(true);
        }
        else if(myClient-state() == QModbusDevice::UnconnectedState)
        {
            emit signal_stateChanged(false);
        }
    }
    //接收到读取线圈/离散输入寄存器请求后执行的槽函数
    void MyModbus::slot_readReadyCoils()
    {
        QVector
            LOGDEBUG
            const QModbusDataUnit unit = reply-result();
            vAllData = unit.values();
            emit signal_readCoils(vAllData);
        }
        else
        {
            LOGDEBUG
        QModbusReply *reply = qobject_cast
            LOGDEBUG
            const QModbusDataUnit unit = reply-result();
            auto valueList = unit.values();
            int nSize = valueList.size();
            if(nSize == 2)
            {
                quint16 uData16[2] = {0};
                uData16[0] = valueList[0];
                uData16[1] = valueList[1];
                int resultNum = uData16[0] | (uData16[1] 
                LOGDEBUG
            LOGDEBUG class Widget; }
    QT_END_NAMESPACE
    class Widget : public QWidget
    {
        Q_OBJECT
    public:
        Widget(QWidget *parent = nullptr);
        ~Widget();
        void initWidget();
    private slots:
        void slot_stateChanged(bool flag);
        void slot_readCoils(QVector
        ui-setupUi(this);
        this-initWidget();
    }
    Widget::~Widget()
    {
        delete ui;
    }
    void Widget::initWidget()
    {
        //初始化MyModbus对象
        m_myModsbus = new MyModbus();
        connect(m_myModsbus,SIGNAL(signal_stateChanged(bool)),this,SLOT(slot_stateChanged(bool)));
        connect(m_myModsbus,SIGNAL(signal_readCoils(QVector
        if(flag)
        {
            ui-lb_state-setText("连接成功");
            ui-te_show-appendPlainText(QTime::currentTime().toString("hh:mm:ss: ") + "连接成功");
            QMessageBox::warning(this,"警告","连接成功!");
        }
        else
        {
            ui-lb_state-setText("连接断开");
            ui-te_show-appendPlainText(QTime::currentTime().toString("hh:mm:ss: ") + "连接断开");
            QMessageBox::warning(this,"警告","连接断开!");
        }
    }
    void Widget::slot_readCoils(QVector
        LOGDEBUG
            LOGDEBUG
        LOGDEBUG
        QString ip = ui-le_ip-text();
        int port = ui-le_port-text().toInt();
        LOGDEBUG
        int startAdd = ui-le_addressM-text().toInt();
        LOGDEBUG
            QMessageBox::warning(this,"警告","M区数据读取失败!");
        }
    }
    void Widget::on_pb_writeM_clicked()
    {
        int startAdd = ui-le_addressM-text().toInt();
        int writeNum = ui-le_dataM-text().toInt();
        LOGDEBUG
            QMessageBox::warning(this,"警告","M区数据写入失败!");
        }
    }
    void Widget::on_pb_readD_clicked()
    {
        int startAdd = ui-le_addressD-text().toInt();
        LOGDEBUG
            QMessageBox::warning(this,"警告","D区数据读取失败!");
        }
    }
    void Widget::on_pb_writeD_clicked()
    {
        int startAdd = ui-le_addressD-text().toInt();
        int writeNum = ui-le_dataD-text().toInt();;
        LOGDEBUG
            QMessageBox::warning(this,"警告","D区数据写入失败!");
        }
    }
    
        static QMutex mutex;
        mutex.lock();
        //初始化log文件夹
        QString logFilePath = QCoreApplication::applicationDirPath() + "/LogFile/";
        QDir dstDir(logFilePath);
        if(!dstDir.exists())
        {
            if(!dstDir.mkpath(logFilePath))
            {
                LOGDEBUG
                LOGDEBUG
            QString debugDateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
            debugMsg = QString("%1\n%2%3").arg(debugDateTime).arg(msg).arg(context.function);
        }
        //保存文件
        QString curDate = QDate::currentDate().toString("yyyyMMdd");
        QString logFile = logFilePath + "log_" + curDate + ".txt";
        QFile file(logFile);
        file.open(QIODevice::WriteOnly | QIODevice::Append);
        QTextStream textStream(&file);
        textStream 
        QApplication a(argc, argv);
        qInstallMessageHandler(outputMessage);
        Widget w;
        w.show();
        return a.exec();
    }
    
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]