Qt中使用MXComponent与三菱PLC通信(PLC型号是FX5U)通过设置逻辑站取代MODBUSTCP 直接访问D0-D100的方法

1.先三菱官网下载MXComponent的安装包

网址:https://me-fa.yangben.cn/plc,找到这里点击下载,下载不了记得注册一个账号。
找到这里点击下载

2.安装MXComponent

解压后先安装EnvMEL中的setup.exe,再安装文件夹中的setup.exe
在这里插入图片描述
安装好了后启动栏有软件 Communication Settings Utility
在这里插入图片描述

3.找到C++中需要用的代码路径

安装的路径中有VS工具打开的代码,如下图:
在这里插入图片描述

4.打开Communication Settings Utility并设置PLC型号,示例为FX5U

打开软件逻辑站号设置为1:
在这里插入图片描述
详细见这个博主的设置
https://blog.youkuaiyun.com/gangli_8/article/details/113518109

点击测试延迟,有延迟反馈即OK:
在这里插入图片描述
设置完毕。

5.Qt开发示例代码:

引用上一步,第3步中VS用的C++代码:
在这里插入图片描述

引用在Qt中:
在这里插入图片描述
下面是我的一部分通信类的代码:

#ifndef MXCOMPONENTMODBUSTCP_H
#define MXCOMPONENTMODBUSTCP_H

#include <QObject>

//Windows的头文件
#include <windows.h>
#include <oleauto.h>
#include <combaseapi.h>
#include <QList>
#include <QTimer>
#include <QMap>

#include "ImportClass/ActProgDataLogging64_i.h"
#include "ImportClass/ActProgType64_i.h"
#include "ImportClass/ActSupportMsg64_i.h"
#include "ImportClass/ActUtlDataLogging64_i.h"
#include "ImportClass/ActUtlType64_i.h"

class MXComponentModBusTCP: public QObject
{
    Q_OBJECT
public:

    explicit MXComponentModBusTCP(QObject *parent = nullptr);
    ~MXComponentModBusTCP();
    long OpenLogicalStationNumber(long number = 1);//打开设备的逻辑站编号,正确返回0
    long CloseLogicalStationNumber();

public slots:
    void setTimerSwitch(bool isStart);

    //单个读写
    long GetDeviceData(QString DeviceName,long& DeviceData);//long& DeviceData是返回的获取值
    long SetDeviceData(QString DeviceName,long DeviceData);//long& DeviceData是准备设置的值

    //多个读写 可不连续
    long GetDeviceData(QStringList DeviceNames, QList<long> &DeviceDatas);//QList<long>& DeviceDatas是返回的获取值
    long SetDeviceData(QStringList DeviceNames,QList<long> DeviceDatas);//QList<long> DeviceDatas是准备设置的值

    //多个连续的块读写
    long GetDeviceData(QString DeviceName, long DeviceSize,QList<long>& DeviceDatas);
    long SetDeviceData(QString DeviceName, long DeviceSize,QList<long> DeviceDatas);

signals:
    void sig_SendReadCoilRegisterData(QMap<QString,bool> readData);
    void sig_StopData(bool isStop);
    void sig_EmerGate(bool isOk);

    void sig_Temp(QList<long> temps);
    void sig_XZpostion(QList<long> data);
    void sig_CurrCnt(QList<long> data);

    void sig_addSecTimer(bool isStart);

    void sig_updataTimeLineEdit(long time);

    void sig_AlarmDatas(QList<long> data);

    void sig_InitRead(QList<long> data);

    void sig_ReadOnlineState(bool isOnline);

    void sig_SendAutoModel(long data);


private:

    bool isOpen;//
    bool Init();

    IActUtlType64* m_pIUtlType;
    IActProgType64* m_pIProgType;

    QString m_ReturnCode;

    long m_StationNumber;//逻辑站编号

    QString m_Password;

    QTimer* timerReadCoilRegister;

//    QString m_DeviceNameSet;
//    QString m_DeviceDataSet;

private slots:

