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) \n", 
 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模塊實例化和配置完成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM