分享

在WINCC中使用WinSock控件与倍加福RFID进行TCP

 阿毅s6kc8rp1nf 2017-10-16
  http://blog.csdn.net/ohiolee/article/details/17878567
在柔性制造FMS系统中,本次项目以西门子PLC300,PLC200和倍加福RFID构建自动化输送和立体仓库物流方案。

硬件:

1、一个西门子PLC300为主站,四个PLC200为从站

2、倍加福RFID IC-KP-B17-AIDA1 IDENTControl interface with Ethernet interface的识别系统

系统:

因为西门子PLC,选用WinCC做组态画面,VBS实现MES/WMS的功能。

 

课题:

因为首次选用带TCP/IP的倍加福RFID,需要解决其与WinCC的通讯问题。

 

倍加福RFID有两种方式可以进行通讯,一、DLL,通过加载和调用所提供的DLL进行通讯;二、TCP的Socket进行通讯。

首先尝试了DLL,在WinCC中是可以调用DLL的,尝试了一个简单的DLL进行测试。

在WinCC图形编辑器中添加一个按钮,2个输入输出框。在按钮点击事件中创建以下代码:

  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")  //指定绝对路径,网上有说放在WinCC/bin目录的,好像不靠谱还是这样好。  
  6. int aufruf1(int a);  //声明函数  
  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里有一个返回参数+100的aufruf1函数。详见 http://www.cnblogs.com/ohiolee/articles/3498381.html

但是倍加福提供的RFID_TCP_DLL及示例代码是C++的,没怎么弄明白要怎么声明里面的函数,还有类的问题。代码如下:

  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. }  


 

最终没能实现。要求厂家提供VB示例代码也没能给过来。

转而研究了其Socket的通讯方式。其报文格式如下:

[plain] view plain copy
  1. 报文格式请参看手册26页,27页。报文格式是这样的  
  2.   
  3. *****************************************************  
  4.                CT格式  
  5.   
  6. 00:06:04:02:30:33 (6个字节的字符)  
  7. 00:06 报文总长度  
  8. 就是CT的命令格式,0x 10是读 就是 SR命令, 000610220000  
  9. 通道1,0000 0010 红色标记的就是通道的编号  
  10. 30:33 Tag type (IPC03)   
  11. 发生命令以后,控制器会回复一个6个字节的确认短报文,一个6个或者6个字节以上的回复报文。  
  12.   
  13. 确认短报文:  
  14. 00:06:04:02:FF:01  
  15. 00:06报文总长度  
  16. 重复一下命令(CT)  
  17. 重复受到的命令  
  18. FF Status FFh (说明正在执行)  
  19. 回复的计数器 到0xff以后会重新开始计数   
  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回复的计数器  
  29.   
  30. *****************************************************  
  31.                单次写SW 命令:  
  32. 0A 40 12 00 01 39 38 37 36  
  33. 0A报文总长度  
  34. 40命令(SW)  
  35.  (0001 0010)红色表示写一个双字,也就是4个字节  
  36. 01 表示起始地址是1.也就从地址0 偏移一个双字(4个字节)  
  37. 38 37 36 表示写入的数值,这里就是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回复的计数器  
  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. 回复的计数  
  68. 31:32:33:34:35:36:37:38 读出数据   
  69.   
  70. 注意,:冒号表示一个字节间的分割,但是TCP传输报文中,没有冒号的。  


 

拿到这些资料,首先面对的问题是WinCC中没有WinSock控件,网上找到了一篇《关于在WINCC中使用WinSock控件进行TCP_IP通讯的例程》的文档,介绍的比较详细。

 

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

1WinSock控件注册

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

注册方法如下:

使用记事本新建一个后缀名为bat的文件,编辑文件,加入以下文本:

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

保存文件退出。双击执行即可。(下载地址中提供了安装.bat文件,双击即可)

 

2、在WinCC中添加WinSock控件

在WinCC图形编辑器中打开需要显示服务器数据的画面,选择“对象选项板”的“控件”选项卡,在选项卡中选择“添加/删除”,在“选择OCX控件”对话框中选择“Microsoft WinSock Control, version 6.0”进行注册。

在对象选项板中的WinSock控件拖入画面中。

 

在实施到服务器上时,碰到了以下问题。

“未找到许可证信息(winsock)”

网上找到了一个神解决方案:

打开注册表,找‍到HKEY_CLASSES_‍ROOT下的Licenses,在他下面添加一个项,并且命名为2c49f800-c2dd-11cf-9ad6-0080c7e7b78d,然后修改这个项的默认值为:mlrljgrlhltlngjlthrligklpkrhllglqlrk,关闭注册表编辑器,再次启动WINCC即可。

 这不是WinCC的许可问题,而是WinSock的注册问题。

 

二、因为需要做数据转换,需导入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,然后单击 解压缩。
单击 确定,然后单击 关闭。
单击 开始,单击 运行,键入 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.     '这是一个转换DLL,后面还要讲到  
  16.     Set cnvt = CreateObject("ADS.ArrayConvert")  
  17.       
  18.     '以下是建立连接前的参数初始化工作,远程地址和端口号根据实际情况修改,此处设置是为了方便测试工作,可使用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.     '连接没有建立、连接错误、同级人员正在关闭连接,这三种情况下,先关闭连接,再尝试建立连接。  
  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.     '从接收缓冲区取得数据,并清空缓冲区  
  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  


  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多