    // void timeoutOpenConnet();//周期尝试连接
    void timeoutReadCoilRegister();//周期读寄存器的线圈

private:
    BSTR QStringToBSTR(const QString &qstr);//转类型使用
    int m_SelectCntl;


    QStringList m_ReadCoilRegisterName;//

    QStringList m_AlarmName;//

    QMap<QString,bool> m_ReadCoilRegisterData;//

    bool initRead;
    // int OnlineCnt;//秒数计时

};

#endif // MXCOMPONENTMODBUSTCP_H

定义文件:

#include "MXComponentModBusTCP.h"
#include <QDebug>
#include <QThread>

MXComponentModBusTCP::MXComponentModBusTCP(QObject *parent):QObject(parent),
    isOpen(false),initRead(false)
{
    m_SelectCntl=0;
    m_ReadCoilRegisterName = QStringList{"X0","X1","X2","X3","X4","X5","X6","X7","X10","X11","X12","X13","X14","X15","X16","X17",
                        "X20","X21","X22","X23","X24","X25","X26","X27","X30","X31","X32","X33","X34","X35","X36","X37",
                        "Y0","Y1","Y2","Y3","Y4","Y5","Y6","Y7","Y10","Y11","Y12","Y13","Y14","Y15","Y16","Y17",
                        "Y20","Y21","Y22","Y23","Y24","Y25","Y26","Y27","Y30","Y31","Y32","Y33","Y34","Y35","Y36","Y37"};
    m_AlarmName = QStringList{"M1001","M1002","M1003","M1004","M1005","M1006","M1007","M1008","M1009","M1010","M1011","M1012","M1013","M1014"
            ,"M1015","M1016","M1017","M1018","M1019","M1020"};

    timerReadCoilRegister = new QTimer(this);
    connect(timerReadCoilRegister,&QTimer::timeout,this,&MXComponentModBusTCP::timeoutReadCoilRegister);
    timerReadCoilRegister->start(500);
}

MXComponentModBusTCP::~MXComponentModBusTCP()
{
    timerReadCoilRegister->stop();
    if(isOpen)
        CloseLogicalStationNumber();
}

