一种基于QT5.12+VS2015的ModbusTcp客户端轮询方法

一种基于QT5.12+VS2015的ModbusTcp客户端轮询方法

服务端:西门子PLC-1200
客户端:Win10+QT5.12.1+VS2015

1.ModbusTcp寄存器规划

(1)客户端00000(线圈:可读可写) -> 服务端10000(离散输入)
(2)客户端10000(离散输入:只读) -> 服务端00000(线圈)
(3)客户端30000(输入寄存器:只读) -> 服务端40000(保持寄存器)
(4)客户端40000(保持寄存器:可读可写) -> 服务端30000(输入寄存器)

2.控制规则

(1)点控:客户端写线圈(00001置1) -> 客户端读线圈(直到00001为1) -> 客户端写线圈(00001置0)
(2)开关:客户端写线圈(00001置1)/ 客户端写线圈(00001置0)
(3)闭环:客户端写线圈(00001置1) -> 客户端读线圈 ->(服务端执行功能中) -> 客户端读离散输入(直到10001为1)-> 客户端写线圈(00001置0)
(4)监控状态:客户端读离散输入
(5)写入参数:客户端写保持寄存器(40001) -> 客户端读保持寄存器(40001)
(6)状态参数:客户端读输入寄存器(30001)

3.Modbus数据长度

ModBus只能有一个主机(TCP客户端),可以有多个从机(TCP服务端)。

3.1.报文请求格式如下:

ModbusRTU:ADU(8字节)=设备地址(1字节)+PDU(5字节)+校验(2字节)
ModbusTCP:ADU(12字节)=MBAP(7字节)+PDU(5字节)

        MBAP(7字节)=事务标(2字节)+协议(2字节)+长度(2字节)+单元(1字节)
        PDU(5字节)=功能码(1字节)+起始地址(2字节)+数据长度(2字节)

3.2.报文响应格式如下:

ModbusRTU:ADU(256字节)=地址(1字节)+PDU(253字节)+校验(2字节)
ModbusTCP:ADU(260字节)=MBAP(7字节)+PDU(253字节)

        MBAP(7字节)=事务标(2字节)+协议(2字节)+长度(2字节)+单元(1字节)
        PDU(253字节)=功能码(1字节)+数据(252字节)
        数据(252字节)=数据长度(1字节)+数据储存区(251字节)

3.3.Modbus TCP和Modbus RTU的通信格式:

差别一是:ModbusRTU最后带两个字节的CRC校验,而ModbusTCP没有;
差别二是:ModbusTCP增加一个7个字节的MBAP的报文头

3.4.存储区数据结构如下:

线圈:1位 = 1/8字节
寄存器:16位 = 2字节

3.5.根据西门子说明可知一次读取数据最大个数如下:

线圈:2000个
离散寄存器:2000个
保持寄存器:125个
输入寄存器:125个

4.服务端配置

4.1.设置DB区

在这里插入图片描述
在这里插入图片描述

4.2.服务端模块

在这里插入图片描述
在这里插入图片描述开通4个数据储存区分别对应服务端01、02、03、04功能码,对应客户端线圈、离散输入、保持寄存器、输入寄存器,每个数据储存区分配500个数据长度

4.3.SCL赋值

“离散输入10001”.“100”[01] := (状态地址);
“输入继存器30001”.“300”[01] := (状态参数地址);
(功能线圈地址) := “线圈00001”.“000”[01] ;
(功能参数地址):= “保持继存器40001”.“400”[01];

4.4.其他设置

IP、Port、设备号、设备标识

5.基于QT的ModbusTCP

5.1.模块设计

/*************************************************************************************************************************************************
**Copyright(C), 2020-2025, bjtds.
**Version:2.0
**Author: dz
**Date:2021.12.27
**Description:
**Others:                          "CModbusTcpClient"
                              ____________________________
              Connect_Device->|REQ          |        DONE|->Done
           Disconnect_Device->|DISCONNECT   |       ERROR|->Error
                  Read/Write->|MB_MODE      |      STATUS|->status
                        addr->|MB_DATA_ADDR |            |
                        size->|MB_DATA_LEN  |            |
                      value ->|MB_DATA_PTR  |            |
                  ip,port,id->|CONNECT      |            |
                              ----------------------------
*************************************************************************************************************************************************/

5.2.Public_Header.h

#pragma once
/*************************************************************************************************************************************************
**Function:RGV功能映射
*************************************************************************************************************************************************/
#define RGV_Fuction_0      0//通信控制(线圈)                (离散:为1时远程控制,PLC端无控制))
#define RGV_Fuction_7      7//主动力位置清零(线圈,工控机立即复位)(离散)
#define RGV_Fuction_8      8//主动力故障复位(线圈,工控机立即复位)(离散)
#define RGV_Fuction_9      9//主动力手动左行(线圈,点控)          (离散:为1运行中)
#define RGV_Fuction_10     10//主动力手动右行(线圈,点控)         (离散:为1运行中)
#define RGV_Fuction_11     11//正向连续运行(线圈,工控机立即复位) (离散:为1运行中)
#define RGV_Fuction_12     12//返向连续运行(线圈,工控机立即复位) (离散:为1运行中)
#define RGV_Fuction_13     13//返向连续运行再启动(线圈,工控机立即复位)(离散:为1运行中)
#define RGV_Fuction_14     14//急停(线圈,工控机立即复位)(离散)
#define RGV_Fuction_15     15//左机器人开机(线圈,工控机立即复位)(离散:为1完成开机)
#define RGV_Fuction_16     16//左机器人关机(线圈,工控机立即复位)(离散:为1完成关机)
#define RGV_Fuction_17     17//右机器人开机(线圈,工控机立即复位)(离散:为1完成开机)
#define RGV_Fuction_18     18//右机器人关机(线圈,工控机立即复位)(离散:为1完成关机)
#define RGV_Fuction_19     19//上电(线圈,工控机立即复位)        (离散:为1所有设备上电处于待机状态)
#define RGV_Fuction_20     20//充电回原点(线圈,工控机立即复位)  
#define RGV_Fuction_21     21//风刀(线圈,工控机立即复位)  
#define RGV_Fuction_22     22//清扫电机(线圈,工控机立即复位)  
#define RGV_Fuction_24     24//轴1移动(线圈,工控机立即复位)(离散:为为1移动中)
#define RGV_Fuction_25     25//轴2移动(线圈,工控机立即复位)(离散:为1移动中)
#define RGV_Fuction_26     26//开始充电(线圈,工控机立即复位)(离散:为1时远程控制,PLC端无控制)
#define RGV_Fuction_27     27//结束充电(线圈,工控机立即复位)(离散:为1时远程控制,PLC端无控制)
#define RGV_Date_0     0//左升降台速度
#define RGV_Date_1     2//左升降台位置
#define RGV_Date_2     4//右升降台速度
#define RGV_Date_3     6//右升降台位置
#define RGV_Date_4     8//轴1移动距离
#define RGV_Date_5     9//轴2移动距离
***************************************************************
**Function:包含目录
*************************************************************************************************************************************************/
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <SDKDDKVer.h>
#include <Windows.h>
using namespace std;

#include <QMap>
#include <QDir>
#include <QFile>
#include <Qbrush>
#include <QDebug>
#include <QTimer>
#include <QWidget>
#include <QObject>
#include <QThread>
#include <QVector>
#include <Qpainter>
#include <QtCharts>
#include <QVariant>
#include <QDateTime>
#include <QKeyEvent>
#include <QJsonValue>
#include <QByteArray>
#include <QJsonArray>
#include <QEventLoop>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QMainWindow>
#include <QJsonObject>
#include <QPolarChart>
#include <QMessageBox>
#include <QPainterPath>
#include <QHostAddress>
#include <QApplication>
#include <QJsonDocument>
#include <QstackedWidget>
#include <QScatterSeries>
#include <QAbstractSocket>
#include <QModbusDataUnit>
#include <QConicalGradient>
#include <QModbusTcpClient>

5.3.RGV_Client.h

在这里插入代码片
#include "Variable.h"
#include "Public_Header.h"

