当前位置:   article > 正文

OneAPIConnect(一) 欧姆龙FINS协议实现源代码

oneapiconnect

每家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);		// 设置超时
  • 1
  • 2
  • 3
  • 4

// 读出
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); 
  • 1
  • 2
  • 3
  • 4

// 写入
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); 
  • 1
  • 2
  • 3
  • 4

private:

CResult SetParament(std::string pName, std::string pValue); 
CResult SetParament(std::string pName, int nValue); 
  • 1
  • 2

private:

CInterfaceExport* m_pFins;
CMgrDllDelegate m_pLoadInterface;
  • 1
  • 2

};

#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);
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

}

// 重写数据接收,开始接收数据,用于协议识别
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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

}

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

}

// 获取fins节点地址
  • 1

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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

}

// 建立通讯
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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

// 发送数据
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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

}

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号