long MXComponentModBusTCP::OpenLogicalStationNumber(long number)
{

    long	lRet = -1;
    BSTR	bstrPassword = NULL;
    HRESULT	hr;
    m_StationNumber = number;

    m_ReturnCode = "";


    // Processing of Open method
    //
    if (m_SelectCntl == 0)	// ActUtlType Control(CustomInterface)
    {

        m_pIUtlType->put_ActLogicalStationNumber(m_StationNumber);
        // Set the string of 'Password' to the property.
        //        bstrPassword = m_Password.AllocSysString();
        bstrPassword = QStringToBSTR(m_Password);
        m_pIUtlType->put_ActPassword(bstrPassword);
//        qDebug() << " Free the allocated area.";
        ::SysFreeString(bstrPassword);
//        qDebug() << "The Open method is executed.";
        hr = m_pIUtlType->Open(&lRet);
    }
    else					// ActProgType Control(CustomInterface)
    {
        // If not use the default value of the property,
        // Set a suitable value before the Open wethod.
        // ( Even if set after the Open method, not reflected in the communication. )
        // ---> e.g., Change the 'UnitType' to RUSB, the 'ProtocolType' to USB, and the 'CpuType' to R08CPU.
        m_pIProgType->put_ActUnitType(4100);		// UNIT_RUSB
        m_pIProgType->put_ActProtocolType(13);		// PROTOCOL_USB
        m_pIProgType->put_ActCpuType(4098);			// CPU_R08CPU

        // Other propety is set a default value.
        m_pIProgType->put_ActBaudRate(19200);
        m_pIProgType->put_ActConnectUnitNumber(0);
        m_pIProgType->put_ActControl(8);
        m_pIProgType->put_ActCpuTimeOut(0);
        m_pIProgType->put_ActDataBits(8);
        m_pIProgType->put_ActDestinationIONumber(0);
        m_pIProgType->put_ActDestinationPortNumber(0);
        m_pIProgType->put_ActDidPropertyBit(1);
        m_pIProgType->put_ActDsidPropertyBit(1);
        QString ActHostAddressStr("1.1.1.1");
        m_pIProgType->put_ActHostAddress(QStringToBSTR(ActHostAddressStr));
        m_pIProgType->put_ActIntelligentPreferenceBit(0);
        m_pIProgType->put_ActIONumber(1023);
        m_pIProgType->put_ActMultiDropChannelNumber(0);
        m_pIProgType->put_ActNetworkNumber(0);
        m_pIProgType->put_ActPacketType(1);
        m_pIProgType->put_ActParity(1);
        QString ActPasswordStr("");
        m_pIProgType->put_ActPassword(QStringToBSTR(ActPasswordStr));
        m_pIProgType->put_ActPortNumber(1);
        m_pIProgType->put_ActSourceNetworkNumber(0);
        m_pIProgType->put_ActSourceStationNumber(0);
        m_pIProgType->put_ActStationNumber(255);
        m_pIProgType->put_ActStopBits(0);
        m_pIProgType->put_ActSumCheck(0);
        m_pIProgType->put_ActTargetSimulator(0);
        m_pIProgType->put_ActThroughNetworkType(0);
        m_pIProgType->put_ActTimeOut(10000);
        m_pIProgType->put_ActUnitNumber(0);

        // The Open method is executed.
        hr = m_pIProgType->Open(&lRet);

    }

    if (SUCCEEDED(hr))	// Compornent Communication is succeeded?
    {
        // When the Open method is succeeded, disable the TextBox of 'LogocalStationNumber'.
        if (m_SelectCntl == 0 && lRet == 0x00)
        {
            return lRet;
        }
        // The return code of the method is displayed by the hexadecimal.
//        m_ReturnCode.Format(_T("0x%08x [HEX]"), lRet);
        return lRet;
    }
    else
    {
        m_ReturnCode = "Component communication failed.";
//        qErrnoWarning(lRet,m_ReturnCode.toLatin1());
        return lRet;
    }
}

long MXComponentModBusTCP::CloseLogicalStationNumber()
{
    long	lRet;
    HRESULT	hr;

    // Displayed output data is cleared.
    m_ReturnCode = "";

    if (m_SelectCntl == 0)	// ActUtlType Control(CustomInterface)
    {
        hr = m_pIUtlType->Close(&lRet);
    }
    else					// ActProgType Control(CustomInterface)
    {
        hr = m_pIProgType->Close(&lRet);
    }

    if (SUCCEEDED(hr))	// Compornent Communication is succeeded?
    {
        // When the Open method is succeeded, enable the TextBox of 'LogocalStationNumber'.
        if (m_SelectCntl == 0 && lRet == 0x00)
        {
            return lRet;
        }
        // The return code of the method is displayed by the hexadecimal.
//		m_ReturnCode.Format(_T("0x%08x [HEX]"), lRet);
    }
    else
    {
        m_ReturnCode = "Component communication failed.";
        qErrnoWarning(lRet,m_ReturnCode.toLatin1());
        return lRet;
    }
}

void MXComponentModBusTCP::setTimerSwitch(bool isStart)
{
    if(isStart)
    {
        timerReadCoilRegister->start(500);
    }
    else
    {
        timerReadCoilRegister->stop();
    }
}