class c_RGV_Client : public QObject
{
    Q_OBJECT
public:
    explicit c_RGV_Client(QObject *parent = nullptr);
	virtual ~c_RGV_Client();

signals:
    void Connect_Done();//连接到服务器
    void Disconnect_Done();//断开连接
    void Read_Coils_Done(QJsonObject value);//读线圈完成
    void Read_DiscreteInputs_Done(QJsonObject value);//读离散输入完成
    void Read_InputRegisters_Done(QJsonObject value);//读输入寄存器完成
    void Read_HoldingRegisters_Done(QJsonObject value);//读保持寄存器完成
    void Write_Coils_Done(); //写线圈完成
    void Write_HoldingRegisters_Done();//写保持寄存器完成
    void Read_Coils_Error();//读线圈错误
    void Read_DiscreteInputs_Error();//读离散输入错误
    void Read_InputRegisters_Error();//读输入寄存器错误
    void Read_HoldingRegisters_Error();//读保持寄存器错误
    void Write_Coils_Error(); //写线圈完成
    void Write_HoldingRegisters_Error();//写保持寄存器错误
    void Status(int state);//通讯状态

public slots:
    void Init();//子线程初始化
    void Connect_Device(QString ip, int port);//连接到服务器
    void Disconnect_Device();//断开连接
    void Read_Coils(int addr, int size);//读线圈
    void Read_DiscreteInputs(int addr, int size);//读离散输入
    void Read_InputRegisters(int addr, int size);//读输入寄存器
    void Read_HoldingRegisters(int addr, int size);//读保持寄存器
    void Write_Coils(int addr, QJsonObject value, int size); //写线圈
    void Write_HoldingRegisters(int addr, QJsonObject value, int size);//写保持寄存器

private slots:
    void State_Changed();//状态改变
    void Read_Ready_Coils();//准备读线圈
    void Read_Ready_DiscreteInputs();//准备散输入完成
    void Read_Ready_InputRegisters();//准备输入寄存器错误
    void Read_Ready_HoldingRegisters();//准备寄存器错误

private:
    QModbusTcpClient *m_ModbusDevice;
	QJsonObject m_Coils;//数据缓存区间
	QJsonObject m_DiscreteInputs;//数据缓存区间
	QJsonObject m_InputRegisters;//数据缓存区间
	QJsonObject m_HoldingRegisters;//数据缓存区间
};

5.4.RGV_Client.cpp

