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的循序解析,转为浮点数。