OneApiConnect(一) Fins欧姆龙通讯协议实现源代码
每家PLC厂商都有自己的通讯协议,三菱有MC、倍福有ADS,然而没有统一性的接口协议。
为适应每一家通讯,每一家设备商、MES和工厂等都需要针对每款产品开发相应的通讯接口。
OneConnectAPI为实现统一的接口,去适配每一家厂商的协议。为中国工控行业快速发展而贡献,每一家公司都需要重新制造轮子,这是非常浪费时间和金钱,同时也不能保证稳定性以及持续的维护。
我们采取高效的多线程处理方案,保证极其高效的读写性能,对电脑性能要求极其低,一直进行读写操作,CPU使用率不超过1%(Atom E3940下测试)。
用户可以在一台工控机上进行对上百台的PLC主动读写操作,我们在光伏行业大量应用和测试过。
我们在半导体行业深耕多年,积累大量的经验,实现功能的同时,也需要保证极其严格的稳定性,晶圆生成设备7*24小时不能出任何故障。
下边是我们的接口库以及源代码。
下载链接:www.semisecs.com
接口代码
```cpp
#pragma once
#include <string>
#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;};Fins实现代码```cpp
#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;
}
OneApiConnect(一) Fins欧姆龙通讯协议实现源代码相关推荐
- OneApiConnect(二)三菱MC通讯协议源代码,高效稳定
每家PLC厂商都有自己的通讯协议,三菱有MC.倍福有ADS.modbus tcp/rtu,然而没有统一性的接口协议. 为适应每一家通讯,每一家设备商.MES和工厂等都需要针对每款产品开发相应的通讯接口 ...
- 欧姆龙OMRON PLC之HostLink通讯协议(五)- CP1H以太网FINS/TCP通讯实例
//写在前面: 自2010年起,本人陆续在新浪博客上面发了几篇OMRON PLC的应用笔记,曾经很疑惑阅读量异常增加,后来发现原来是这里有人转载.现将原文照发在这里,希望能帮到做工控的同行朋友们. C ...
- 【转】欧姆龙OMRON PLC之 CP1H 以太网FINS/TCP通讯实例
原文:http://blog.sina.com.cn/s/blog_539cee190102wr4t.html CP1H上面的选件板插槽可以插入1-2块CP1W-CIF41模块,系统即具有了以太网功能 ...
- 欧姆龙 PLC通讯协议
https://blog.csdn.net/sgmcumt/article/details/87435778 fins 欧姆龙 PLC通讯协议
- 欧姆龙CJ2M 与海利普变频器通讯 协议宏方式 欧姆龙通讯模块协议宏 功能:通过触摸屏进行启停和点动,频率设定,加减速时间,点动频率设定
欧姆龙CJ2M 与海利普变频器通讯 协议宏方式可直接拿来实用了,欧姆龙CJ2M PLC与变频器协议宏通讯 采用器件:欧姆龙CJ2M的PLC,1个CJ1W SCU21 V1通讯模块,1台海利普HLP-B ...
- 欧姆龙CJ2M 与海利普变频器通讯 协议宏方式可直接拿来实用了,欧姆龙CJ2M PLC与变频器协议宏通讯
欧姆龙CJ2M 与海利普变频器通讯 协议宏方式可直接拿来实用了,欧姆龙CJ2M PLC与变频器协议宏通讯 采用器件:欧姆龙CJ2M的PLC,1个CJ1W SCU21 V1通讯模块,1台海利普HLP-B ...
- 记录一下川崎机器人实现FINS TCP 通讯
这里写自定义目录标题 记录下项目上使用的通讯 川崎机器人套接字编程 FINS TCP报文分析 握手 读取 写入 川崎机器人通讯源码 记录下项目上使用的通讯 开个坑,在项目中利用川崎机器人自带的TCP实 ...
- xk3190串口通讯JAVA开发包_常用品牌plc通讯协议汇总学习
一.美系厂家Rockwell ABRockwell的PLC主要是包括:PLC2.PLC3.PLC5.SLC500.ControlLogix等型号,PLC2和PLC3是早期型号,现在用的比较多的小型PL ...
- 2017-2018-1 20155327 实验五 通讯协议设计
2017-2018-1 20155327 实验五 通讯协议设计 实验一: 实验要求: 在Ubuntu中完成 http://www.cnblogs.com/rocedu/p/5087623.html 中 ...
- 2017-2018-1 201553334 实验五 通讯协议设计
2017-2018-1 201553334 实验五 通讯协议设计 1.在Ubuntu中完成 http://www.cnblogs.com/rocedu/p/5087623.html 中的作业 提交运行 ...
最新文章
- swim 中一行代码解决收回键盘
- 谷歌母公司投资成绩:4大机构各有侧重,投资2个马斯克项目
- PLSQL基础语法二-流程控制,循环
- 【转】常用的工业测量坐标系
- 程序猿 自己所擅长的还是码代码 请远离 业务。
- 测试学开发——第一课:环境搭建与页面开发介绍。
- Python 中 3 个不可思议的返回
- 服务器如何启动运行,如何在服务器系统启动或重新启动时执行命令或脚本
- 江苏师范大学计算机控制考试题库,江苏技术师范学院2006¬—2007学年第2学期《微机原理与接口技术》试卷(2份,有答案)...
- 程序猿跳槽季,为什么你的薪水总升不上去?
- iOS 实现简单的列表预加载
- android httpclient版本,android版本存在 httpclient leak
- 拉杆音响电池升压芯片4.2V转12V2.5A大功率升压芯片
- read/write函数
- druid之本机批量摄取
- 如何群发电子邮件?群发邮箱账号批发吗?
- QT精确延时定时函数
- mysql在cmd下启动及操作
- 2013年07月26日
- Memory Clean 3 1.0.19 强大的mac内存清理工具
热门文章
- oracle11g监听配置访问QA
- 浅谈 NCSI 及其在 Linux 上的实现
- Mysql基础-常用sql语句
- 终于,连字节、腾讯都烧不起钱了
- 一寸照纯红色底图片_红底证件照换成蓝色背景,边缘怎样处理,才能让照片更自然呢?...
- 电脑连接热点无internet访问权限_Win10连接wifi后显示无internet访问权限如何解决...
- 【已解决】双系统启动选择的界面(GRUB)字体太小,Ubuntu登录用户界面字体太小
- python简单的构建爬虫ip代理池
- 小程序获取微信登陆用户
- 可三维成像(16,32线等)激光雷达调研