#pragma execution_character_set("utf-8")
#include "RGV_Client.h"
/*************************************************************************************************************************************************
**Function:    构造函数
**Description: 初始化成员变量
**Input:       无输入
**Output:      无输出
**Return:      无返回
**Others:      构造函数初始化在主线程实例化中完成,故在子线程中运行时,成员函数的初始化不能在构造函数中完成
*************************************************************************************************************************************************/
c_RGV_Client::c_RGV_Client(QObject *parent) : QObject(parent)
{

}
/*************************************************************************************************************************************************
**Function:    析构函数
**Description: 析构成员变量
**Input:       无输入
**Output:      无输出
**Return:      无返回
**Others:      析构成员变量后,再次操作时需要重新实例化
*************************************************************************************************************************************************/
c_RGV_Client::~c_RGV_Client()
{
	m_ModbusDevice->deleteLater();
}
/*************************************************************************************************************************************************
**Function:    初始化函数
**Description: 线程的构造函数
**Input:       无输入
**Output:      无输出
**Return:      无返回
**Others:
*************************************************************************************************************************************************/
void c_RGV_Client::Init()
{
    //对象实列化
    m_ModbusDevice = new QModbusTcpClient;
    //状态改变
    QObject::connect(m_ModbusDevice, &QModbusTcpClient::stateChanged, this, &c_RGV_Client::State_Changed);
    //错误诊断
    QObject::connect(m_ModbusDevice, &QModbusTcpClient::errorOccurred, this, &c_RGV_Client::Status);
}
/*************************************************************************************************************************************************
**Function:    Connect_Device()
**Description: 连接modbustcp服务器
**Input:       -> ip
               -> port
**Output:      onStateChanged -> connectDone    连接成功
                              -> disconnectDone 断开成功
               status -> 0 已连接
                      -> 1 读取操作期间发生错误。
                      -> 2 写入操作期间发生错误。
                      -> 3 尝试打开后端时出错。
                      -> 4 尝试设置配置参数时出错。
                      -> 5 I/O期间发生超时。I/O操作未在给定的时间范围内完成。
                      -> 6 发生Modbus特定协议错误。
                      -> 7 由于设备断开连接,回复被中止。
                      -> 8 发生未知错误
                      -> 9 设备已断开连接。
                      ->10 正在连接设备。
                      ->11 设备正在关闭
**Return:      无返回
**Others:      二次调用时,如果已连接,则会先断开原来的连接
*************************************************************************************************************************************************/
void c_RGV_Client::Connect_Device(QString ip, int port)
{
    //如果已连接,则返回
    if (m_ModbusDevice->state() == QModbusDevice::ConnectedState)
    {
        return;
    }
    //配置modbus tcp的连接参数 IP + Port
    m_ModbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ip);
    m_ModbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
    //再设置从机无响应时的动作
    m_ModbusDevice->setTimeout(1000);//从设备回复信息的超时时间
    m_ModbusDevice->setNumberOfRetries(2);//重复发送次数
    m_ModbusDevice->connectDevice();
}
/*************************************************************************************************************************************************
**Function:    Disconnect_Device()
**Description: 断开modbustcp服务器
**Input:       无输入
**Output:      onStateChanged、status
**Return:      无返回
**Others:      如果未连接,则会直接返回
*************************************************************************************************************************************************/
void c_RGV_Client::Disconnect_Device()
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    m_ModbusDevice->disconnectDevice();
}
/*************************************************************************************************************************************************
**Function:    readCoils(ModbusTcpDataBlock dataBlock)
**Description: 读线圈寄存器(读写,一般为继电器的控制)
**Input:       QJsonObject dataBlock -> readCoilsAddr
                                     -> readCoilsSize
                                     -> id
**Output:      status、readCoilsError、readReadyCoils
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Read_Coils(int addr, int size)
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    if(size == 0)
    {
        emit Read_Coils_Error();
        return;
    }
    QModbusDataUnit ReadUnit(QModbusDataUnit::Coils, addr, size);
    auto *reply = m_ModbusDevice->sendReadRequest(ReadUnit, 1);
    if(reply)
    {
        if (!reply->isFinished())
        {
          QObject::connect(reply, &QModbusReply::finished, this, &c_RGV_Client::Read_Ready_Coils);
        }
        else
        {
            reply->deleteLater();
            emit Read_Coils_Error();
            return;
        }
    }
    else
    {
        reply->deleteLater();
        emit Read_Coils_Error();;
        return;
    }
}
/*************************************************************************************************************************************************
**Function:    readDiscreteInputs(QJsonObject dataBlock)
**Description: 读离散输入寄存器(只读,通常为开关量输入)
**Input:       QJsonObject dataBlock -> readDiscreteInputsAddr
                                     -> readDiscreteInputsSize
                                     -> id
**Output:      status、readDiscreteInputsError、readReadyDiscreteInputs
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Read_DiscreteInputs(int addr, int size)
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    if(size == 0)
    {
        emit Read_DiscreteInputs_Error();
        return;
    }
    QModbusDataUnit ReadUnit(QModbusDataUnit::DiscreteInputs, addr, size);
    auto *reply = m_ModbusDevice->sendReadRequest(ReadUnit, 1);
    if(reply)
    {
        if (!reply->isFinished())
        {
          QObject::connect(reply, &QModbusReply::finished, this, &c_RGV_Client::Read_Ready_DiscreteInputs);
        }
        else
        {
            reply->deleteLater();
            emit Read_DiscreteInputs_Error();
            return;
        }
    }
    else
    {
        reply->deleteLater();
        emit Read_DiscreteInputs_Error();
        return;
    }
}
/*************************************************************************************************************************************************
**Function:    readInputRegisters(ModbusTcpDataBlock dataBlock)
**Description: 读输入寄存器(只读,一般为模拟量输入)
**Input:       QJsonObject dataBlock -> readInputRegistersAddr
                                     -> readInputRegistersSize
                                     -> id
**Output:      status、readInputRegistersError、readReadyInputRegisters
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Read_InputRegisters(int addr, int size)
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    if(size == 0)
    {
        emit Read_InputRegisters_Error();
        return;
    }
    QModbusDataUnit ReadUnit(QModbusDataUnit::InputRegisters, addr, size);
    auto *reply = m_ModbusDevice->sendReadRequest(ReadUnit, 1);
    if(reply)
    {
        if (!reply->isFinished())
        {
          QObject::connect(reply, &QModbusReply::finished, this, &c_RGV_Client::Read_Ready_InputRegisters);
        }
        else
        {
            reply->deleteLater();
            emit Read_InputRegisters_Error();
            return;
        }
    }
    else
    {
        reply->deleteLater();
        emit Read_InputRegisters_Error();
        return;
    }
}
/*************************************************************************************************************************************************
**Function:    readHoldingRegisters(ModbusTcpDataBlock dataBlock)
**Description: 读保持寄存器(读写,一般状态参数控制)
**Input:       QJsonObject dataBlock -> readHoldingRegistersAddr
                                     -> readHoldingRegistersSize
                                     -> id
**Output:      status、readHoldingRegistersError、readReadyHoldingRegisters
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Read_HoldingRegisters(int addr, int size)
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    if(size == 0)
    {
        emit Read_HoldingRegisters_Error();
        return;
    }
    QModbusDataUnit ReadUnit(QModbusDataUnit::HoldingRegisters, addr, size);
    auto *reply = m_ModbusDevice->sendReadRequest(ReadUnit, 1);
    if(reply)
    {
        if (!reply->isFinished())
        {
          QObject::connect(reply, &QModbusReply::finished, this, &c_RGV_Client::Read_Ready_HoldingRegisters);
        }
        else
        {
            reply->deleteLater();
            emit Read_HoldingRegisters_Error();
            return;
        }
    }
    else
    {
        reply->deleteLater();
        emit Read_HoldingRegisters_Error();
        return;
    }
}
/*************************************************************************************************************************************************
**Function:    writeCoils(int addr, QJsonObject value, quint16 size)
**Description: 写线圈寄存器(读写,一般为继电器的控制)
**Input:       ->addr 地址
               ->value 值
               ->size 个数
**Output:      status、writeCoilsError、writeCoilsDone
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Write_Coils(int addr, QJsonObject value, int size)
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    if(size <= 0)
    {
        emit Write_HoldingRegisters_Error();
        return;
    }
    //写,地址,写多少位
    QModbusDataUnit writeUnit(QModbusDataUnit::Coils, addr, size);
    //该位置,数据
    for(int i=0; i<size; i++)
    {
        QString address = QString::number(addr + i);//当前数据地址
        quint16 data = quint16(value.value(address).toInt());
        writeUnit.setValue(i, data);
    }
    //发送校验 1 代表设备地址
    if(auto *reply = m_ModbusDevice->sendWriteRequest(writeUnit, 1))
    {
        if (!reply->isFinished())
        {
            //如果接收到响应信息
            QObject::connect(reply, &QModbusReply::finished, this, [&, reply]()
            {
                if (reply->error() == QModbusDevice::NoError)
                {
                    //接收到的响应信无错误,发送完成信号
                    emit Write_Coils_Done();
                }
                else
                {
                    reply->deleteLater();
                    emit Write_Coils_Error();
                    return;
                }
                reply->deleteLater();
            });
        }
        else
        {
            reply->deleteLater();
            emit Write_Coils_Error();
            return;
        }
    }
}
/*************************************************************************************************************************************************
**Function:    writeHoldingRegisters(int addr, QJsonObject value, quint16 size)
**Description: 写保持寄存器(读写,一般状态参数控制)
**Input:       ->addr 地址
               ->value 值
               ->size 个数
**Output:      status、writeHoldingRegistersError、writeHoldingRegistersDone
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Write_HoldingRegisters(int addr, QJsonObject value, int size)
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    if(size <= 0)
    {
        emit Write_HoldingRegisters_Error();
        return;
    }

    //写,地址,写多少位
    QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, addr, size);
    //该位置,数据
    for(int i=0; i<size; i++)
    {
        QString address = QString::number(addr + i);//当前数据地址
        quint16 data = quint16(value.value(address).toInt());
        writeUnit.setValue(i, data);
    }
    //发送校验 1 代表设备地址
    if(auto *reply = m_ModbusDevice->sendWriteRequest(writeUnit, 1))
    {
        if (!reply->isFinished())
        {
            //如果接收到响应信息
            QObject::connect(reply, &QModbusReply::finished, this, [&, reply]()
            {
                if (reply->error() == QModbusDevice::NoError)
                {
                    //接收到的响应信无错误,发送完成信号
                    emit Write_HoldingRegisters_Done();
                }
                else
                {
                    reply->deleteLater();
                    emit Write_HoldingRegisters_Error();
                    return;
                }
                reply->deleteLater();
            });
        }
        else
        {
            reply->deleteLater();
            emit Write_HoldingRegisters_Error();
            return;
        }
    }
}
/*************************************************************************************************************************************************
**Function:    onStateChanged()
**Description: modbustcp连接状态改变
**Input:       无输入
**Output:      connectDone、disconnectDone、status
**Return:      无返回
**Others:      已连接、连接中、已断开、断开中
*************************************************************************************************************************************************/
void c_RGV_Client::State_Changed()
{
    if(m_ModbusDevice->state() == QModbusDevice::ConnectedState)
    {
        emit Status(0);
        emit Connect_Done();
    }
    if(m_ModbusDevice->state() == QModbusDevice::UnconnectedState)
    {
        emit Status(9);
        emit Disconnect_Done();
    }
    if(m_ModbusDevice->state() == QModbusDevice::ConnectingState)
    {
        emit Status(10);
    }
    if(m_ModbusDevice->state() == QModbusDevice::ClosingState)
    {
        emit Status(11);
    }
}
/*************************************************************************************************************************************************
**Function:    readReadyCoils()
**Description: 读线圈寄存器(读写,一般为继电器的控制)
**Input:       readCoils
**Output:      QJsonObject value -> {"地址":值}
               status、readCoilsError、readCoilsDone
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Read_Ready_Coils()
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    auto *reply = qobject_cast<QModbusReply *>(sender());
    if (!reply)
    {
        reply->deleteLater();
        emit Read_Coils_Error();
        return;
    }
    //如果校验无误
    if (reply->error() == QModbusDevice::NoError)
    {
        const QModbusDataUnit writeUnit = reply->result();//获取结果
        int size = int(writeUnit.valueCount());//数据长度
        int addr = writeUnit.startAddress();//数据起始地址
        for(int i=0; i<size; i++)
        {
            QString add = QString::number(addr + i);//当前数据地址
            int data = int(writeUnit.value(i));//当前数据值
            m_Coils.insert(add, data);//记录数据
        }
    }
    //如果校验有误
    else
    {
        reply->deleteLater();
        emit Read_Coils_Error();
        return;
    }
    reply->deleteLater(); //删除答复
    //发送信号
    emit Read_Coils_Done(m_Coils);//输出数据
}
/*************************************************************************************************************************************************
**Function:    readReadyDiscreteInputs()
**Description: 读离散输入寄存器(只读,通常为开关量输入)
**Input:       readDiscreteInputs
**Output:      QJsonObject value -> {"地址":值}
               status、readDiscreteInputsError、readDiscreteInputsDone
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Read_Ready_DiscreteInputs()
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    auto *reply = qobject_cast<QModbusReply *>(sender());
    if (!reply)
    {
        reply->deleteLater();
        emit Read_DiscreteInputs_Error();
        return;
    }
    //如果校验无误
    if (reply->error() == QModbusDevice::NoError)
    {
        const QModbusDataUnit readUnit = reply->result();//获取结果
        int size = readUnit.valueCount();//数据长度
        int addr = readUnit.startAddress();//数据起始地址
        for(int i=0; i<size; i++)
        {
            QString add = QString::number(addr + i);//当前数据地址
            int data = int(readUnit.value(i));//当前数据值
            m_DiscreteInputs.insert(add, data);//记录数据
        }
    }
    //如果校验有误
    else
    {
        reply->deleteLater();
        emit Read_DiscreteInputs_Error();
        return;
    }
    reply->deleteLater(); //删除答复
    //发送信号
    emit Read_DiscreteInputs_Done(m_DiscreteInputs);//输出数据
}
/*************************************************************************************************************************************************
**Function:    readReadyInputRegisters()
**Description: 读输入寄存器(只读,一般为模拟量输入)
**Input:       readInputRegisters
**Output:      QJsonObject value -> {"地址":值}
               status、readInputRegistersError、readInputRegistersDone
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Read_Ready_InputRegisters()
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    auto *reply = qobject_cast<QModbusReply *>(sender());
    if (!reply)
    {
        reply->deleteLater();
        emit Read_InputRegisters_Error();
        return;
    }
    //如果校验无误
    if (reply->error() == QModbusDevice::NoError)
    {
        const QModbusDataUnit readUnit = reply->result();//获取结果
        int size = readUnit.valueCount();//数据长度
        int addr = readUnit.startAddress();//数据起始地址
        for(int i=0; i<size; i++)
        {
            QString add = QString::number(addr + i);//当前数据地址
            int data = int(readUnit.value(i));//当前数据值
            m_InputRegisters.insert(add, data);//记录数据
        }
    }
    //如果校验有误
    else
    {
        reply->deleteLater();
        emit Read_InputRegisters_Error();
        return;
    }
    reply->deleteLater(); //删除答复
    //发送信号
    emit Read_InputRegisters_Done(m_InputRegisters);//输出数据
}
/*************************************************************************************************************************************************
**Function:    readReadyHoldingRegisters()
**Description: 读保持寄存器(读写,一般状态参数控制)
**Input:       readHoldingRegisters
**Output:      QJsonObject value -> {"地址":值}
               status、readHoldingRegistersError、readHoldingRegistersDone
**Return:      无返回
**Others:      采用的是基于ModbusReply的Finished信号,做异步处理
*************************************************************************************************************************************************/
void c_RGV_Client::Read_Ready_HoldingRegisters()
{
    if ((!m_ModbusDevice) || (m_ModbusDevice->state() != QModbusDevice::ConnectedState))
    {
        return;//如果RGV没有连接则提前退出
    }
    auto *reply = qobject_cast<QModbusReply *>(sender());
    if (!reply)
    {
        reply->deleteLater();
        emit Read_HoldingRegisters_Error();
        return;
    }
    //如果校验无误
    if (reply->error() == QModbusDevice::NoError)
    {
        const QModbusDataUnit readUnit = reply->result();//获取结果
        int size = readUnit.valueCount();//数据长度
        int addr = readUnit.startAddress();//数据起始地址
        for(int i=0; i<size; i++)
        {
            QString add = QString::number(addr + i);//当前数据地址
            int data = int(readUnit.value(i));//当前数据值
            m_HoldingRegisters.insert(add, data);//记录数据
        }
    }
    //如果校验有误
    else
    {
        reply->deleteLater();
        emit Read_HoldingRegisters_Error();
        return;
    }
    reply->deleteLater(); //删除答复
    //发送信号
    emit Read_HoldingRegisters_Done(m_HoldingRegisters);//输出数据
}

