QT-C++ 西门子snap7通讯库接口

时间:2024-11-01 22:29:57
#include "Snap7ConObject.h" #include "snap7.h" #include <QDebug> #include <QTime> #include <QDataStream> struct sSnapData { int nErrorCount = 0; bool bExit = false; bool bConneted = false; TS7Client *pClient = nullptr; QMutex funMutex; // 为了保证通讯的稳定性,函数接口锁为必须 }; // 不阻塞定时器 struct sSnap7Timer { QTime time; uint32_t interval; void start(uint32_t t) { interval = t; time.restart(); }; bool isTimeOut() { return time.elapsed() > interval; }; }; cSnapConObject::cSnapConObject(QObject *parent) : QThread(parent) , m_ptr(new sSnapData()) { m_ptr->pClient = new TS7Client(); this->start(); } cSnapConObject::~cSnapConObject() { } /** * @brief 获取示例对象 * @param[IN] * @param[OUT] * @return 对象指针 * * @note */ cSnapConObject *cSnapConObject::getInstance() { static cSnapConObject instance; return &instance; } void cSnapConObject::run() { static int nStep = 0; static sSnap7Timer timeout; while (true) { QThread::msleep(100); if (m_ptr->bExit) return; switch (nStep) { case 0: { // 掉线重新连接 if (m_ptr->nErrorCount > 50) { nStep = 1; } }break; case 1: { if (!m_ptr->pClient->Connected()) { int nRet = m_ptr->pClient->ConnectTo(m_strIp.toStdString().c_str(), m_nRackNumber, m_nSlotNumber); if (nRet == 0) { m_ptr->nErrorCount = 0; m_ptr->bConneted = true; } else m_ptr->bConneted = false; } else { m_ptr->nErrorCount = 0; } timeout.start(5 * 1000); nStep = 2; }break; case 2: { if (timeout.isTimeOut()) { nStep = 0; } }break; default: break; } } } // 连接 bool cSnapConObject::connect(QString strIp, int nPort, int nRack, int nSlot) { m_strIp = strIp; m_nPort = nPort; m_nRackNumber = nRack; m_nSlotNumber = nSlot; int nRet = m_ptr->pClient->ConnectTo(strIp.toStdString().c_str(), nRack, nSlot); if (nRet == 0) m_ptr->bConneted = true; else m_ptr->bConneted = false; return m_ptr->bConneted; } // 读取VW寄存器值(16)位 bool cSnapConObject::readInt16(uint16_t uAddr, int16_t &nValue,int nDb) { if (!m_ptr->bConneted) return false; int16_t buffer[1] = { 0 }; bool bRet = readMultInt16(uAddr, 1, buffer, nDb); nValue = buffer[0]; return bRet; } // 批量读取16位 bool cSnapConObject::readMultInt16(uint16_t uStartAddr, int nCount, int16_t *buffer, int nDb) { if (!m_ptr->bConneted) return false; // 创建用于读取的数据缓冲区 QByteArray data(nCount * sizeof(int16_t), 0); int nRet = m_ptr->pClient->ReadArea(S7AreaDB, nDb, uStartAddr, nCount * sizeof(int16_t), S7WLByte, data.data()); if (nRet == 0) { // 如果没有错误 QDataStream dataStream(data); dataStream.setByteOrder(QDataStream::BigEndian); // 设置字节序为大端 // 逐个读取 qint16 数据并转换 for (int i = 0; i < nCount; ++i) { int16_t value; dataStream >> value; // 读取 qint16 值 //buffer[i] = bigEndianToLittleEndian(value); buffer[i] = (value); } return true; } else m_ptr->nErrorCount++; return false; } // 读取VD寄存器值(32)位 bool cSnapConObject::readInt32(uint16_t uAddr, int32_t &nValue, int nDb) { if (!m_ptr->bConneted) return false; int32_t buffer[1] = { 0 }; bool bRet = readMultiInt32(uAddr, 1, buffer, nDb); nValue = buffer[0]; return bRet; } // 批量读取32位 bool cSnapConObject::readMultiInt32(uint16_t uStartAddr, int nCount, int32_t *buffer, int nDb) { if (!m_ptr->bConneted) return false; // 创建用于读取的数据缓冲区 QByteArray data(nCount * sizeof(int32_t), 0); int nRet = m_ptr->pClient->ReadArea(S7AreaDB, nDb, uStartAddr, nCount * sizeof(int32_t), S7WLByte, data.data()); if (nRet == 0) { // 如果没有错误 QDataStream dataStream(data); dataStream.setByteOrder(QDataStream::BigEndian); // 设置字节序为大端 // 逐个读取 int32_t 数据并转换 for (int i = 0; i < nCount; ++i) { int32_t value; dataStream >> value; // 读取 int32_t 值 //buffer[i] = bigEndianToLittleEndian(value); buffer[i] = (value); } return true; } return false; } // 读取浮点 bool cSnapConObject::readFloat(uint16_t uAddr, float &fValue, int nDb) { float fArray[1] = {0.0}; bool bRet = readMultiFloat(uAddr,1,fArray); fValue = fArray[0]; return bRet; } // 读取多个浮点数寄存器 bool cSnapConObject::readMultiFloat(uint16_t uStartAddr, int nCount, float *buffer, int nDb) { if (!m_ptr->bConneted) return false; // 创建用于读取的数据缓冲区 int nSize = sizeof(float); QByteArray data(nCount * sizeof(float), 0); int nRet = m_ptr->pClient->ReadArea(S7AreaDB, nDb, uStartAddr, nCount * sizeof(float), S7WLByte, data.data()); if (nRet == 0) { // 如果没有错误 QDataStream dataStream(data); //dataStream.setByteOrder(QDataStream::BigEndian); // 设置字节序为大端 dataStream.setFloatingPointPrecision(QDataStream::SinglePrecision); // 逐个读取 float 数据并转换 for (int i = 0; i < nCount; ++i) { float value; dataStream >> value; // 读取 float 值 buffer[i] = (value); } return true; } return false; } // 读取M x.x bool cSnapConObject::readM(uint16_t uStartByte, uint16_t uBitOffset, bool &bState, int nDb) { if (!m_ptr->bConneted) return false; uint8_t boolValue = 0; // 存储读取到的布尔值 int nRet = m_ptr->pClient->ReadArea(S7AreaMK, nDb, uStartByte, 1, S7WLBit, &boolValue); if (nRet == 0) { bState = (boolValue & (1 << uBitOffset)) != 0; return true; } else m_ptr->nErrorCount++; return false; } // 读取输入点 bool cSnapConObject::readInput_X(uint16_t uStartByte, uint16_t uBitOffset, bool &bState, int nDb) { if (!m_ptr->bConneted) return false; uint8_t boolValue = 0; int nRet = m_ptr->pClient->ReadArea(S7AreaPE, nDb, uStartByte, 1, S7WLBit, &boolValue); if (nRet == 0) { bState = (boolValue & (1 << uBitOffset)) != 0; return true; } else m_ptr->nErrorCount++; return false; } // 读取输出点 bool cSnapConObject::readOutput_Y(uint16_t uStartByte, uint16_t uBitOffset, bool &bState, int nDb) { if (!m_ptr->bConneted) return false; uint8_t boolValue = 0; int nRet = m_ptr->pClient->ReadArea(S7AreaPA, nDb, uStartByte, 1, S7WLBit, &boolValue); if (nRet == 0) { bState = (boolValue & (1 << uBitOffset)) != 0; return true; } else m_ptr->nErrorCount++; return false; } // 写入16位整数 bool cSnapConObject::writeInt16(uint16_t uAddr, int16_t nValue, int nDb) { int16_t buffer[1] = { nValue }; return writeMultiInt16(uAddr, 1, buffer, nDb); } // 批量写入 bool cSnapConObject::writeMultiInt16(uint16_t uStartAddr, int nCount, int16_t *buffer, int nDb) { if (!m_ptr->bConneted) return false; std::vector<byte> bufferTemp(nCount * sizeof(int16_t)); // 将 INT16 数据转换为大端格式并填入缓冲区 for (size_t i = 0; i < nCount; ++i) { convertInt16ToBigEndian(buffer[i], &bufferTemp[i * sizeof(int16_t)]); } int nRet = m_ptr->pClient->WriteArea(S7AreaDB, nDb, uStartAddr,nCount*sizeof(int16_t), S7WLByte, bufferTemp.data()); if (nRet == 0) return true; else m_ptr->nErrorCount++; return false; } // 写入32位整数 bool cSnapConObject::writeInt32(uint16_t uAddr, int32_t nValue, int nDb) { if (!m_ptr->bConneted) return false; int32_t buffer[1] = { nValue }; return writeMultiInt32(uAddr,1,buffer,nDb); } // 批量写入 bool cSnapConObject::writeMultiInt32(uint16_t uStartAddr, int nCount, int32_t *buffer, int nDb) { if (!m_ptr->bConneted) return false; std::vector<byte> bufferTemp(nCount * sizeof(int32_t)); // 将 INT32 数据转换为大端格式并填入缓冲区 for (size_t i = 0; i < nCount; ++i) { convertInt32ToBigEndian(buffer[i], &bufferTemp[i * sizeof(int32_t)]); } int nRet = m_ptr->pClient->WriteArea(S7AreaDB, nDb, uStartAddr,nCount*sizeof(int32_t), S7WLByte, bufferTemp.data()); if (nRet == 0) return true; else m_ptr->nErrorCount++; return false; } // 写入浮点数 bool cSnapConObject::writeFloat(uint16_t uAddr, float fValue, int nDb) { float buffer[1] = { fValue }; return writeMultiFloat(uAddr,1,buffer,nDb); } // 批量写入浮点数 bool cSnapConObject::writeMultiFloat(uint16_t uStartAddr, int nCount, float *buffer, int nDb) { if (!m_ptr->bConneted) return false; // 准备要写入的数据的字节数组 QByteArray byteArray; for (size_t i = 0; i < nCount; ++i) { float value = buffer[i]; QByteArray tempData(reinterpret_cast<const char*>(&value), sizeof(float)); // 大端转换:将字节顺序反转 for (int j = sizeof(float) - 1; j >= 0; --j) { byteArray.append(tempData[j]); } } int nRet = m_ptr->pClient->WriteArea(S7AreaDB, nDb, uStartAddr, byteArray.size(), S7WLByte, byteArray.data()); if (nRet == 0) return true; else m_ptr->nErrorCount++; return false; } // 写入M x.x bool cSnapConObject::writeM(uint16_t uStartByte, uint16_t uBitOffset, bool bState, int nDb) { if (!m_ptr->bConneted) return false; // 准备写入的数据 uint8_t dataToWrite = 0; if (bState) dataToWrite = (1 << uBitOffset); // 构造要写入的数据 // 读取当前的值 uint8_t currentData = 0; int nRet = m_ptr->pClient->ReadArea(S7AreaMK, nDb, uStartByte, 1, S7WLBit, &currentData); if (nRet != 0) { m_ptr->nErrorCount++; return false; } // 更新数据 if (bState) currentData |= dataToWrite; // eg.设置 M2.2 对应的位 else currentData &= ~dataToWrite; // eg.清除 M2.2 对应的位 // 写入 int nRet1 = m_ptr->pClient->ReadArea(S7AreaMK, nDb, uStartByte, 1, S7WLBit