一、TCPIP通信

以太网通信基本上最先想到的是TCPIP

就是在PC端的VS上布置服务器端,我用的是VS2015,最长用的是WinSock2.h

大致的步骤就是:

a.初始化版本号

b.建立套接字

c.定义并绑定地址

d.进入监听状态

e.接收连接请求

f.交换数据

有一点值得注意的是,Inter的CPU和西门子的CPU的储存方式不同,大端和小端储存方式。就是你VS定义的一个int型数据,在传输的时候char[0]是高位,而西门子的储存方式是char[3]是高位。这个也是做了大量的实验发现的问题,后来在西门子提供的prodave库中的函数也得到了证明。

send_text[0] = temp_send[3];
send_text[1] = temp_send[2];
send_text[2] = temp_send[1];
send_text[3] = temp_send[0];

转换以后再发送,数就能对的上了,但是还有问题。

做实验的时候发现,可能PLC通信的时候还需要时序的信息,还有一些不为人知的数据结构,这就导致PC发送的时候,PLC收到的是不含时序或者混乱的信息。比如我发送三个数,一个浮点一个整型,一个bool型给PLC,PLC的DB块负责接收,发现第1次接收是正确的,第2次就错了,第3次错,第4次错,第5次错,第6次正确。。。就是这样的情况。

PLC          PC
123         64
20          -34
-34         20
64          123
-20         65
81          4
4           81
65          -20
0           0
0           0
-34         0
64          0-89            64
-116            -34
123         20
20          123
82          65
-114            4
-20         81
21          -20
-89         0
-116            0
123         0
20          0-20            64
81          -34
4           20
65          123
123         65
20          4
-34         81
64          -20
0           0
0           0
4           0
65          082         64
-114            -34
-20         20
21          123
-89         65
-116            4
123         81
20          -20
82          0
-114            0
-20         0
21          082         64
-114            -34
-20         20
21          123
-89         65
-116            4
123         81
20          -20
82          0
-114            0
-20         0
21          0123            64
20          -34
-34         20
64          123
-20         65
81          4
4           81
65          -20
0           0
0           0
-34         0
64          0

就像这样的。还有一个问题就是,当第一个数只要是浮点就会发生这样的情况,但是换成第一个是整型,第二个数是浮点,问题就不会发生了。所以这样的通信是不能让人接受的。

二、OPC方式

OPC方式需要直接在PLC组态的时候就要和Windows的OPC进行OPC组态,连接成功就能通信。

需要通过vs读取windows opc中的数据,查资料知道MatrikonOPC可以简单的和VS搭配

这个需要提前安装MatrikonOPCSimulation工具,默认路径安装就行。这是代码:

