• TwinCAT 3中基于UDP协议通讯的C++实现


        因为项目需要,学习了TwinCAT3中使用UDP协议进行通讯的基本知识。这个做个简单的笔记,方便以后查询。

    1 概述

    倍福为了实现从实时环境中直接访问网卡(network cards)专门提供了一个函数 “TCP/UDP Realtime”, 这个访问要么来自PLC(61131-3), 要么来自C++.这个函数对使用以下协议进行的通讯提供支持:

    • TCP/IP
    • UDP/IP
    • ARP/Ping

    TC3中使用该函数实现网络通信的示意图如下所示:

    不管使用何种协议, 在基于该协议的项目和TC3之间的通讯连接的实现都必须通过一对接口(interfaces)来实现:

    • 一个接口指针对发送数据和建立连接等功能提供支持
    • 基于回调形式(callbacks)实现一个接收器接口,该接收器接口以事件或数据的形式为项目提供反馈

    通信组件是一个TcCom对象——TCP/UDP RT, 这个通信组件通过网卡完成实例化和配置。

    2 TCP/UDP RT模块的配置

            1)在实时的以太网适配器下创建TCP/UDP RT模块

          2) 选择对应模块

           3)参数化先前创建的模块实例

     至此,我们完成了对TCP/UDP RT模块的实例化创建。

    3 实现一个具有反射服务的例程

          1) 在VS2012下创建一个TC3的解决方案

    Grafik aus Coding UDP Echo in C++ (ibter4i2.png)

             2)在Tasks下添加一个task. 然后在TMC Files里面实现一个ITcIoUdpProtocolRecv类型的接口。通过该接口的实现,TC3生成了一个method. 这个method在UDP数据包到达是被调用。

    Grafik aus Coding UDP Echo in C++ (iiuh3sj2.png)

    TCP/UDP RT模块需要一个接口指针ITcIoUdpProtocol,该指针包含了对TCP/UDP RT对象的引用。

            3)创建一个名字为udpPort 的ITcIoUdpProtocol类型的接口指针

    Grafik aus Coding UDP Echo in C++ (i3g5hbp1.png)

          4)生成TMC code. 接下来我们着重描述一个代码实现细节

    TCP/UDP RT 模块中的CycleUpdate() method 和CheckReceived() method作为模块的一部分必须被调用。

           5)    CycleUpdate() method实现如下:

    1 ///<AutoGeneratedContent id="ImplementationOf_ITcCyclic">
    2 HRESULT CModule1::CycleUpdate(ITcTask* ipTask, ITcUnknown* ipCaller, ULONG_PTR context)
    3 {
    4 HRESULT hr = S_OK;
    5     m_counter+=m_Inputs.Value;
    6     m_Outputs.Value=m_counter;
    7     m_spUdpProt->CheckReceived(); // ADDED
    8     return hr;
    9 }

    ReceivedData() method通过接口的实现被创建,并且此method将被CheckReceived()反复调用。
            6)ReveiveData() method以发送的信息和数据作为输入参数

     1 ///<AutoGeneratedContent id="ImplementationOf_ITcIoUdpProtocolRecv">
     2 HRESULT CModule1::ReceiveData(ULONG ipAddr, USHORT udpDestPort, USHORT udpSrcPort, ULONG nData, PVOID pData, ETYPE_VLAN_HEADER* pVlan)
     3 {
     4     HRESULT hr = S_OK;
     5     // mirror incomming data
     6     hr = m_spUdpProt->SendData(ipAddr, udpSrcPort, udpDestPort, nData, pData, true);
     7     m_Trace.Log(tlInfo, FLEAVEA "UDP ReceiveData: IP: %d.%d.%d.%d udpSrcPort: %d DataSize: %d (hr2=%x) 
    ", 
     8          ((PBYTE)&ipAddr)[3], ((PBYTE)&ipAddr)[2], ((PBYTE)&ipAddr)[1], ((PBYTE)&ipAddr)[0], 
     9         udpSrcPort, nData, hr);
    10     return hr; 
    11 }
    12 ///</AutoGeneratedContent>

    在开启和终止的过程中, 一个UdpProtocol接口的引用必须被设置。  

    7)端口开启在SafeOp到Op的过程中被触发,RegisterReceiver打开一个UDP端口以接收数据

     1 HRESULT CModule1::SetObjStateSO()
     2 {
     3     HRESULT hr = S_OK;
     4     //START EDITING
     5     if (SUCCEEDED(hr) && m_spUdpProt.HasOID())
     6     {
     7         m_Trace.Log(tlInfo, FLEAVEA "Register UdpProt");
     8         if (SUCCEEDED_DBG(hr = m_spSrv->TcQuerySmartObjectInterface(m_spUdpProt)))
     9         {
    10             m_Trace.Log(tlInfo, FLEAVEA "Server: UdpProt listen to Port: %d", 10000);
    11             if (FAILED(hr = m_spUdpProt->RegisterReceiver(10000,
    12  THIS_CAST(ITcIoUdpProtocolRecv))))
    13             {
    14                 m_Trace.Log(tlError, FLEAVEA "Server: UdpProtRegisterReceiver failed on Port: %d", 10000);
    15                 m_spUdpProt = NULL;
    16             }
    17     }
    18     }
    19 
    20     // If following call is successful the CycleUpdate method will be
    21 called, 
    22     // eventually even before method has been left.
    23     hr = FAILED(hr) ? hr : AddModuleToCaller(); 
    24     // Cleanup if transition failed at some stage
    25     if ( FAILED(hr) )
    26     {
    27         if (m_spUdpProt != NULL)
    28             m_spUdpProt->UnregisterReceiver(10000);
    29         m_spUdpProt = NULL;
    30         RemoveModuleFromCaller(); 
    31     }
    32     //END EDITING
    33     m_Trace.Log(tlVerbose, FLEAVEA "hr=0x%08x", hr);
    34     return hr;
    35 }

           8) 停止操作在Op到SafeOp的过程中被执行

     1 HRESULT CModule1::SetObjStateOS()
     2 {
     3     m_Trace.Log(tlVerbose, FENTERA);
     4     HRESULT hr = S_OK;
     5     
     6     if (m_spUdpProt != NULL)
     7            m_spUdpProt->UnregisterReceiver(10000);
     8     m_spUdpProt = NULL;
     9     m_Trace.Log(tlVerbose, FLEAVEA "hr=0x%08x", hr);
    10     return hr;
    11 }

    至此,TCP/UDP RT模块实例化和配置完成。

  • 相关阅读:
    英语面试自我介绍范文(二)
    在PHP中PDO解决中文乱码问题的一些补充
    英文面试自我介绍(一)
    添加XP/2003的网络用户和密码及用户自动登录
    Windows Server 2000/2003/2008错误
    数据库连接字符串大全 (转载)
    flash中特殊字符解析的使用
    创建T100Monitor技术研究过程
    LINQ,SQL查询,LINQ 实现常见SQL查询
    Web.Config 的图形配置及配置项含意
  • 原文地址:https://www.cnblogs.com/freshmen/p/4817806.html
Copyright © 2020-2023  润新知