电竞比分网-中国电竞赛事及体育赛事平台

分享

在WINCC中使用WinSock控件與倍加福RFID進行TCP

 阿毅s6kc8rp1nf 2017-10-16
  http://blog.csdn.net/ohiolee/article/details/17878567
在柔性制造FMS系統(tǒng)中,本次項目以西門子PLC300,PLC200和倍加福RFID構(gòu)建自動化輸送和立體倉庫物流方案。

硬件:

1、一個西門子PLC300為主站,四個PLC200為從站

2、倍加福RFID IC-KP-B17-AIDA1 IDENTControl interface with Ethernet interface的識別系統(tǒng)

系統(tǒng):

因為西門子PLC,選用WinCC做組態(tài)畫面,VBS實現(xiàn)MES/WMS的功能。

 

課題:

因為首次選用帶TCP/IP的倍加福RFID,需要解決其與WinCC的通訊問題。

 

倍加福RFID有兩種方式可以進行通訊,一、DLL,通過加載和調(diào)用所提供的DLL進行通訊;二、TCP的Socket進行通訊。

首先嘗試了DLL,在WinCC中是可以調(diào)用DLL的,嘗試了一個簡單的DLL進行測試。

在WinCC圖形編輯器中添加一個按鈕,2個輸入輸出框。在按鈕點擊事件中創(chuàng)建以下代碼:

  1. #include "apdefap.h"  
  2. void OnLButtonDown(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nFlags, int x, int y)  
  3. {  
  4.   
  5. #pragma code ("c:/DLL/T1_C.dll")  //指定絕對路徑,網(wǎng)上有說放在WinCC/bin目錄的,好像不靠譜還是這樣好。  
  6. int aufruf1(int a);  //聲明函數(shù)  
  7. #pragma code ()  
  8.   
  9. int value;  
  10. value = GetTagDouble("var1"); //Return-Type: double  
  11. SetTagDouble("result",aufruf1(value)); //Return-Type: BOOL  
  12.   
  13. }  

 

其中T1_C.dll里有一個返回參數(shù)+100的aufruf1函數(shù)。詳見 http://www.cnblogs.com/ohiolee/articles/3498381.html