#import "C://Windows//SysWOW64//OPCAuto.dll"
#pragma warning( disable : 4786 )
#include <comdef.h>
#include <vector>
#include <iostream>using namespace std;using namespace OPCAutomation;//声明全局变量
typedef struct OLEInit {OLEInit() { CoInitialize(NULL); }~OLEInit() { CoUninitialize(); }
} OLEInit;OLEInit oleInit;
OPCAutomation::IOPCAutoServerPtr opcSvr;
OPCAutomation::IOPCGroupsPtr opcGrps;
OPCAutomation::IOPCGroupPtr opcGrp;
vector<OPCAutomation::OPCItemPtr> opcItems;//连接到OPC Server
void agOPConn(const char * opcSvrName)
{HRESULT hr;hr = opcSvr.CreateInstance(_uuidof(OPCServer));if (FAILED(hr)){cerr << "OPCSever CreateInstance failed, hr = " << hr << endl;exit(1);}opcSvr->Connect(opcSvrName);
}//断开连接void agOPCDisc()
{opcGrps->RemoveAll();opcSvr->Disconnect();
}//创建一个组void agOPCCreateGroup()
{opcGrps = opcSvr->OPCGroups;opcGrp = opcGrps->Add(_variant_t("group1"));
}void agOPCAddItems()
{OPCItemPtr opcItm;opcItm = opcGrp->OPCItems->AddItem(_bstr_t("Bucket Bridge.Int4"),1);opcItems.push_back(opcItm);opcItm = opcGrp->OPCItems->AddItem(_bstr_t("Bucket Bridge.Int2"), 1);opcItems.push_back(opcItm);opcItm = opcGrp->OPCItems->AddItem(_bstr_t("Bucket Bridge.String"), 1);opcItems.push_back(opcItm);}//显示读取的值void agDumpVariant(VARIANT *v)
{switch (v->vt){case VT_I2:printf("value(VT_I2) = %d ", v->iVal);break;case VT_I4:printf("value(VT_I4) = %ld", v->lVal);break;case VT_BSTR:printf(" value(VT_BSTR) = %ls ", v->bstrVal);break;default:printf(" value(unknown type:%d) ", v->vt);break;}
}//同步读取三个Item的值,同步在很多情况下都是简单有效的选择方案,其实读取的异步方式在C++中可以建立一个工作线程来执行同步读的操作,等有新的Item值的时候再通过某种线程间通信的方式告诉主线程“数据改变”的事件
void agOPCReadItems() {_variant_t            quality;_variant_t            timestamp;SAFEARRAY            *pServerHandles;SAFEARRAY            *pValues;SAFEARRAY            *pErrors;SAFEARRAYBOUND        rgsabound[1];long                dim[1];long                svrHdl;vector<_variant_t>    values;vector<long>        errs;int                    i;_variant_t            value;long                err;// VC数组索引从0开始,而在OPCAuto.dll需要中从1开始,所以是rgsabound[ 0 ].cElements = 4,而给pServerHandles赋值的时候应该给索引是1,2,3相应的赋值Server Handlergsabound[0].cElements = 4;rgsabound[0].lLbound = 0;pServerHandles = SafeArrayCreate(VT_I4, 1, rgsabound); //构建一个1维数组,类型是VT_I4for (i = 0; i < opcItems.size(); i++) {svrHdl = opcItems[i]->ServerHandle;dim[0] = i + 1;// 给数组的每个元素赋值,对应的索引值是1, 2, 3SafeArrayPutElement(pServerHandles, dim, &svrHdl);}opcGrp->SyncRead(OPCDevice,3,                      // 读取的Item数目&pServerHandles,        // 输入的服务器端句柄数组&pValues,               // 输出的Item值数组&pErrors,               // 输出的Item错误状态数组&quality,               // 读取的值的状态&timestamp);           // 读取的事件戳for (i = 1; i <= opcItems.size(); i++) {dim[0] = i;SafeArrayGetElement(pValues, dim, &value); // 读取Item值在value中SafeArrayGetElement(pErrors, dim, &err);   // 读取错误状态值在err中   values.push_back(value);errs.push_back(err);}for (i = 0; i < values.size(); i++) {agDumpVariant(&values[i]);   // 显示读取的Item值cout << ", err = " << errs[i] << endl;}SafeArrayDestroy(pServerHandles);SafeArrayDestroy(pValues);SafeArrayDestroy(pErrors);
}// 写入3个Item的值,为了演示实例简单,参数传递3个对应的Item值
void agOPCWriteItems(vector<_variant_t> values) {_variant_t    quality;_variant_t    timestamp;SAFEARRAY    *pServerHandles;SAFEARRAY    *pValues;SAFEARRAY    *pErrors;long        dim[1];long        svrHdl;int            i;SAFEARRAYBOUND rgsabound[1];rgsabound[0].cElements = values.size() + 1;rgsabound[0].lLbound = 0;pServerHandles = SafeArrayCreate(VT_I4, 1, rgsabound);pValues = SafeArrayCreate(VT_VARIANT, 1, rgsabound);for (i = 0; i < values.size(); i++) {svrHdl = opcItems[i]->ServerHandle;dim[0] = i + 1;SafeArrayPutElement(pServerHandles, dim, &svrHdl);SafeArrayPutElement(pValues, dim, &values[i]);}opcGrp->SyncWrite(3, &pServerHandles, &pValues, &pErrors);SafeArrayDestroy(pServerHandles);SafeArrayDestroy(pValues);SafeArrayDestroy(pErrors);
}//main主程序
int main()
{try{agOPConn("Matrikon.OPC.Simulation.1");agOPCCreateGroup();agOPCAddItems();// 第一次写和读vector<_variant_t> values;values.push_back((long)156);values.push_back((short)11);values.push_back("opc");agOPCWriteItems(values);agOPCReadItems();cout << "---------------------------------------" << endl;// 第二次写和读vector<_variant_t> values1;values1.push_back((long)123456);values1.push_back((short)666);values1.push_back("hello");agOPCWriteItems(values1);agOPCReadItems();}catch (_com_error &e) {// 应该在上面的子函数里面捕捉异常,但为了演示简单,在主函数里面捕捉异常_bstr_t bstrSource(e.Source());_bstr_t bstrDescription(e.Description());cout << "Code = " << e.Error() << endl;cout << "Code meaning = " << e.ErrorMessage() << endl;cout << "Source = " << (LPCTSTR)bstrSource << endl;cout << "Description = " << (LPCTSTR)bstrDescription << endl;}system("pause");getchar();return 0;
}

因为网上的代码import的时候加了no_namespace 但是得到的.tlh找不到OPCAuto.dll的底层函数接口,所以我就加上了,namespace问题解决。这样的通信方法,一组数大约需要100ms,可能不是因为数据量的问题,可能就是这样的速度。

三、prodave

prodave是西门子提供的库,用来和vs进行通信。现在我能找到最新的是6.2版本,需要安装prodave安装包,并注册激活。

安装完成目录下会生成VB、VC的demo,但是VC的demo需要改一些东西才能在C++中编译成功。

Prodave6.2    密码:yak3

授权               密码:qr7b

我改的demo   密码:c8ce

关于PC端与PLC端以太网通信相关推荐

  1. SIMATIC WINCC与PLC进行以太网通信的具体组态方法和步骤

    SIMATIC WINCC与PLC进行以太网通信的具体组态方法和步骤 采用普通网卡通过TCP/IP与PLC通讯,通过以太网实现WICC与PLC系统连接的前提条件是PLC系统配置有以太网模块或者使用带P ...

  2. 博途PLC开放式以太网通信TRCV_C指令应用编程(运动传感器UDP通信)

    博途PLC开放式以太网通信TSENG_C指令应用,请参看下面的文章链接: 博途PLC 1200/1500PLC开放式以太网通信TSEND_C通信(UDP)_plc的udp通信_RXXW_Dor的博客- ...

  3. 查看PLC IP 端口_详解S7-1500的以太网通信数据类型:TCON_IP_v4

    西门子S7系列PLC的开放式以太网通信过程包括如下几个步骤:建立连接(Establish connection).发送/接收数据(Send/receive data).断开连接(Disconnect) ...

  4. 三菱FX系列PLC转以太网连接CHNet-FX实现以太网通信配置方法

    产品简介 兴达易控CHNet-FX是兴达易控研制的一款经济型的以太网通讯处理器,是为满足日益增多的工厂设备信息化需求(设备网络监控和生产管理)而设计,用于三菱FX1S/1N/2N/3S/3G/3GA/ ...

  5. 使用PC Access实现WinCC v7.4和S7-200 PLC之间的通信

    -- 参考自: PC Access快速入门 <现代电气控制及PLC应用技术> 王永华 北京航空航天大学 0 WinCC和S7-200 PLC之间的通信 WinCC没有集成S7-200系列的 ...

  6. 欧姆龙CP系列PLC转以太网连接CHNet-CP实现以太网通信配置方法

    产品简介 CHNet-CP是兴达易控研制的一款经济型的以太网通讯处理器,是为满足日益增多的工厂设备信息化需求(设备网络监控和生产管理)而设计,用于欧姆龙CP1L/CP1E/CP1H系列PLC的以太网数 ...

  7. 如何在 PC 机上测试移动端的网页?

    如何在 PC 机上测试移动端的网页?如果用 HTML5 写的页面,想兼容 iOS.Android 平台的手机,在 PC 机上看有些效果可能不准确,但不可能在每个移动终端都放上去看下效果吧,一般用什么工 ...

  8. 超详细的用户认证、权限、安全原理详解(认证、权限、JWT、RFC 7235、HTTPS、HSTS、PC端、服务端、移动端、第三方认证等等)

    用户认证.权限.安全 原 理 与 实 践 作者: jcLee95 邮箱 :291148484@163.com CSDN 主页:https://blog.csdn.net/qq_28550263?spm ...

  9. javascript 判断 前端 是 pc端 还是 移动端

    javascript 判断 前端 是 pc端 还是 移动端 <!DOCTYPE html> <html lang="en"> <head>< ...

最新文章

  1. static 静态成员变量和静态函数 C++
  2. Spring 整合 CXF
  3. class h5 点击后样式变化_H5学习笔记
  4. 蓝桥杯--算法训练 表达式计算
  5. JSON表单提交(ajax异步刷新)
  6. jzoj1402-偷懒的小X【贪心】
  7. C#求数组中元素的全排列
  8. http状态码_一些常见的HTTP状态码
  9. WEB前端开发规范文档+CSS命名规范
  10. C++ 面向对象编程
  11. 昨天,JetBrains 推出“下一代 IDE”,对标VS Code?快看看有哪些值得期待的功能!...
  12. 走近源码:Redis的启动过程
  13. 关于idea,双击选中问题
  14. 2022年Java面试宝典【4万字带答案】
  15. 北理工慕课 嵩天 Python零基础入门 笔记整理
  16. C++ typedef 用法详解
  17. ROS服务通信《客户端》 C++向服务端发送信息(乌龟案例,生成第二个乌龟)
  18. Failed to start LSB: Enable AMQP service provided by RabbitMQ broker.
  19. arbexpress使用教程_信号发生器使用说明
  20. 记一次JAVA中字符串首字母大写转化为小写的Code

热门文章

  1. Speedoffice(Excel)如何计算指定日期后续N天的日期
  2. android 紧急呼叫号码,android学习之——紧急呼叫
  3. Java 基础夯实2:全面了解异常
  4. 提取OutLook邮件里面的邮件头信息(发件人、收件人)
  5. 基于C++实现(MFC界面)家谱管理系统【100010005】
  6. Vue3电商项目实战-结算支付 3【05-结算-收货地址-添加、06-结算-收货地址-修改、07-结算-提交订单】
  7. 渗透测试工具-burpsuite
  8. PHP中json_encode与json_decode用法
  9. 微博短链接的生成算法(Java版本)
  10. ESP8266连接阿里云(STM32)