赞
踩
每家PLC厂商都有自己的通讯协议,三菱有MC、倍福有ADS,然而没有统一性的接口协议。
为适应每一家通讯,每一家设备商、MES和工厂等都需要针对每款产品开发相应的通讯接口。
OneConnectAPI为实现统一的接口,去适配每一家厂商的协议。为中国工控行业快速发展而贡献,每一家公司都需要重新制造轮子,这是非常浪费时间和金钱,同时也不能保证稳定性以及持续的维护。
我们采取高效的多线程处理方案,保证极其高效的读写性能,对电脑性能要求极其低,一直进行读写操作,CPU使用率不超过1%(Atom E3940下测试)。
用户可以在一台工控机上进行对上百台的PLC主动读写操作,我们在光伏行业大量应用和测试过。
我们在半导体行业深耕多年,积累大量的经验,实现功能的同时,也需要保证极其严格的稳定性,晶圆生成设备7*24小时不能出任何故障。
下边是我们的接口库以及源代码。
下载地址 金南瓜科技 软件及资料书
https://gitee.com/secsgem/one-api-connect/tree/master/
https://github.com/SECSGEM/Fins
#pragma once
#include
#include “InterfaceExport.h”
#include “ModuleDevelopH.h”
// 欧姆龙Fins协议
class CFins
{
public:
CFins();
virtual ~CFins();
// 参数
CResult SetIP(std::string pIP); // 设置地址
CResult SetPort(int nPort); // 设置端口号
CResult SetTimeout(int nTimeMs); // 设置超时
// 读出
CResult Read(std::string pAddr, char& pData);
CResult Read(std::string pAddr, __int16& pData);
CResult Read(std::string pAddr, __int32& pData);
CResult Read(std::string pAddr, __int64& pData);
CResult Read(std::string pAddr, char* pData, int nSize);
CResult Read(std::string pAddr, __int16* pData, int nSize);
CResult Read(std::string pAddr, __int32* pData, int nSize);
CResult Read(std::string pAddr, __int64* pData, int nSize);
// 写入
CResult Write(std::string pAddr, char& pData);
CResult Write(std::string pAddr, __int16& pData);
CResult Write(std::string pAddr, __int32& pData);
CResult Write(std::string pAddr, __int64& pData);
CResult Write(std::string pAddr, char* pData, __int32 nSize);
CResult Write(std::string pAddr, __int16* pData, __int32 nSize);
CResult Write(std::string pAddr, __int32* pData, __int32 nSize);
CResult Write(std::string pAddr, __int64* pData, __int32 nSize);
private:
CResult SetParament(std::string pName, std::string pValue);
CResult SetParament(std::string pName, int nValue);
private:
CInterfaceExport* m_pFins;
CMgrDllDelegate m_pLoadInterface;
};
#include “stdafx.h”
#include “FinsHandle.h”
CFinsHandle::CFinsHandle()
{
m_bEstablishCommunicationByFins = false;
m_nIpNode = 0;
}
// 重写数据接收,用于协议识别
void CFinsHandle::OnDataRecv(char* pData, int nSize)
{
if (nSize > 0)
{
m_pRecvData.Append(pData, nSize);
if (m_pRecvData.Size() >= FINS_TCP_HEAD_SIZE)
{
FINS_TCP_HEAD pHead;
pHead.SetData(m_pRecvData.GetString());
int nAllSize = pHead.GetLength();
if (m_pRecvData.Size() >= nAllSize)
{
SetRecvComplete(nAllSize);
}
}
}
}
// 重写数据接收,开始接收数据,用于协议识别
void CFinsHandle::OnBeginRecv()
{
m_pRecvData.SetSize(0);
}
// 通讯关闭
void CFinsHandle::OnCloseConnect()
{
m_bEstablishCommunicationByFins = false;
}
long CFinsHandle::ReadMemoryData(int nAddr, int nSize, FINS_DATA_TYPE::ENUM nType, __int16* pData)
{
long nCode = 0;
if(nCode = EstablishCommunicationByFins())
{
return nCode;
}
CMyString pSendData; // 获取发送内存 int nAllSize; nAllSize = FINS_TCP_HEAD_SIZE; nAllSize += FINS_CONTROL_HEAD_SIZE; nAllSize += FINS_MEMORY_AREA_READ_SIZE; pSendData.SetSize(nAllSize); char* pBuff = pSendData.GetString(); // 头部信息 FINS_TCP_HEAD pHead; pHead.nCommand = FINS_TCP_CMD_DATA; pHead.SetLength(nAllSize); //长度 pHead.GetData(pBuff); // control部分 FINS_CONTROL_HEAD pControlHead; pControlHead.nDA1 = 0; pControlHead.nSA1 = m_nIpNode; pControlHead.nCmd1 = 0x01; pControlHead.nCmd2 = 0x01; pControlHead.GetData(pBuff + FINS_TCP_HEAD_SIZE); // 数据部分 FINS_MEMORY_AREA_READ pMemory; pMemory.nAreaCode = nType; pMemory.nAddr = nAddr; pMemory.nBitNo = 0; pMemory.nLength = nSize; pMemory.GetData(pBuff + FINS_TCP_HEAD_SIZE + FINS_CONTROL_HEAD_SIZE); // // 发送数据 CMyString pRecvData; nCode = SendSyncData(pSendData, pRecvData); if (nCode == 0) { // 先判断答复数据的头数据是否正确 if(nCode = CheckReplyDataIsError(pRecvData.GetString(), pRecvData.Size())) { return nCode; } // 数据头 FINS_TCP_HEAD pHeadReply; pHeadReply.SetData(pRecvData.GetString()); // 答复长度要求 int nMinSize = FINS_TCP_HEAD_SIZE + FINS_CONTROL_HEAD_SIZE + FINS_MEMORY_AREA_READ_FIX_R_SIZE + nSize * 2; if(pHeadReply.GetLength() < nMinSize) { return FINS_REPLY_READ_DATA_TOO_SHORT; } else { // FINS协议部分 FINS_CONTROL_HEAD pControlHeadReply; pControlHeadReply.SetData(pRecvData.GetString()); if (pControlHeadReply.nCmd1 != pControlHead.nCmd1 || pControlHeadReply.nCmd2 != pControlHead.nCmd2) { // 命令不一致 return FINS_REPLY_CMD_NO_IS_REQUST_CMD; } // 答复数据 FINS_MEMORY_AREA_READ_REPLY pReplyData; pReplyData.SetData(pRecvData.GetString(), pRecvData.Size()); if(pReplyData.nEndCode != 0) { return FINS_REPLY_READ_DATA_FAIL; } // 拷贝数据 int nReadByte = nSize * 2; if (pReplyData.GetDataBytsSize() == nReadByte) { memcpy(pData, pReplyData.GetData(), nReadByte); } else { return FINS_REPLY_READ_DATA_TOO_SHORT; } } } return nCode;
}
long CFinsHandle::WriteMemoryData(int nAddr, int nSize, FINS_DATA_TYPE::ENUM nType, __int16* pData)
{
long nCode = 0;
if(nCode = EstablishCommunicationByFins())
{
return nCode;
}
CMyString pSendData; int nBytsSize = nSize * 2; // 获取发送内存 int nAllSize; nAllSize = FINS_TCP_HEAD_SIZE; nAllSize += FINS_CONTROL_HEAD_SIZE; nAllSize += FINS_MEMORY_AREA_READ_SIZE; nAllSize += nBytsSize; pSendData.SetSize(nAllSize); char* pBuff = pSendData.GetString(); // 头部信息 FINS_TCP_HEAD pHead; pHead.nCommand = FINS_TCP_CMD_DATA; pHead.SetLength(nAllSize); //长度 pHead.GetData(pBuff); // control部分 FINS_CONTROL_HEAD pControlHead; pControlHead.nDA1 = 0; pControlHead.nSA1 = m_nIpNode; pControlHead.nCmd1 = 0x01; pControlHead.nCmd2 = 0x02; pControlHead.GetData(pBuff + FINS_TCP_HEAD_SIZE); // 数据部分 FINS_MEMORY_AREA_WRITE pMemory; pMemory.nAreaCode = nType; pMemory.nAddr = nAddr; pMemory.nBitNo = 0; pMemory.nLength = nSize; pMemory.pData.Append((char*)pData, nBytsSize); pMemory.GetData(pBuff + FINS_TCP_HEAD_SIZE + FINS_CONTROL_HEAD_SIZE); // // 发送数据 CMyString pRecvData; nCode = SendSyncData(pSendData, pRecvData); if (nCode == 0) { // 先判断答复数据的头数据是否正确 if(nCode = CheckReplyDataIsError(pRecvData.GetString(), pRecvData.Size())) { return nCode; } // 数据头 FINS_TCP_HEAD pHeadReply; pHeadReply.SetData(pRecvData.GetString()); // 答复长度要求 int nMinSize = FINS_TCP_HEAD_SIZE + FINS_CONTROL_HEAD_SIZE + FINS_MEMORY_AREA_WRITE_R_SIZE; if(pHeadReply.GetLength() < nMinSize) { return FINS_REPLY_READ_DATA_TOO_SHORT; } else { // FINS协议部分 FINS_CONTROL_HEAD pControlHeadReply; pControlHeadReply.SetData(pRecvData.GetString()); if (pControlHeadReply.nCmd1 != pControlHead.nCmd1 || pControlHeadReply.nCmd2 != pControlHead.nCmd2) { // 命令不一致 return FINS_REPLY_CMD_NO_IS_REQUST_CMD; } // 答复数据 FINS_MEMORY_AREA_WRITE_REPLY pReplyData; pReplyData.SetData(pRecvData.GetString()); if(pReplyData.nEndCode != 0) { return FINS_REPLY_WRITE_DATA_FAIL; } } } return nCode;
}
// 获取fins节点地址
long CFinsHandle::GetFinsNodeAddress()
{
return 0;
}
// 检查答复数据是否错误
long CFinsHandle::CheckReplyDataIsError(char* pData, int nSize)
{
if (nSize < FINS_TCP_HEAD_SIZE)
{
// 小于最小要求数据
return FINS_REPLY_DATA_TOO_SHORT;
}
// 消息错误
FINS_TCP_HEAD pHeadReply;
pHeadReply.SetData(pData);
if (pHeadReply.nErrorCode)
{
return FINS_REPLY_ERROR_BY_MESSAGE;
}
return 0;
}
// 建立通讯
long CFinsHandle::EstablishCommunicationByFins()
{
if (m_bEstablishCommunicationByFins)
{
// 已经建立通讯连接了
return 0;
}
long nCode = 0; CMyString pSendData; // 获取发送内存 int nAllSize; nAllSize = FINS_TCP_HEAD_SIZE; nAllSize += FINS_CONNECT_REQUST_SIZE; pSendData.SetSize(nAllSize); char* pBuff = pSendData.GetString(); // 头部信息 FINS_TCP_HEAD pHead; pHead.nCommand = FINS_TCP_CMD_CONNECT_REQUST; pHead.SetLength(nAllSize); //长度 pHead.GetData(pBuff); // IP地址 FINS_CONNECT_REQUST pConnectRequst; pConnectRequst.GetData(pBuff + FINS_TCP_HEAD_SIZE);
// 发送数据
CMyString pRecvData;
if(nCode = SendSyncData(pSendData, pRecvData))
{
return nCode;
}
// 处理返回值 FINS_TCP_HEAD pHeadReply; pHeadReply.SetData(pRecvData.GetString()); // 检查头信息 if (pHeadReply.nErrorCode == 0 && pHeadReply.nCommand == FINS_TCP_CMD_CONNECT_RESPONSE) { // 提取 IP Node信息 if (pHeadReply.GetLength() == FINS_TCP_HEAD_SIZE + FINS_CONNECT_RESPONS_SIZE) { // 提取 FINS_CONNECT_RESPONSE pConnectResponse; pConnectResponse.SetData(pRecvData.GetString()); m_nIpNode = pConnectResponse.pClientAddrss[3]; // 建立通讯成功 m_bEstablishCommunicationByFins = true; return 0; } } return FINS_REQUST_CONNECT_FAIL;
}
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。