5.5.在线程中实现轮询RGV_Remote.h

#pragma once
#include "RGV_Client.h"

class c_RGV_Remote : public QObject
{
	Q_OBJECT
public:
	explicit c_RGV_Remote(QObject *parent = nullptr);
	virtual ~c_RGV_Remote();
	QThread *m_RGV_Remote_Thread;
	c_RGV_Client *m_RGV_Remote;

	public slots:
	void Init();
	void Connect();
	void Fuction_0_Set();//通信控制(线圈)
	void Fuction_0_Reset();//通信控制(线圈)
	void Fuction_7();//主动力位置清零(线圈,工控机立即复位)
	void Fuction_8();//主动力故障复位(线圈,工控机立即复位)
	void Fuction_9_Set();//主动力手动左行(线圈,点控)
	void Fuction_9_Reset();//主动力手动左行(线圈,点控)
	void Fuction_10_Set();//主动力手动右行(线圈,点控) 
	void Fuction_10_Reset();//主动力手动右行(线圈,点控) 
	void Fuction_11();//正向连续运行(线圈,工控机立即复位)
	void Fuction_12();//返向连续运行(线圈,工控机立即复位)
	void Fuction_13();//返向连续运行再启动(线圈,工控机立即复位)
	void Fuction_14();//急停(线圈,工控机立即复位)(离散)
	void Fuction_15();//左机器人开机(线圈,工控机立即复位)
	void Fuction_16();//左机器人关机(线圈,工控机立即复位)
	void Fuction_17();//右机器人开机(线圈,工控机立即复位)
	void Fuction_18();//右机器人关机(线圈,工控机立即复位)
	void Fuction_19_Set();//上电(线圈,点控)
	void Fuction_19_Reset();//上电(线圈,点控)
	void Fuction_20();//充电回原点(线圈,工控机立即复位)
	void Fuction_21_Set();//风刀电机开
	void Fuction_21_Reset();//风刀电机关
	void Fuction_22_Set();//清扫电机开
	void Fuction_22_Reset();//清扫电机关
	void Fuction_24();//轴1移动(线圈,工控机立即复位)
	void Fuction_25();//轴2移动(线圈,工控机立即复位)
	void Fuction_26();//开始充电(线圈,工控机立即复位)
	void Fuction_27();//结束充电(线圈,工控机立即复位)
	void Date_0();//左升降台速度
	void Date_1();//左升降台位置
	void Date_2();//右升降台速度
	void Date_3();//右升降台位置
	void Date_4();//轴1移动距离
	void Date_5();//轴2移动距离

signals:
	void Connect_Device(QString ip, int port);//连接到服务器
	void Disconnect_Device();//断开连接
	void Write_RGV_Remote_State(QJsonObject db);//写状态
	void RGV_Remote_Read_Ready();//写入缓存区
	void Set_Working();//工作状态
	void Set_Default();//非工作状态
	void setEnabled(bool ready);//写消息状态
	void Status(QString status);//监视器状态
	void Write_Coils(int addr, QJsonObject value, int size);//写线圈
	void Write_HoldingRegisters(int addr, QJsonObject value, int size);//写输入寄存器
	void Read_Coils(int addr, int size);//读线圈
	void Read_HoldingRegisters(int addr, int size);//读输入寄存器
	void Read_DiscreteInputs(int addr, int size); //读离散输入
	void Read_InputRegisters(int addr, int size);//读输入寄存器

private:
	QJsonObject m_RGV_Remote_DB;
	QJsonObject m_RGV_Remote_State;
	QJsonObject m_Coils;
	QJsonObject m_DiscreteInputs;
	QJsonObject m_InputRegisters;
	QJsonObject m_HoldingRegisters;

	bool m_RGV_Fuction_0_Set = false;//通信控制(线圈)
	bool m_RGV_Fuction_0_Reset = false;//通信控制(线圈)
	bool m_RGV_Fuction_7 = false;//主动力位置清零(线圈,工控机立即复位)
	bool m_RGV_Fuction_8 = false;//主动力故障复位(线圈,工控机立即复位)
	bool m_RGV_Fuction_9_Set = false;//主动力手动左行(线圈,点控)
	bool m_RGV_Fuction_9_Reset = false;//主动力手动左行(线圈,点控)
	bool m_RGV_Fuction_10_Set = false;//主动力手动右行(线圈,点控)
	bool m_RGV_Fuction_10_Reset = false;//主动力手动右行(线圈,点控)
	bool m_RGV_Fuction_11 = false;//正向连续运行(线圈,工控机立即复位)
	bool m_RGV_Fuction_12 = false;//返向连续运行(线圈,工控机立即复位)
	bool m_RGV_Fuction_13 = false;//返向连续运行再启动(线圈,工控机立即复位)
	bool m_RGV_Fuction_14 = false;//急停(线圈,工控机立即复位)
	bool m_RGV_Fuction_15 = false;//左机器人开机(线圈,工控机立即复位)
	bool m_RGV_Fuction_16 = false;//左机器人关机(线圈,工控机立即复位)
	bool m_RGV_Fuction_17 = false;//右机器人开机(线圈,工控机立即复位)
	bool m_RGV_Fuction_18 = false;//右机器人关机(线圈,工控机立即复位)
	bool m_RGV_Fuction_19_Set = false;//上电(线圈,点控)
	bool m_RGV_Fuction_19_Reset = false;//上电(线圈,点控)
	bool m_RGV_Fuction_20 = false;//充电回原点(线圈,工控机立即复位)
	bool m_RGV_Fuction_21_Set = false;//风刀电机开
	bool m_RGV_Fuction_21_Reset = false;//风刀电机关
	bool m_RGV_Fuction_22_Set = false;//清扫电机开
	bool m_RGV_Fuction_22_Reset = false;//清扫电机关
	bool m_RGV_Fuction_24 = false;//轴1移动(线圈,工控机立即复位)
	bool m_RGV_Fuction_25 = false;//轴2移动(线圈,工控机立即复位)
	bool m_RGV_Fuction_26 = false;//开始充电(线圈,工控机立即复位)
	bool m_RGV_Fuction_27 = false;//结束充电(线圈,工控机立即复位)
	bool m_RGV_Date_0 = false;//左升降台速度
	bool m_RGV_Date_1 = false;//左升降台位置
	bool m_RGV_Date_2 = false;//右升降台速度
	bool m_RGV_Date_3 = false;//右升降台位置
	bool m_RGV_Date_4 = false;//轴1移动距离
	bool m_RGV_Date_5 = false;//轴2移动距离
	int m_DiscreteInputs_Addr;//离散起始地址
	int m_DiscreteInputs_Size;//离散数据长度
	int m_Coils_Addr;//线圈起始地址
	int m_Coils_Size;//线圈数据长度
	int m_InputRegisters_Addr;//输入起始地址
	int m_InputRegisters_Size;//输入数据长度
	int m_HoldingRegisters_Addr;//保持起始地址
	int m_HoldingRegisters_Size;//保持数据长度
	int m_Read_Coils_Count;//读线圈长度
	int m_Read_DiscreteInputs_Count;//读离散次数
	int m_Read_HoldingRegisters_Count;//读保持次数
	int m_Read_InputRegisters_Count;//读输入次数
	int m_Carbox_Number;//车厢号
	int m_Bogie_Number;//转向架号
	int m_Axis_Number;//轮轴号

	private slots:
	void Connect_Done();
	void Disconnect_Done();
	void Write_Coils_Done();//读线圈
	void Write_HoldingRegisters_Done();//读保持寄存器
	void Read_Coils_Done(QJsonObject value);//读线圈
	void Read_HoldingRegisters_Done(QJsonObject value);//读输入寄存器
	void Read_DiscreteInputs_Done(QJsonObject value);//读离散输入
	void Read_InputRegisters_Done(QJsonObject value);//读输入寄存器
	void Write_RGV_State();
	bool Set_Coils(int addr);
	bool Reset_Coils(int addr);
	bool Set_HoldingRegisters_16(int addr, int value);
	bool Set_HoldingRegisters_32(int addr, int low, int high);
	bool If_Write_Coils();
	bool If_Write_HoldingRegisters();
	bool If_Coils_Set();
};

5.6.RGV_Remote.cpp

#pragma execution_character_set("utf-8")
#include "RGV_Remote.h"
/*************************************************************************************************************************************************
**Function:构造函数
*************************************************************************************************************************************************/
c_RGV_Remote::c_RGV_Remote(QObject *parent) : QObject(parent)
{

}
/*************************************************************************************************************************************************
**Function:析构函数
*************************************************************************************************************************************************/
c_RGV_Remote::~c_RGV_Remote()
{
	//线程中断
	m_RGV_Remote_Thread->requestInterruption();
	//线程退出
	m_RGV_Remote_Thread->quit();
	//线程等待
	m_RGV_Remote_Thread->wait();
}
/*************************************************************************************************************************************************
**Function:初始化函数
*************************************************************************************************************************************************/
void c_RGV_Remote::Init()
{
	//实例化
	m_RGV_Remote = new c_RGV_Client;
	m_RGV_Remote_Thread = new QThread;
	m_RGV_Remote->moveToThread(m_RGV_Remote_Thread);
	//初始化数据交换层
	QObject::connect(m_RGV_Remote_Thread, &QThread::started, m_RGV_Remote, &c_RGV_Client::Init);
	QObject::connect(m_RGV_Remote_Thread, &QThread::finished, m_RGV_Remote, &c_RGV_Client::deleteLater);
	//连接设备
	QObject::connect(this, &c_RGV_Remote::Connect_Device, m_RGV_Remote, &c_RGV_Client::Connect_Device);
	QObject::connect(this, &c_RGV_Remote::Disconnect_Device, m_RGV_Remote, &c_RGV_Client::Disconnect_Device);
	//读数据
	QObject::connect(this, &c_RGV_Remote::Read_Coils, m_RGV_Remote, &c_RGV_Client::Read_Coils);
	QObject::connect(this, &c_RGV_Remote::Read_HoldingRegisters, m_RGV_Remote, &c_RGV_Client::Read_HoldingRegisters);
	QObject::connect(this, &c_RGV_Remote::Read_DiscreteInputs, m_RGV_Remote, &c_RGV_Client::Read_DiscreteInputs);
	QObject::connect(this, &c_RGV_Remote::Read_InputRegisters, m_RGV_Remote, &c_RGV_Client::Read_InputRegisters);
	//写数据
	QObject::connect(this, &c_RGV_Remote::Write_Coils, m_RGV_Remote, &c_RGV_Client::Write_Coils);
	QObject::connect(this, &c_RGV_Remote::Write_HoldingRegisters, m_RGV_Remote, &c_RGV_Client::Write_HoldingRegisters);
	//设备状态改变
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Connect_Done, this, &c_RGV_Remote::Set_Working);
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Disconnect_Done, this, &c_RGV_Remote::Set_Default);
	//键盘按键改变
	QObject::connect(this, &c_RGV_Remote::Set_Working, this, [=] {emit setEnabled(true); });
	QObject::connect(this, &c_RGV_Remote::Set_Default, this, [=] {emit setEnabled(false); });
	//读到消息
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Write_Coils_Done, this, &c_RGV_Remote::Write_Coils_Done);
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Write_HoldingRegisters_Done, this, &c_RGV_Remote::Write_HoldingRegisters_Done);
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Read_Coils_Done, this, &c_RGV_Remote::Read_Coils_Done);
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Read_HoldingRegisters_Done, this, &c_RGV_Remote::Read_HoldingRegisters_Done);
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Read_DiscreteInputs_Done, this, &c_RGV_Remote::Read_DiscreteInputs_Done);
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Read_InputRegisters_Done, this, &c_RGV_Remote::Read_InputRegisters_Done);
	//向状态服务写入状态
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Connect_Done, this, &c_RGV_Remote::Connect_Done);
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Disconnect_Done, this, &c_RGV_Remote::Disconnect_Done);
	//提示信息
	QObject::connect(m_RGV_Remote, &c_RGV_Client::Status, this, [=](int state) {emit Status(c_Variable::Modbus_Status(state)); });
	//启动线程
	m_RGV_Remote_Thread->start();
	emit setEnabled(false);
}
/*************************************************************************************************************************************************
**Function:连接设备
*************************************************************************************************************************************************/
void c_RGV_Remote::Connect()
{
	if (m_RGV_Remote_State.value("Connected").toBool()) { return; }
	QString ip = c_Variable::g_Communicate_DB.value("RGV_Ip").toString();
	int port = c_Variable::g_Communicate_DB.value("RGV_Port").toInt();
	emit Connect_Device(ip, port);
}
/*************************************************************************************************************************************************
**断开连接
************************************************************************************************************************************************/
void c_RGV_Remote::Disconnect_Done()
{
	m_RGV_Remote_State.insert("Connected", false);
	Write_RGV_State();
}
/*************************************************************************************************************************************************
**置位复位赋值
************************************************************************************************************************************************/
bool c_RGV_Remote::Set_Coils(int addr)
{
	m_Coils.insert(QString::number(addr), 1);
	emit Write_Coils(addr, m_Coils, 1);
	return false;
}
bool c_RGV_Remote::Reset_Coils(int addr)
{
	m_Coils.insert(QString::number(addr), 0);
	emit Write_Coils(addr, m_Coils, 1);
	return false;
}
bool c_RGV_Remote::Set_HoldingRegisters_16(int addr, int value)
{
	m_HoldingRegisters.insert(QString::number(addr), value);
	emit Write_HoldingRegisters(addr, m_HoldingRegisters, 1);
	return false;
}
bool c_RGV_Remote::Set_HoldingRegisters_32(int addr, int low, int high)
{
	m_HoldingRegisters.insert(QString::number(addr), low);
	m_HoldingRegisters.insert(QString::number(addr + 1), high);
	emit Write_HoldingRegisters(addr, m_HoldingRegisters, 2);
	return false;
}
void c_RGV_Remote::Write_RGV_State()
{
	QEventLoop *loop = new QEventLoop;
	QObject::connect(this, &c_RGV_Remote::RGV_Remote_Read_Ready, loop, &QEventLoop::quit);
	emit Write_RGV_Remote_State(m_RGV_Remote_State);//发送到缓存区
	loop->exec();
}
/*************************************************************************************************************************************************
**轮询操作
************************************************************************************************************************************************/
//完成连接->读线圈
void c_RGV_Remote::Connect_Done()
{
	m_RGV_Remote_State.insert("Connected", true);
	Write_RGV_State();
	//更新轮询参数
	m_Coils_Addr = c_Variable::g_Communicate_DB.value("Write_Coils_Addr").toInt();
	m_Coils_Size = c_Variable::g_Communicate_DB.value("Write_Coils_Size").toInt();
	m_Read_Coils_Count = 1;
	if (m_Coils_Size > 1000) {
		emit Read_Coils(m_DiscreteInputs_Addr, 1000);
		return;
	}
	emit Read_Coils(m_Coils_Addr, m_Coils_Size);
}
//读线圈完成->写线圈复位
//直到线圈全部复位->读保持存器
void c_RGV_Remote::Read_Coils_Done(QJsonObject value)
{
	m_Coils = value;
	m_RGV_Remote_DB.insert("Coils", value);//保存离散数据
	m_RGV_Remote_State.insert("DB", m_RGV_Remote_DB);//编入通讯协议
	Write_RGV_State();//发送到缓存区
	
	//当前需要读取的线圈起始地址 = 读取次数 * 每次读取长度 (0~999=1000)
	int Read_Coils_Addr = m_Read_Coils_Count * 1000;
	//当前需要读取的线圈数据长度 = 总数据长度(1000) - 当前起始地址(0)
	int Read_Coils_Size = m_Coils_Size - Read_Coils_Addr;
	//如果当前地址 < 总长度 且 还需读取长度大于124 则 从当前地址开始再读124个长度 计数加1 并返回
	if (Read_Coils_Addr < m_Coils_Size && Read_Coils_Size > 1000) {
		emit Read_Coils(Read_Coils_Addr, 1000);
		m_Read_Coils_Count += 1;
		return;
	}
	//如果当前地址 < 总长度 且 还需读取长度小于124 则 从当前地址开始读完剩余数据 并返回
	if (Read_Coils_Addr < m_Coils_Size && Read_Coils_Size < 1000) {
		emit Read_Coils(Read_Coils_Addr, Read_Coils_Size);
		m_Read_Coils_Count += 1;
		return;
	}
	//如果读到需要复位的线圈,进行复位,并返回写线圈完成
	if (If_Coils_Set()) { return; }
	//更新轮询参数
	m_HoldingRegisters_Addr = c_Variable::g_Communicate_DB.value("Write_HoldingRegisters_Addr").toInt();
	m_HoldingRegisters_Size = c_Variable::g_Communicate_DB.value("Write_HoldingRegisters_Size").toInt();
	m_Read_HoldingRegisters_Count = 1;
	if (m_HoldingRegisters_Size > 124) {
		emit Read_HoldingRegisters(m_HoldingRegisters_Addr, 124);
		return;
	}
	emit Read_HoldingRegisters(m_HoldingRegisters_Addr, m_HoldingRegisters_Size);
}
//写线圈完成->读线圈是否写完
void c_RGV_Remote::Write_Coils_Done()
{
	c_Variable::msleep(2);
	//更新轮询参数
	m_Coils_Addr = c_Variable::g_Communicate_DB.value("Write_Coils_Addr").toInt();
	m_Coils_Size = c_Variable::g_Communicate_DB.value("Write_Coils_Size").toInt();
	m_Read_Coils_Count = 1;
	if (m_Coils_Size > 1000) {
		emit Read_Coils(m_DiscreteInputs_Addr, 1000);
		return;
	}
	emit Read_Coils(m_Coils_Addr, m_Coils_Size);
}
//读保持寄存器完成->读离散输入
void c_RGV_Remote::Read_HoldingRegisters_Done(QJsonObject value)
{
	m_HoldingRegisters = value;
	m_RGV_Remote_DB.insert("HoldingRegisters", value);//保存保持数据
	m_RGV_Remote_State.insert("DB", m_RGV_Remote_DB);//编入通讯协议
	Write_RGV_State();//发送到缓存区
	
	//当前需要读取的保持寄存器起始地址 = 读取次数 * 每次读取长度 (0~123=124)
	int Read_HoldingRegisters_Addr = m_Read_HoldingRegisters_Count * 124;
	//当前需要读取的保持寄存器数据长度 = 总数据长度(250) - 当前起始地址(124)
	int Read_HoldingRegisters_Size = m_HoldingRegisters_Size - Read_HoldingRegisters_Addr;
	//如果当前地址 < 总长度 且 还需读取长度大于124 则 从当前地址开始再读124个长度 计数加1 并返回
	if (Read_HoldingRegisters_Addr < m_HoldingRegisters_Size && Read_HoldingRegisters_Size > 124) {
		emit Read_HoldingRegisters(Read_HoldingRegisters_Addr, 124);
		m_Read_HoldingRegisters_Count += 1;
		return;
	}
	//如果当前地址 < 总长度 且 还需读取长度小于124 则 从当前地址开始读完剩余数据 并返回
	if (Read_HoldingRegisters_Addr < m_HoldingRegisters_Size && Read_HoldingRegisters_Size < 124) {
		emit Read_HoldingRegisters(Read_HoldingRegisters_Addr, Read_HoldingRegisters_Size);
		m_Read_HoldingRegisters_Count += 1;
		return;
	}
	//读离散输入更新轮询参数
	m_DiscreteInputs_Addr = c_Variable::g_Communicate_DB.value("Read_DiscreteInputs_Addr").toInt();
	m_DiscreteInputs_Size = c_Variable::g_Communicate_DB.value("Read_DiscreteInputs_Size").toInt();
	m_Read_DiscreteInputs_Count = 1;
	if (m_DiscreteInputs_Size > 1000) {
		emit Read_DiscreteInputs(m_DiscreteInputs_Addr, 1000);
		return;
	}
	emit Read_DiscreteInputs(m_DiscreteInputs_Addr, m_DiscreteInputs_Size);
}
//需要写线圈时:读离散输入完成->写线圈
//不需要写线圈时:读离散输入完成->读输入存器
void c_RGV_Remote::Read_DiscreteInputs_Done(QJsonObject value)
{
	m_DiscreteInputs = value;
	m_RGV_Remote_DB.insert("DiscreteInputs", value);//保存离散数据
	m_RGV_Remote_State.insert("DB", m_RGV_Remote_DB);//编入通讯协议
	Write_RGV_State();//发送到缓存区
	
	//当前需要读取的离散起始地址 = 读取次数 * 每次读取长度 (0~999=1000)
	int Read_DiscreteInputs_Addr = m_Read_DiscreteInputs_Count * 1000;
	//当前需要读取的离散数据长度 = 总数据长度(1000) - 当前起始地址(0)
	int Read_DiscreteInputs_Size = m_DiscreteInputs_Size - Read_DiscreteInputs_Addr;
	//如果当前地址 < 总长度 且 还需读取长度大于124 则 从当前地址开始再读124个长度 计数加1 并返回
	if (Read_DiscreteInputs_Addr < m_DiscreteInputs_Size && Read_DiscreteInputs_Size > 1000) {
		emit Read_DiscreteInputs(Read_DiscreteInputs_Addr, 1000);
		m_Read_DiscreteInputs_Count += 1;
		return;
	}
	//如果当前地址 < 总长度 且 还需读取长度小于124 则 从当前地址开始读完剩余数据 并返回
	if (Read_DiscreteInputs_Addr < m_DiscreteInputs_Size && Read_DiscreteInputs_Size < 1000) {
		emit Read_DiscreteInputs(Read_DiscreteInputs_Addr, Read_DiscreteInputs_Size);
		m_Read_DiscreteInputs_Count += 1;
		return;
	}
	//如果线圈改变则等待线圈写完成后,读线圈
	if (If_Write_Coils()) { return; }
	//如果线圈不改变则不读线圈,直接读输入寄存器,更新轮询参数
	m_InputRegisters_Addr = c_Variable::g_Communicate_DB.value("Read_InputRegisters_Addr").toInt();
	m_InputRegisters_Size = c_Variable::g_Communicate_DB.value("Read_InputRegisters_Size").toInt();
	//如果读取的数据长度大于124则读124个数据,并初始化计数
	m_Read_InputRegisters_Count = 1;
	if (m_InputRegisters_Size > 124) {
		emit Read_InputRegisters(m_InputRegisters_Addr, 124);
		return;
	}
	emit Read_InputRegisters(m_InputRegisters_Addr, m_InputRegisters_Size);
}
//需写保持寄存器:读输入寄存器完成—>写保持寄存器
//无需写保持寄存器:读输入寄存器完成->读离散
void c_RGV_Remote::Read_InputRegisters_Done(QJsonObject value)
{
	m_InputRegisters = value;
	m_RGV_Remote_DB.insert("InputRegisters", value);//保存输入数据
	m_RGV_Remote_State.insert("DB", m_RGV_Remote_DB);//编入通讯协议
	Write_RGV_State();//发送到缓存区
	
	//当前需要读取的输入寄存器起始地址 = 读取次数 * 每次读取长度 (0~123=124)
	int Read_InputRegisters_Addr = m_Read_InputRegisters_Count * 124;
	//当前需要读取的输入寄存器数据长度 = 总数据长度(250) - 当前起始地址(124)
	int Read_InputRegisters_Size = m_InputRegisters_Size - Read_InputRegisters_Addr;
	//如果当前地址 < 总长度 且 还需读取长度大于124 则 从当前地址开始再读124个长度 计数加1 并返回
	if (Read_InputRegisters_Addr < m_InputRegisters_Size && Read_InputRegisters_Size > 124) {
		emit Read_InputRegisters(Read_InputRegisters_Addr, 124);
		m_Read_InputRegisters_Count += 1;
		return;
	}
	//如果当前地址 < 总长度 且 还需读取长度小于124 则 从当前地址开始读完剩余数据 并返回
	if (Read_InputRegisters_Addr < m_InputRegisters_Size && Read_InputRegisters_Size < 124) {
		emit Read_InputRegisters(Read_InputRegisters_Addr, Read_InputRegisters_Size);
		m_Read_InputRegisters_Count += 1;
		return;
	}
	//完成所有输入数据读取后,继续执行如下程序
	//如果保持寄存器改变则等待保持寄存器写完成后,读保持寄存器
	if (If_Write_HoldingRegisters()) { return; }
	//如果保持寄存器没有改变,则直接读离散输入
	//更新轮询参数
	m_DiscreteInputs_Addr = c_Variable::g_Communicate_DB.value("Read_DiscreteInputs_Addr").toInt();
	m_DiscreteInputs_Size = c_Variable::g_Communicate_DB.value("Read_DiscreteInputs_Size").toInt();
	m_Read_DiscreteInputs_Count = 1;
	if (m_DiscreteInputs_Size > 1000) {
		emit Read_DiscreteInputs(m_DiscreteInputs_Addr, 1000);
		return;
	}
	emit Read_DiscreteInputs(m_DiscreteInputs_Addr, m_DiscreteInputs_Size);
}
//写保持寄存器完成->读保持寄存器
void c_RGV_Remote::Write_HoldingRegisters_Done()
{
	c_Variable::msleep(2);
	//更新轮询参数
	m_HoldingRegisters_Addr = c_Variable::g_Communicate_DB.value("Write_HoldingRegisters_Addr").toInt();
	m_HoldingRegisters_Size = c_Variable::g_Communicate_DB.value("Write_HoldingRegisters_Size").toInt();
	m_Read_HoldingRegisters_Count = 1;
	if (m_HoldingRegisters_Size > 124) {
		emit Read_HoldingRegisters(m_HoldingRegisters_Addr, 124);
		return;
	}
	emit Read_HoldingRegisters(m_HoldingRegisters_Addr, m_HoldingRegisters_Size);
}
/*************************************************************************************************************************************************
**线圈操作
************************************************************************************************************************************************/
//通信控制(线圈)(离散:为1时远程控制,PLC端无控制)
void c_RGV_Remote::Fuction_0_Set()
{
	m_RGV_Fuction_0_Set = true;
}
void c_RGV_Remote::Fuction_0_Reset()
{
	m_RGV_Fuction_0_Reset = true;
}
//主动力位置清零(线圈,工控机立即复位)(离散)
void c_RGV_Remote::Fuction_7()
{
	m_RGV_Fuction_7 = true;
}
//主动力故障复位(线圈,工控机立即复位)(离散)
void c_RGV_Remote::Fuction_8()
{
	m_RGV_Fuction_8 = true;
}
//主动力手动左行(线圈,点控)(离散:为1运行中)
void c_RGV_Remote::Fuction_9_Set()
{
	m_RGV_Fuction_9_Set = true;
}
//主动力手动左行(线圈,点控)(离散:为1运行中)
void c_RGV_Remote::Fuction_9_Reset()
{
	m_RGV_Fuction_9_Reset = true;
}
//主动力手动右行(线圈,点控)(离散:为1运行中)
void c_RGV_Remote::Fuction_10_Set()
{
	m_RGV_Fuction_10_Set = true;
}
//主动力手动右行(线圈,点控)(离散:为1运行中)
void c_RGV_Remote::Fuction_10_Reset()
{
	m_RGV_Fuction_10_Reset = true;
}
//正向连续运行(线圈,工控机立即复位)(离散:为1运行中)
void c_RGV_Remote::Fuction_11()
{
	m_RGV_Fuction_11 = true;
}
//返向连续运行(线圈,工控机立即复位)(离散:为1运行中)
void c_RGV_Remote::Fuction_12()
{
	m_RGV_Fuction_12 = true;
}
//返向连续运行再启动(线圈,工控机立即复位)(离散:为1运行中)
void c_RGV_Remote::Fuction_13()
{
	m_RGV_Fuction_13 = true;
}//
 //急停(线圈,工控机立即复位)(离散)
void c_RGV_Remote::Fuction_14()
{
	m_RGV_Fuction_14 = true;
}
//左机器人开机(线圈,工控机立即复位)(离散:为1完成开机)
void c_RGV_Remote::Fuction_15()
{
	m_RGV_Fuction_15 = true;
}
//左机器人关机(线圈,工控机立即复位)(离散:为1完成关机)
void c_RGV_Remote::Fuction_16()
{
	m_RGV_Fuction_16 = true;
}
//右机器人开机(线圈,工控机立即复位)(离散:为1完成开机)
void c_RGV_Remote::Fuction_17()
{
	m_RGV_Fuction_17 = true;
}
//右机器人关机(线圈,工控机立即复位)(离散:为1完成关机)
void c_RGV_Remote::Fuction_18()
{
	m_RGV_Fuction_18 = true;
}
//上电(线圈,点控)(离散:为1所有设备上电处于待机状态)
void c_RGV_Remote::Fuction_19_Set()
{
	m_RGV_Fuction_19_Set = true;
}
//上电(线圈,点控)(离散:为1所有设备上电处于待机状态)
void c_RGV_Remote::Fuction_19_Reset()
{
	m_RGV_Fuction_19_Reset = true;
}
//充电回原点(线圈,工控机立即复位)
void c_RGV_Remote::Fuction_20()
{
	m_RGV_Fuction_20 = true;
}
//风刀电机开
void c_RGV_Remote::Fuction_21_Set()
{
	m_RGV_Fuction_21_Set = true;
}
//风刀电机关
void c_RGV_Remote::Fuction_21_Reset()
{
	m_RGV_Fuction_21_Reset = true;
}
//清扫电机开
void c_RGV_Remote::Fuction_22_Set()
{
	m_RGV_Fuction_22_Set = true;
}
//清扫电机关
void c_RGV_Remote::Fuction_22_Reset()
{
	m_RGV_Fuction_22_Reset = true;
}
//轴1移动(线圈,工控机立即复位)(离散:为为1移动中)
void c_RGV_Remote::Fuction_24()
{
	m_RGV_Fuction_24 = true;
}
//轴2移动(线圈,工控机立即复位)(离散:为1移动中)
void c_RGV_Remote::Fuction_25()
{
	m_RGV_Fuction_25 = true;
}
//开始充电(线圈,工控机立即复位)(离散:为1时远程控制,PLC端无控制)
void c_RGV_Remote::Fuction_26()
{
	m_RGV_Fuction_26 = true;
}
//结束充电(线圈,工控机立即复位)(离散:为1时远程控制,PLC端无控制)
void c_RGV_Remote::Fuction_27()
{
	m_RGV_Fuction_27 = true;
}
/*************************************************************************************************************************************************
**保持寄存器操作
************************************************************************************************************************************************/
//左升降台速度
void c_RGV_Remote::Date_0()
{
	m_RGV_Date_0 = true;
}
//左升降台位置
void c_RGV_Remote::Date_1()
{
	m_RGV_Date_1 = true;
}
//右升降台速度
void c_RGV_Remote::Date_2()
{
	m_RGV_Date_2 = true;
}
//右升降台位置
void c_RGV_Remote::Date_3()
{
	m_RGV_Date_3 = true;
}
//轴1移动距离
void c_RGV_Remote::Date_4()
{
	m_RGV_Date_4 = true;
}
//轴2移动距离
void c_RGV_Remote::Date_5()
{
	m_RGV_Date_5 = true;
}
/*************************************************************************************************************************************************
**判断是否写线圈
************************************************************************************************************************************************/
bool c_RGV_Remote::If_Write_Coils()
{
	if (m_RGV_Fuction_0_Set) {
		m_RGV_Fuction_0_Set = Set_Coils(RGV_Fuction_0);
		return true;
	}
	if (m_RGV_Fuction_0_Reset) {
		m_RGV_Fuction_0_Reset = Reset_Coils(RGV_Fuction_0);
		return true;
	}
	if (m_RGV_Fuction_7) {
		m_RGV_Fuction_7 = Set_Coils(RGV_Fuction_7);
		return true;
	}
	if (m_RGV_Fuction_8) {
		m_RGV_Fuction_8 = Set_Coils(RGV_Fuction_8);
		return true;
	}
	if (m_RGV_Fuction_9_Set) {
		m_RGV_Fuction_9_Set = Set_Coils(RGV_Fuction_9);
		return true;
	}
	if (m_RGV_Fuction_9_Reset) {
		m_RGV_Fuction_9_Reset = Reset_Coils(RGV_Fuction_9);
		return true;
	}
	if (m_RGV_Fuction_10_Set) {
		m_RGV_Fuction_10_Set = Set_Coils(RGV_Fuction_10);
		return true;
	}
	if (m_RGV_Fuction_10_Reset) {
		m_RGV_Fuction_10_Reset = Reset_Coils(RGV_Fuction_10);
		return true;
	}
	if (m_RGV_Fuction_11) {
		m_RGV_Fuction_11 = Set_Coils(RGV_Fuction_11);
		return true;
	}
	if (m_RGV_Fuction_12) {
		m_RGV_Fuction_12 = Set_Coils(RGV_Fuction_12);
		return true;
	}
	if (m_RGV_Fuction_13) {
		m_RGV_Fuction_13 = Set_Coils(RGV_Fuction_13);
		return true;
	}
	if (m_RGV_Fuction_14) {
		m_RGV_Fuction_14 = Set_Coils(RGV_Fuction_14);
		return true;
	}
	if (m_RGV_Fuction_15) {
		m_RGV_Fuction_15 = Set_Coils(RGV_Fuction_15);
		return true;
	}
	if (m_RGV_Fuction_16) {
		m_RGV_Fuction_16 = Set_Coils(RGV_Fuction_16);
		return true;
	}
	if (m_RGV_Fuction_17) {
		m_RGV_Fuction_17 = Set_Coils(RGV_Fuction_17);
		return true;
	}
	if (m_RGV_Fuction_18) {
		m_RGV_Fuction_18 = Set_Coils(RGV_Fuction_18);
		return true;
	}
	if (m_RGV_Fuction_19_Set) {
		m_RGV_Fuction_19_Set = Set_Coils(RGV_Fuction_19);
		return true;
	}
	if (m_RGV_Fuction_19_Reset) {
		m_RGV_Fuction_19_Reset = Reset_Coils(RGV_Fuction_19);
		return true;
	}
	if (m_RGV_Fuction_20) {
		m_RGV_Fuction_20 = Set_Coils(RGV_Fuction_20);
		return true;
	}
	if (m_RGV_Fuction_21_Set) {
		m_RGV_Fuction_21_Set = Set_Coils(RGV_Fuction_21);
		return true;
	}
	if (m_RGV_Fuction_21_Reset) {
		m_RGV_Fuction_21_Reset = Reset_Coils(RGV_Fuction_21);
		return true;
	}
	if (m_RGV_Fuction_22_Set) {
		m_RGV_Fuction_22_Set = Set_Coils(RGV_Fuction_22);
		return true;
	}
	if (m_RGV_Fuction_22_Reset) {
		m_RGV_Fuction_22_Reset = Reset_Coils(RGV_Fuction_22);
		return true;
	}
	if (m_RGV_Fuction_24) {
		m_RGV_Fuction_24 = Set_Coils(RGV_Fuction_24);
		return true;
	}
	if (m_RGV_Fuction_25) {
		m_RGV_Fuction_25 = Set_Coils(RGV_Fuction_25);
		return true;
	}
	if (m_RGV_Fuction_26) {
		m_RGV_Fuction_26 = Set_Coils(RGV_Fuction_26);
		return true;
	}
	if (m_RGV_Fuction_27) {
		m_RGV_Fuction_27 = Set_Coils(RGV_Fuction_27);
		return true;
	}
	else {
		return false;
	}
}
/*************************************************************************************************************************************************
**判断是否写保持寄存器
************************************************************************************************************************************************/
bool c_RGV_Remote::If_Write_HoldingRegisters()
{
	//左升降台速度
	if (m_RGV_Date_0) {
		int Date = c_Variable::g_Communicate_DB.value("RGV_Date_0").toInt();
		int high = Date / 65536;
		int low = Date % 65536;
		m_RGV_Date_0 = Set_HoldingRegisters_32(RGV_Date_0, low, high);
		return true;
	}
	//左升降台位置
	if (m_RGV_Date_1) {
		int Date = c_Variable::g_Communicate_DB.value("RGV_Date_1").toInt();
		int high = Date / 65536;
		int low = Date % 65536;
		m_RGV_Date_1 = Set_HoldingRegisters_32(RGV_Date_1, low, high);
		return true;
	}
	//右升降台速度
	if (m_RGV_Date_2) {
		int Date = c_Variable::g_Communicate_DB.value("RGV_Date_2").toInt();
		int high = Date / 65536;
		int low = Date % 65536;
		m_RGV_Date_2 = Set_HoldingRegisters_32(RGV_Date_2, low, high);
		return true;
	}
	//右升降台位置
	if (m_RGV_Date_3) {
		int Date = c_Variable::g_Communicate_DB.value("RGV_Date_3").toInt();
		int high = Date / 65536;
		int low = Date % 65536;
		m_RGV_Date_3 = Set_HoldingRegisters_32(RGV_Date_3, low, high);
		return true;
	}
	//轴1移动距离
	if (m_RGV_Date_4) {
		int Date = c_Variable::g_Communicate_DB.value("RGV_Date_4").toInt();
		m_RGV_Date_4 = Set_HoldingRegisters_16(RGV_Date_4, Date);
		return true;
	}
	//轴2移动距离
	if (m_RGV_Date_5) {
		int Date = c_Variable::g_Communicate_DB.value("RGV_Date_5").toInt();
		m_RGV_Date_5 = Set_HoldingRegisters_16(RGV_Date_5, Date);
		return true;
	}
	//否则返回false
	else {
		return false;
	}
}
/*************************************************************************************************************************************************
**判断线圈是否置位(点控)
************************************************************************************************************************************************/
bool c_RGV_Remote::If_Coils_Set()
{
	//主动力位置清零
	if (m_Coils.value(QString::number(RGV_Fuction_7)).toInt() == 1 ) {
		Reset_Coils(RGV_Fuction_7);
		return true;
	}
	//主动力故障复位
	if (m_Coils.value(QString::number(RGV_Fuction_8)).toInt() == 1 ) {
		Reset_Coils(RGV_Fuction_8);
		return true;
	}
	//正向连续运行
	if (m_Coils.value(QString::number(RGV_Fuction_11)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_11);
		return true;
	}
	//返向连续运行
	if (m_Coils.value(QString::number(RGV_Fuction_12)).toInt() == 1 ) {
		Reset_Coils(RGV_Fuction_12);
		return true;
	}
	//返向连续运行再启动
	if (m_Coils.value(QString::number(RGV_Fuction_13)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_13);
		return true;
	}
	//急停
	if (m_Coils.value(QString::number(RGV_Fuction_14)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_14);
		return true;
	}
	//左机器人开机
	if (m_Coils.value(QString::number(RGV_Fuction_15)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_15);
		return true;
	}
	//左机器人关机
	if (m_Coils.value(QString::number(RGV_Fuction_16)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_16);
		return true;
	}
	//右机器人开机
	if (m_Coils.value(QString::number(RGV_Fuction_17)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_17);
		return true;
	}
	//右机器人关机
	if (m_Coils.value(QString::number(RGV_Fuction_18)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_18);
		return true;
	}
	//充电回原点(线圈,工控机立即复位)
	if (m_Coils.value(QString::number(RGV_Fuction_20)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_20);
		return true;
	}
	//轴1移动
	if (m_Coils.value(QString::number(RGV_Fuction_24)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_24);
		return true;
	}
	//轴2移动
	if (m_Coils.value(QString::number(RGV_Fuction_25)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_25);
		return true;
	}
	//开始充电(线圈,工控机立即复位)
	if (m_Coils.value(QString::number(RGV_Fuction_26)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_26);
		return true;
	}
	//结束充电(线圈,工控机立即复位)
	if (m_Coils.value(QString::number(RGV_Fuction_27)).toInt() == 1) {
		Reset_Coils(RGV_Fuction_27);
		return true;
	}
	//否则返回false
	else {
		return false;
	}
}

5.7.在UI中实例化,并绑定控件

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值