但是倍加福提供的RFID_TCP_DLL及示例代碼是C++的,沒怎么弄明白要怎么聲明里面的函數(shù),還有類的問題。代碼如下:

  1. /* in your c++ header file */  
  2.   
  3. #include "RFIDTCP.h"  
  4. #pragma comment(lib, "..\\impDLL\\PF_RFID_LIB.lib")  
  5.   
  6. /* in your c++ CPP file */  
  7.   
  8. void RFID_test()  
  9. {  
  10.     int ret;  
  11.     RFIDTCP *pRFIDTCP;  
  12.     pRFIDTCP=new RFIDTCP;  
  13.     rfidMSG *pRfidMSG;  
  14.     pRfidMSG= new rfidMSG;  
  15.     pRFIDTCP->setupDevice("192.168.40.119",2);  
  16.       
  17.     int startAddr=0;  
  18.     int wordNum=0;  
  19.     int channel;  
  20.     int ms_BlocTimeout=1000;  
  21.     int retStatus;  
  22.   
  23.     channel=1;  
  24.   
  25.     pRFIDTCP->connectDevice(ms_BlocTimeout);  
  26.   
  27.     /* CT Test */  
  28.     pRfidMSG->reset();  
  29.     ret=pRFIDTCP->rfidCT(channel,pRfidMSG->pMsgBuff,"21",&retStatus);  
  30.     TRACE("CT [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  31.   
  32.       
  33.     startAddr=0;  
  34.     wordNum=26/4+1;  
  35.   
  36.     Sleep(500);  
  37.     /* SW Test */  
  38.     pRfidMSG->reset();  
  39.     ret=pRFIDTCP->rfidSW(channel,startAddr,wordNum,pRfidMSG->pMsgBuff,"zyxvwutsrqponmlkjihgfedcba",&retStatus);  
  40.     TRACE("SW [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  41.   
  42.     /* SR Test */  
  43.       
  44.     pRfidMSG->reset();  
  45.     ret=pRFIDTCP->rfidSR(channel,startAddr,wordNum,pRfidMSG->pMsgBuff,&retStatus);  
  46.     TRACE("SR [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  47.       
  48.   
  49.     /* QU Test */  
  50.     pRfidMSG->reset();  
  51.     ret=pRFIDTCP->rfidQU(channel,pRfidMSG->pMsgBuff,&retStatus);  
  52.     TRACE("QU [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  53.   
  54.     /* SF Test */  
  55.     pRfidMSG->reset();  
  56.     ret=pRFIDTCP->rfidSF(channel,pRfidMSG->pMsgBuff,&retStatus);  
  57.     TRACE("SF [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  58.   
  59.   
  60.   
  61.       
  62.     /* EW Test */  
  63.     /*wordNum MUST <= 15 () */  
  64.     pRfidMSG->reset();  
  65.     char wContent[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ@ABCDEFGHIJKLMNOPQRSTUVWXYZ@@ABCDEFGHIJKLMNOPQRSTUVWXYZ@";  
  66.     //wordNum=(strlen(wContent)/4+1);  
  67.     wordNum=15;  
  68.     ret=pRFIDTCP->rfidEW(channel,startAddr,wordNum,pRfidMSG->pMsgBuff,wContent,&retStatus);  
  69.     pRfidMSG->reset();  
  70.     TRACE("EW [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  71.     for(int i=0;i<5;i++)  
  72.     {  
  73.         pRfidMSG->reset();  
  74.         ret=pRFIDTCP->enhancedMSGRec(pRfidMSG);  
  75.         TRACE("EW [ret=%d][i=%d][status=%d][%s]\n",ret,i,pRfidMSG->status,pRfidMSG->pString);  
  76.     }  
  77.   
  78.     /* QU Test */  
  79.     pRfidMSG->reset();  
  80.     ret=pRFIDTCP->rfidQU(channel,pRfidMSG->pMsgBuff,&retStatus);  
  81.     TRACE("QU [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  82.   
  83.     /* ER Test */  
  84.     pRfidMSG->reset();  
  85.     ret=pRFIDTCP->rfidER(channel,startAddr,wordNum,pRfidMSG->pMsgBuff,&retStatus);  
  86.     TRACE("ER [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  87.     pRfidMSG->reset();  
  88.     for(int i=0;i<5;i++)  
  89.     {  
  90.         pRfidMSG->reset();  
  91.         ret=pRFIDTCP->enhancedMSGRec(pRfidMSG);  
  92.         TRACE("ER [ret=%d][i=%d][status=%d][%s]\n",ret,i,pRfidMSG->status,pRfidMSG->pString);  
  93.     }  
  94.   
  95.     /* QU Test */  
  96.     pRfidMSG->reset();  
  97.     ret=pRFIDTCP->rfidQU(channel,pRfidMSG->pMsgBuff,&retStatus);  
  98.     TRACE("QU [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  99.   
  100.   
  101.     /* EF Test */  
  102.     pRfidMSG->reset();  
  103.     ret=pRFIDTCP->rfidEF(channel,startAddr,wordNum,pRfidMSG->pMsgBuff,&retStatus);  
  104.     TRACE("EF [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  105.     pRfidMSG->reset();  
  106.     for(int i=0;i<5;i++)  
  107.     {  
  108.         pRfidMSG->reset();  
  109.         ret=pRFIDTCP->enhancedMSGRec(pRfidMSG);  
  110.         TRACE("EF [ret=%d][i=%d][status=%d][%s]\n",ret,i,pRfidMSG->status,pRfidMSG->pString);  
  111.         if(ret>6)  
  112.         {  
  113.             TRACE("[");  
  114.             for(int j=0;j<(ret-6); j++)  
  115.                 TRACE("0x%02x ",(unsigned char )*(pRfidMSG->pString+j));  
  116.             TRACE("]\n");  
  117.         }  
  118.     }  
  119.   
  120.     /* QU Test */  
  121.     pRfidMSG->reset();  
  122.     ret=pRFIDTCP->rfidQU(channel,pRfidMSG->pMsgBuff,&retStatus);  
  123.     TRACE("QU [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  124.   
  125.   
  126.   
  127.     /* RS Test */  
  128.     pRfidMSG->reset();  
  129.     ret=pRFIDTCP->rfidRS(channel,pRfidMSG->pMsgBuff,&retStatus);  
  130.     TRACE("RS [ret=%d][%s][status=%d]\n",ret,pRfidMSG->pString,retStatus);  
  131.   
  132.   
  133.   
  134.     pRFIDTCP->disconnectDevice();  
  135.     delete pRFIDTCP;  
  136.     delete pRfidMSG;      
  137.   
  138. }  


 

最終沒能實現(xiàn)。要求廠家提供VB示例代碼也沒能給過來。

轉(zhuǎn)而研究了其Socket的通訊方式。其報文格式如下:

[plain] view plain copy
  1. 報文格式請參看手冊26頁,27頁。報文格式是這樣的  
  2.   
  3. *****************************************************  
  4.                CT格式  
  5.   
  6. 00:06:04:02:30:33 (6個字節(jié)的字符)  
  7. 00:06 報文總長度  
  8. 就是CT的命令格式,0x 10是讀 就是 SR命令, 000610220000  
  9. 通道1,0000 0010 紅色標記的就是通道的編號  
  10. 30:33 Tag type (IPC03)   
  11. 發(fā)生命令以后,控制器會回復一個6個字節(jié)的確認短報文,一個6個或者6個字節(jié)以上的回復報文。  
  12.   
  13. 確認短報文:  
  14. 00:06:04:02:FF:01  
  15. 00:06報文總長度  
  16. 重復一下命令(CT)  
  17. 重復受到的命令  
  18. FF Status FFh (說明正在執(zhí)行)  
  19. 回復的計數(shù)器 到0xff以后會重新開始計數(shù)   
  20.   
  21. 回復報文  
  22.   
  23. 00:06:04:02:00:02  
  24. 00:06報文總長度  
  25. 04重復一下命令(CT)  
  26. 02重復受到的命令  
  27. Status 0 (0表示命令成功完成,如果不是0,可以參考10 Troubleshooting 的10.1 Fault/Status messages P114. 有返回錯誤碼的解釋)  
  28. 02回復的計數(shù)器  
  29.   
  30. *****************************************************  
  31.                單次寫SW 命令:  
  32. 0A 40 12 00 01 39 38 37 36  
  33. 0A報文總長度  
  34. 40命令(SW)  
  35.  (0001 0010)紅色表示寫一個雙字,也就是4個字節(jié)  
  36. 01 表示起始地址是1.也就從地址0 偏移一個雙字(4個字節(jié))  
  37. 38 37 36 表示寫入的數(shù)值,這里就是ASCII :9876  
  38. SW的確認短報文  
  39. 06 40 12 ff 67   
  40. SW的回復報文  
  41. 06 40 02 00 68          
  42.    
  43. **************************************************  
  44.   
  45. 單次讀SR 命令:  
  46. 00:06:10:22:00:00  
  47. 00:06 報文總長度  
  48. 10命令(SR)  
  49. (0010 0010)Word number (2) / Channel (1), toggle bit (0)  
  50. 00:00 讀起始地址(0000)  
  51.   
  52. 確認短報文  
  53. 00:06:10:22:FF:01  
  54. 00:06報文總長度  
  55. 10重復一下命令(SR)  
  56. (0010 0010)Word number (2) / Channel (1), toggle bit (0)  
  57. FF Status FFh (processing command)  
  58. 01回復的計數(shù)器  
  59.   
  60.                回復報文  
  61.   
  62. 00:0E:10:22:00:02:31:32:33:34:35:36:37:38  
  63. 00:0E報文總長度(14 bytes)  
  64. 10重復一下命令(SR)  
  65. (0010 0010)Word number (2) / Channel (1), toggle bit (0)  
  66. Status 0 (成功運行)  
  67. 回復的計數(shù)  
  68. 31:32:33:34:35:36:37:38 讀出數(shù)據(jù)   
  69.   
  70. 注意,:冒號表示一個字節(jié)間的分割,但是TCP傳輸報文中,沒有冒號的。  


 

拿到這些資料,首先面對的問題是WinCC中沒有WinSock控件,網(wǎng)上找到了一篇《關(guān)于在WINCC中使用WinSock控件進行TCP_IP通訊的例程》的文檔,介紹的比較詳細。

 

一、在WINCC中使用WinSock控件進行TCP_IP通訊的例程

1、WinSock控件注冊

在WinCC中使用WinSock控件前,需要先進行注冊。下載地址:http://down5.cr173.com//soft1/MSWINSCK.rar

注冊方法如下:

使用記事本新建一個后綴名為bat的文件,編輯文件,加入以下文本:

Copy /y MSWINSCK.OCX %windir%\system32\
regsvr32/s %windir%\system32\MSWINSCK.OCX

保存文件退出。雙擊執(zhí)行即可。(下載地址中提供了安裝.bat文件,雙擊即可)

 

2、在WinCC中添加WinSock控件

在WinCC圖形編輯器中打開需要顯示服務(wù)器數(shù)據(jù)的畫面,選擇“對象選項板”的“控件”選項卡,在選項卡中選擇“添加/刪除”,在“選擇OCX控件”對話框中選擇“Microsoft WinSock Control, version 6.0”進行注冊。

在對象選項板中的WinSock控件拖入畫面中。

 

在實施到服務(wù)器上時,碰到了以下問題。

“未找到許可證信息(winsock)”

網(wǎng)上找到了一個神解決方案:

打開注冊表,找?到HKEY_CLASSES_?ROOT下的Licenses,在他下面添加一個項,并且命名為2c49f800-c2dd-11cf-9ad6-0080c7e7b78d,然后修改這個項的默認值為:mlrljgrlhltlngjlthrligklpkrhllglqlrk,關(guān)閉注冊表編輯器,再次啟動WINCC即可。

 這不是WinCC的許可問題,而是WinSock的注冊問題。

 

二、因為需要做數(shù)據(jù)轉(zhuǎn)換,需導入ads.dll,下載 ArrayConvert.exe 文件。

以下文件是可從 Microsoft 下載中心下載:
收起這個圖片展開這個圖片Download the arrayconvert.exe package now. (http://download.microsoft.com/download/exch55/sample/55/win98/en-us/arrayconvert.exe)
打開您下載 ArrayConvert.exe 文件文件夾,然后雙擊 ArrayConvert.exe 文件。
在 解壓縮到文件夾 框中鍵入 C:\ArrayConvert,然后單擊 解壓縮。
單擊 確定,然后單擊 關(guān)閉。
單擊 開始,單擊 運行,鍵入 regsvr32 C:\ArrayConvert\ads.dll,然后按 ENTER 鍵。
單擊 確定。


 

  1. '-------------------------------------------------------------------------------  
  2. '    連接倍加福RFID  
  3. '-------------------------------------------------------------------------------  
  4. Function RFID_Connect  
  5.     Dim Obj_SockClient  
  6.     Dim cnvt  
  7.     Dim Tag_intTXStatus  
  8.     Dim i,j  
  9.     Dim Tag_f,Tag_b  
  10.       
  11.     ScreenItems("msg").Text = "Obj_SockClient init" & Chr(13) & Chr(10) & ScreenItems("msg").Text  
  12.     '獲得當前窗口中的WinSock對象  
  13.     Set Obj_SockClient = ScreenItems("objSock")  
  14.       
  15.     '這是一個轉(zhuǎn)換DLL,后面還要講到  
  16.     Set cnvt = CreateObject("ADS.ArrayConvert")  
  17.       
  18.     '以下是建立連接前的參數(shù)初始化工作,遠程地址和端口號根據(jù)實際情況修改,此處設(shè)置是為了方便測試工作,可使用TCP&UDP測試工具進行測試。  
  19.     'Obj_SockClient.Protocol = "sckTCPProtocol"  
  20.     'Obj_SockClient.RemoteHost = "192.168.1.222"  
  21.     'Obj_SockClient.RemotePort = 10000  
  22.     ScreenItems("msg").Text = "Obj_SockClient.Protocol=" & Obj_SockClient.Protocol & Chr(13) & Chr(10) & ScreenItems("msg").Text  
  23.     ScreenItems("msg").Text = "Obj_SockClient.RemoteHost=" & Obj_SockClient.RemoteHost & Chr(13) & Chr(10) & ScreenItems("msg").Text  
  24.     ScreenItems("msg").Text = "Obj_SockClient.RemotePort=" & Obj_SockClient.RemotePort & Chr(13) & Chr(10) & ScreenItems("msg").Text  
  25.     ScreenItems("msg").Text = "Obj_SockClient.State=" & Obj_SockClient.State & Chr(13) & Chr(10) & ScreenItems("msg").Text  
  26.       
  27.     '連接沒有建立、連接錯誤、同級人員正在關(guān)閉連接,這三種情況下,先關(guān)閉連接,再嘗試建立連接。  
  28.     If (Obj_SockClient.State = 0) Or (Obj_SockClient.State = 9) Or (Obj_SockClient.State = 8) Then  
  29.         Obj_SockClient.Close   
  30.         Obj_SockClient.Connect  
  31.     End If  
  32.     ScreenItems("msg").Text = "Obj_SockClient.Connect=" & Obj_SockClient.State & Chr(13) & Chr(10) & ScreenItems("msg").Text  
  33.        
  34.       
  35. End Function  


  1. Sub DataArrival(ByVal Item,  ByVal bytesTotal)                        
  2.     On Error Resume Next  
  3.       
  4.     Dim cnvt  
  5.     Dim obj_OutText  
  6.     Dim strReceive  
  7.     Dim strFromRec  
  8.     Dim strTest  
  9.           
  10.     Set cnvt = CreateObject("ADS.ArrayConvert")  
  11.     Set obj_OutText = ScreenItems("objOutText")  
  12.       
  13. '    MsgBox "DataArrival:bytesTotal=" & bytesTotal  
  14.     strFromRec = ""  
  15.     Set strReceive = Null  
  16.     '從接收緩沖區(qū)取得數(shù)據(jù),并清空緩沖區(qū)  
  17.     Item.GetData strReceive  
  18.       
  19.     strFromRec = cnvt.CvOctetStr2vHexStr(strReceive)  
  20. 'obj_OutText.Text = "strFromRec=" & strTest & Chr(13) & Chr(10) & obj_OutText.Text  
  21.     If Len(strFromRec) > 0 Then  
  22.         getDataArrival(strFromRec)  
  23.     End If  
  24.       
  25. End Sub  


  

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多