long MXComponentModBusTCP::GetDeviceData(QString DeviceName,long& DeviceData)
{
    long	lValue;
    long	lRet;
    HRESULT	hr;
    BSTR	szDev = NULL;


//    m_DeviceNameSet = DeviceName;

    // Displayed output data is cleared.
    m_ReturnCode = "";

    szDev = QStringToBSTR(DeviceName);

    //
    // Processing of GetDevice method
    //
    if (m_SelectCntl == 0) 	// ActUtlType Control(CustomInterface)
    {
        hr = m_pIUtlType->GetDevice(szDev, &lValue, &lRet);
    }
    else					// ActProgType Control(CustomInterface)
    {
        hr = m_pIProgType->GetDevice(szDev, &lValue, &lRet);
    }

    if (SUCCEEDED(hr)) // Compornent Communication is succeeded?
    {
        // When the method is succeeded, display the read data.
        if (lRet == 0x00) // 设置成功
        {
            DeviceData = lValue;//返回值
            ::SysFreeString(szDev);
            return lRet;

        }
        ::SysFreeString(szDev);
        return lRet;
    }
    else
    {
        m_ReturnCode = "Component communication failed.";
        qErrnoWarning(lRet,m_ReturnCode.toLatin1());
        ::SysFreeString(szDev);
        return lRet;
    }

    // Free the allocated area.

}

long MXComponentModBusTCP::SetDeviceData(QString DeviceName,long DeviceData)
{
    long	lValue;
    long	lRet;
    HRESULT	hr;
    BSTR	szDev = NULL;
    
    m_ReturnCode = "";

    // Check the target of TextBox.
    if (DeviceName == "" )
    {
        qDebug() << "DeviceName不能为空";
        return -1;
    }

    lValue = DeviceData;

    // Allocate the BSTR-Type String area. (After use, you have to free it.)
    szDev = QStringToBSTR(DeviceName);

    if(m_SelectCntl == 0) 	// ActUtlType Control(CustomInterface)
    {
        hr = m_pIUtlType->SetDevice(szDev, lValue, &lRet);
    }
    else					// ActProgType Control(CustomInterface)
    {
        hr = m_pIProgType->SetDevice(szDev, lValue, &lRet);
    }

    if (SUCCEEDED(hr))	// Compornent Communication is succeeded?
    {
        ::SysFreeString(szDev);
        return lRet;
    }
    else
    {
        m_ReturnCode = "Component communication failed.";
        qErrnoWarning(lRet,m_ReturnCode.toLatin1());
        ::SysFreeString(szDev);
        return lRet;
    }
}

long MXComponentModBusTCP::GetDeviceData(QStringList DeviceNames, QList<long> &DeviceDatas)
{

    if(DeviceNames.size() == 0)
    {
        qDebug()  << "DeviceData的个数不能为0";
        return -1;
    }



    long*	lValue;
    long	lRet;
    long	lSize;
    QString deviceName;

    HRESULT	hr;
    BSTR	szDev = NULL;
    m_ReturnCode = "";

    foreach (auto str, DeviceNames) {
        deviceName += str;
        deviceName += "\n";
    }
    deviceName.chop(1);
    // Allocate the BSTR-Type String area. (After use, you have to free it.)
    szDev = QStringToBSTR(deviceName);

    lSize = DeviceNames.size();
    lValue = new long[lSize];

    //
    // Processing of ReadDeviceRandom method
    //
    if (m_SelectCntl == 0)	// ActUtlType Control(CustomInterface)
    {
        hr = m_pIUtlType->ReadDeviceRandom(szDev, lSize, &lValue[0], &lRet);
    }
    else					// ActProgType Control(CustomInterface)
    {
        hr = m_pIProgType->ReadDeviceRandom(szDev, lSize, &lValue[0], &lRet);
    }



    if (SUCCEEDED(hr)) // Compornent Communication is succeeded?
    {
        // When the method is succeeded, display the read data.
        if (lRet == 0x00)
        {
//            GetLongCString(lValue, lSize, m_Data);
            for(int i = 0 ; i < lSize ; i++)
            {
                DeviceDatas << lValue[i];
            }
            ::SysFreeString(szDev);
            delete[] lValue;
            return lRet;
        }
        // The return code of the method is displayed by the hexadecimal.
//        m_ReturnCode.Format(_T("0x%08x [HEX]"), lRet);
        ::SysFreeString(szDev);
        delete[] lValue;
        return lRet;
    }
    else
    {
        m_ReturnCode = "Component communication failed.";
        qErrnoWarning(lRet,m_ReturnCode.toLatin1());
        ::SysFreeString(szDev);
        delete[] lValue;
        return lRet;
    }
}

long MXComponentModBusTCP::SetDeviceData(QStringList DeviceNames, QList<long> DeviceDatas)
{
    if(DeviceDatas.size() != DeviceDatas.size())
    {
        qDebug()  << "DeviceData和DeviceData的个数不一致";
        return -1;
    }
    if(DeviceDatas.size() == 0 &&  DeviceDatas.size() == 0)
    {
        qDebug()  << "DeviceData和DeviceData的个数不能为0";
        return -1;
    }

    long*	lValue;
    long	lRet;
    long	lSize;
    QString deviceName;
//	CString	MsgStr;
    HRESULT	hr;
    BSTR	szDev = NULL;
    
    m_ReturnCode = "";

    foreach (auto str, DeviceNames) {
        deviceName += str;
        deviceName += "\n";
    }
    deviceName.chop(1);
    // Allocate the BSTR-Type String area. (After use, you have to free it.)
    szDev = QStringToBSTR(deviceName);


    lSize = DeviceNames.size();

    // Check the 'DeviceData'.(If succeeded, the value is gotten.)
    lValue = new long[lSize];
    // lValue = (long*)malloc(lSize*sizeof(long));


    for(int i = 0 ; i < lSize ; i++)
    {
        lValue[i] = DeviceDatas.at(i);

    }

    if (m_SelectCntl == 0)	// ActUtlType Control(CustomInterface)
    {
        hr = m_pIUtlType->WriteDeviceRandom(szDev, lSize, &lValue[0], &lRet);
    }
    else					// ActProgType Control(CustomInterface)
    {
        hr = m_pIProgType->WriteDeviceRandom(szDev, lSize, &lValue[0], &lRet);
    }

    if (SUCCEEDED(hr))	// Compornent Communication is succeeded?
    {
        ::SysFreeString(szDev);
        delete[] lValue;
        return lRet;
    }
    else
    {
        m_ReturnCode = "Component communication failed.";
        qErrnoWarning(lRet,m_ReturnCode.toLatin1());
        ::SysFreeString(szDev);
        delete[] lValue;
        return lRet;
    }
}

long MXComponentModBusTCP::GetDeviceData(QString DeviceName, long DeviceSize, QList<long> &DeviceDatas)
{
    long	*lValue;
    long	lSize;
    long	lRet;
    HRESULT	hr;
    BSTR	szDev = NULL;
    m_ReturnCode = "";


    // Allocate the BSTR-Type String area. (After use, you have to free it.)
    szDev = QStringToBSTR(DeviceName);

    lSize = DeviceSize;

    lValue = new long[lSize];

    //
    // Processing of ReadDeviceBlock method
    //
    if (m_SelectCntl == 0)	// ActUtlType Control(CustomInterface)
    {
        hr = m_pIUtlType->ReadDeviceBlock(szDev, lSize, &lValue[0], &lRet);
    }
    else					// ActProgType Control(CustomInterface)
    {
        hr = m_pIProgType->ReadDeviceBlock(szDev, lSize, &lValue[0], &lRet);
    }

    if (SUCCEEDED(hr)) // Compornent Communication is succeeded?
    {
        if (lRet == 0x00)
        {
            for(int i = 0 ; i < lSize ; i++)
            {
                DeviceDatas << lValue[i];
            }
            ::SysFreeString(szDev);
            delete[] lValue;
            return lRet;
        }

        ::SysFreeString(szDev);
        delete[] lValue;
        return lRet;
    }
    else
    {
        m_ReturnCode = "Component communication failed.";
        qErrnoWarning(lRet,m_ReturnCode.toLatin1());
        ::SysFreeString(szDev);
        delete[] lValue;
        return lRet;
    }
}

long MXComponentModBusTCP::SetDeviceData(QString DeviceName, long DeviceSize, QList<long> DeviceDatas)
{
    long*	lValue;
    long	lRet;
    long	lSize;
    HRESULT	hr;
    BSTR	szDev = NULL;

    // Displayed output data is cleared.
    m_ReturnCode = "";


    // Allocate the BSTR-Type String area. (After use, you have to free it.)
    szDev = QStringToBSTR(DeviceName);

    lSize = DeviceSize;

    // Check the 'DeviceData'.(If succeeded, the value is gotten.)
    lValue = new long[lSize];
    for(int i = 0 ; i < lSize ; i++)
    {
        lValue[i] = DeviceDatas.at(i);
    }

    if (m_SelectCntl == 0)	// ActUtlType Control(CustomInterface)
    {
        hr = m_pIUtlType->WriteDeviceBlock(szDev, lSize, &lValue[0], &lRet);
    }
    else	// ActProgType Control(CustomInterface)
    {
        hr = m_pIProgType->WriteDeviceBlock(szDev, lSize, &lValue[0], &lRet);
    }

    if (SUCCEEDED(hr))	// Compornent Communication is succeeded?
    {
        ::SysFreeString(szDev);
        delete[] lValue;
        return lRet;
    }
    else
    {
        m_ReturnCode = "Component communication failed.";
        qErrnoWarning(lRet,m_ReturnCode.toLatin1());
        ::SysFreeString(szDev);
        delete[] lValue;
        return lRet;
    }
}

bool MXComponentModBusTCP::Init()
{
    HRESULT hr;
    // ActUtlType64 Control
    hr = CoCreateInstance(CLSID_ActUtlType64,
        NULL,
        CLSCTX_LOCAL_SERVER,
        IID_IActUtlType64,
        (LPVOID*)&m_pIUtlType);
    if (!SUCCEEDED(hr))
    {
        qDebug() << "ActUtlType64 CoCreateInstance() failed. Code :" << hr;
        return false;
    }

    // ActProgType64 Control
    hr = CoCreateInstance(CLSID_ActProgType64,
        NULL,
        CLSCTX_LOCAL_SERVER,
        IID_IActProgType64,
        (LPVOID*)&m_pIProgType);
    if (!SUCCEEDED(hr))
    {
        qDebug() << "ActProgType64 CoCreateInstance() failed. Code :" << hr;
        return false;
    }

    if( 0x00 == OpenLogicalStationNumber())
    {
        qDebug() << "PLC Open Success!";
        return true;
    }
    return true;
}

//读寄存器的线圈
void MXComponentModBusTCP::timeoutReadCoilRegister()
{
    // qDebug() << isOpen;
    if(!isOpen)
    {
        qDebug() << "Init ing......";
        isOpen =  Init();
        return;
    }


    long lisTrue;
    QList<long> datas;
    if(!initRead)
    {
        QStringList strNames;
        //声音 照明 和自动
        strNames << "M406" << "M150";

        //热痛搅拌-----> 冷旁通电磁阀
        strNames << "M50" << "M52" << "M54" << "M66" << "M70" << "M72" << "M74";

        //

        if( 0x00 == GetDeviceData(strNames,datas))
        {
            initRead = true;
            emit sig_InitRead(datas);
        }
    }

    //自动模式
    if(0x00 == GetDeviceData("M150",lisTrue))
    {
        emit sig_SendAutoModel(lisTrue);
    }

    if(0x00 == GetDeviceData("SM8000",lisTrue))
    {
        if(lisTrue == 1)
            emit sig_ReadOnlineState(true);
        else
            emit sig_ReadOnlineState(false);
    }
    else
    {
        emit sig_ReadOnlineState(false);
    }


    datas.clear();
    if( 0x00 == GetDeviceData(m_ReadCoilRegisterName,datas))
    {
        // qDebug() << "ReadCoilRegister";
        if(datas.size() == m_ReadCoilRegisterName.size())
        {
            m_ReadCoilRegisterData.clear();
            for(int i = 0; i < datas.size() ; i ++)
            {
                if(datas.at(i) == 1)
                {
                    m_ReadCoilRegisterData.insert(m_ReadCoilRegisterName.at(i),true);
                }
                else
                {
                    m_ReadCoilRegisterData.insert(m_ReadCoilRegisterName.at(i),false);
                }
            }
            emit sig_SendReadCoilRegisterData(m_ReadCoilRegisterData);
            isOpen = true;
            emit sig_ReadOnlineState(true);
        }
        else
        {
            isOpen = false;
            emit sig_ReadOnlineState(false);
            qDebug() << "读取线圈寄存器的数量和数据返回的数量不一致";
        }
    }
    else
    {
        isOpen = false;
        emit sig_ReadOnlineState(false);
        // qDebug() << "循环读取线圈寄存器失败";
        return;
    }


    //急停
    if( 0x00 == GetDeviceData("M1001",lisTrue))
    {
        // qDebug() << "M1001";
        if(lisTrue == 0)
            emit sig_StopData(false);
        else
            emit sig_StopData(true);
    }

    //安全門打開中
    if( 0x00 == GetDeviceData("X2",lisTrue))
    {
        // qDebug() << "X2";
        if(lisTrue == 0)
            emit sig_EmerGate(false);
        else
            emit sig_EmerGate(true);
    }

    //冷热温度
    datas.clear();
    QStringList Names;
    Names << "D10" << "D16";
    if( 0x00 == GetDeviceData(Names,datas))
    {
        // qDebug() << Names;
        emit sig_Temp(datas);
    }

    Names.clear();
    datas.clear();
    Names <<  "SD8341" << "SD8340" << "SD8351" << "SD8350";
    // Names << "SD8340" << "SD8350";
    if( 0x00 == GetDeviceData(Names,datas))
    {
        // qDebug() << Names;
        long low16FromNumber1 = datas[0] & 0xFFFF;
        long low16FromNumber2 = datas[1] & 0xFFFF;
        long combined16Bits1 = (low16FromNumber1 << 16) | low16FromNumber2;
        low16FromNumber1 = datas[2] & 0xFFFF;
        low16FromNumber2 = datas[3] & 0xFFFF;
        long combined16Bits2 = (low16FromNumber1 << 16) | low16FromNumber2;

        QList<long> TempData;
        TempData << combined16Bits1 << combined16Bits2;
        emit sig_XZpostion(TempData);
    }

    //当前次数 和 循环次数
    Names.clear();
    datas.clear();
    Names << "D408" << "D412";
    if( 0x00 == GetDeviceData(Names,datas))
    {
        // qDebug() << Names;
        emit sig_CurrCnt(datas);
    }

    //累计即使开始
    if( 0x00 == GetDeviceData("M85",lisTrue))
    {
        // qDebug() << "M85";
        if(lisTrue == 1)
            emit sig_addSecTimer(true);
        else
            emit sig_addSecTimer(false);
    }

    //只读的计时
    if( 0x00 == GetDeviceData("D400",lisTrue))
    {
        emit sig_updataTimeLineEdit(lisTrue);
    }

    //报警信息
    datas.clear();
    if( 0x00 == GetDeviceData(m_AlarmName,datas))
    {
        emit sig_AlarmDatas(datas);
    }

}


BSTR MXComponentModBusTCP::QStringToBSTR(const QString &qstr)
{
    std::wstring wstr = qstr.toStdWString();

    //分配一个BSTR并复制一个字符串的内容
    BSTR bstr = ::SysAllocStringLen(wstr.c_str(),qstr.length());
    if(!bstr)
    {
        qDebug() << "QStringToBSTR失败";
    }
    return bstr;
}

使用的文件 mainwindow.cpp:

	modbusTcpThread = new QThread();
    m_MXComponentModBusTCP = new MXComponentModBusTCP(nullptr);// 工业平板使用三菱插件只能在主线程,没办法分离出

    // 将 worker 移动到新线程,并确保在线程结束时删除
    m_MXComponentModBusTCP->moveToThread(modbusTcpThread);
    connect(modbusTcpThread, &QThread::finished, modbusTcpThread, &QObject::deleteLater);

    // 当 worker 被删除时,结束线程
    connect(m_MXComponentModBusTCP, &QObject::destroyed, modbusTcpThread, &QThread::quit);

    // 获取QCoreApplication的实例
    QCoreApplication *app = QCoreApplication::instance();
    if(app)
    {
        // 确保在应用程序退出时线程已经结束
        connect(app, &QCoreApplication::aboutToQuit, modbusTcpThread, &QThread::quit);
        connect(modbusTcpThread, &QThread::finished, app, &QCoreApplication::quit);
    }

    connect(m_MXComponentModBusTCP,&MXComponentModBusTCP::sig_SendReadCoilRegisterData,pcMonitoringDialog,&MonitoringDialog::slot_ShowReadCoilRegisterData,Qt::QueuedConnection);
    connect(pcManualDialog,SIGNAL(sig_SetDeviceData(QString,long)),m_MXComponentModBusTCP,SLOT(SetDeviceData(QString,long)),Qt::QueuedConnection);
    connect(pcManualDialog,SIGNAL(sig_SetDeviceDatas(QStringList,QList<long>)),m_MXComponentModBusTCP,SLOT(SetDeviceData(QStringList,QList<long>)),Qt::QueuedConnection);
    connect(pcAutoDialog,SIGNAL(sig_SetDeviceData(QString,long)),m_MXComponentModBusTCP,SLOT(SetDeviceData(QString,long)),Qt::QueuedConnection);
    connect(pcAlarmDialog,SIGNAL(sig_SetDeviceData(QString,long)),m_MXComponentModBusTCP,SLOT(SetDeviceData(QString,long)),Qt::QueuedConnection);
    connect(this,SIGNAL(sig_SetDeviceData(QString,long)),m_MXComponentModBusTCP,SLOT(SetDeviceData(QString,long)),Qt::QueuedConnection);
    connect(this,SIGNAL(sig_SetDeviceData(QStringList,QList<long>)),m_MXComponentModBusTCP,SLOT(SetDeviceData(QStringList,QList<long>)),Qt::QueuedConnection);

    //初始化的读取
    connect(m_MXComponentModBusTCP,&MXComponentModBusTCP::sig_InitRead,this,&MainWindow::slot_InitReadNameDatas);

    //急停 ,安全门 和 自动模式
    connect(m_MXComponentModBusTCP,&MXComponentModBusTCP::sig_StopData,this,&MainWindow::slot_RecStopData,Qt::QueuedConnection);
    connect(m_MXComponentModBusTCP,&MXComponentModBusTCP::sig_EmerGate,this,&MainWindow::slot_RecEmerData,Qt::QueuedConnection);

通信子线程中主要的函数:

    //单个读写
    long GetDeviceData(QString DeviceName,long& DeviceData);//long& DeviceData是返回的获取值
    long SetDeviceData(QString DeviceName,long DeviceData);//long& DeviceData是准备设置的值

    //多个读写 可不连续
    long GetDeviceData(QStringList DeviceNames, QList<long> &DeviceDatas);//QList<long>& DeviceDatas是返回的获取值
    long SetDeviceData(QStringList DeviceNames,QList<long> DeviceDatas);//QList<long> DeviceDatas是准备设置的值

    //多个连续的块读写
    long GetDeviceData(QString DeviceName, long DeviceSize,QList<long>& DeviceDatas);
    long SetDeviceData(QString DeviceName, long DeviceSize,QList<long> DeviceDatas);

逻辑站可写死为1,刚刚前面设置为1
在这里插入图片描述
可直接访问寄存器设备编号XYDM都可以。
在这里插入图片描述

注意事项

1.三菱的通信类不可以在子线程中创建主线程调用,会崩亏。
在这里插入图片描述
2.开发机器装MXComponent软件,目标机也一定要装这个软件并且要设置,否则代码运行也会崩。
3.寄存器中如果是双字,也是需要反过来,例如D5和D6组成一个浮点数,解析的时候就要按D6 D5的循序解析,转为浮点数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黄猿欲度愁攀援

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

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

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

打赏作者

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

抵扣说明:

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

余额充值