我是靠谱客的博主 会撒娇宝马,这篇文章主要介绍在WINCC中使用WinSock控件与倍加福RFID进行TCP_IP通讯,现在分享给大家,希望可以做个参考。

在柔性制造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
2
3
4
5
6
7
8
9
10
11
12
13
#include "apdefap.h" void OnLButtonDown(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nFlags, int x, int y) { #pragma code ("c:/DLL/T1_C.dll")  //指定绝对路径,网上有说放在WinCC/bin目录的,好像不靠谱还是这样好。 int aufruf1(int a);  //声明函数 #pragma code () int value; value = GetTagDouble("var1"); //Return-Type: double SetTagDouble("result",aufruf1(value)); //Return-Type: BOOL }

 

其中T1_C.dll里有一个返回参数+100的aufruf1函数。详见 http://www.cnblogs.com/ohiolee/articles/3498381.html

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

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


 

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
报文格式请参看手册26页,27页。报文格式是这样的 ***************************************************** CT格式 00:06:04:02:30:33 (6个字节的字符) 00:06 报文总长度 就是CT的命令格式,0x 10是读 就是 SR命令, 000610220000 通道1,0000 0010 红色标记的就是通道的编号 30:33 Tag type (IPC03) 发生命令以后,控制器会回复一个6个字节的确认短报文,一个6个或者6个字节以上的回复报文。 确认短报文: 00:06:04:02:FF:01 00:06报文总长度 重复一下命令(CT) 重复受到的命令 FF Status FFh (说明正在执行) 回复的计数器 到0xff以后会重新开始计数 回复报文 00:06:04:02:00:02 00:06报文总长度 04重复一下命令(CT) 02重复受到的命令 Status 0 (0表示命令成功完成,如果不是0,可以参考10 Troubleshooting 的10.1 Fault/Status messages P114. 有返回错误码的解释) 02回复的计数器 ***************************************************** 单次写SW 命令: 0A 40 12 00 01 39 38 37 36 0A报文总长度 40命令(SW) (0001 0010)红色表示写一个双字,也就是4个字节 01 表示起始地址是1.也就从地址0 偏移一个双字(4个字节) 38 37 36 表示写入的数值,这里就是ASCII :9876 SW的确认短报文 06 40 12 ff 67 SW的回复报文 06 40 02 00 68 ************************************************** 单次读SR 命令: 00:06:10:22:00:00 00:06 报文总长度 10命令(SR) (0010 0010)Word number (2) / Channel (1), toggle bit (0) 00:00 读起始地址(0000) 确认短报文 00:06:10:22:FF:01 00:06报文总长度 10重复一下命令(SR) (0010 0010)Word number (2) / Channel (1), toggle bit (0) FF Status FFh (processing command) 01回复的计数器 回复报文 00:0E:10:22:00:02:31:32:33:34:35:36:37:38 00:0E报文总长度(14 bytes) 10重复一下命令(SR) (0010 0010)Word number (2) / Channel (1), toggle bit (0) Status 0 (成功运行) 回复的计数 31:32:33:34:35:36:37:38 读出数据 注意,:冒号表示一个字节间的分割,但是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%system32MSWINSCK.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:ArrayConvertads.dll,然后按 ENTER 键。
单击 确定。


 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
'------------------------------------------------------------------------------- ' 连接倍加福RFID '------------------------------------------------------------------------------- Function RFID_Connect Dim Obj_SockClient Dim cnvt Dim Tag_intTXStatus Dim i,j Dim Tag_f,Tag_b ScreenItems("msg").Text = "Obj_SockClient init" & Chr(13) & Chr(10) & ScreenItems("msg").Text '获得当前窗口中的WinSock对象 Set Obj_SockClient = ScreenItems("objSock") '这是一个转换DLL,后面还要讲到 Set cnvt = CreateObject("ADS.ArrayConvert") '以下是建立连接前的参数初始化工作,远程地址和端口号根据实际情况修改,此处设置是为了方便测试工作,可使用TCP&UDP测试工具进行测试。 'Obj_SockClient.Protocol = "sckTCPProtocol" 'Obj_SockClient.RemoteHost = "192.168.1.222" 'Obj_SockClient.RemotePort = 10000 ScreenItems("msg").Text = "Obj_SockClient.Protocol=" & Obj_SockClient.Protocol & Chr(13) & Chr(10) & ScreenItems("msg").Text ScreenItems("msg").Text = "Obj_SockClient.RemoteHost=" & Obj_SockClient.RemoteHost & Chr(13) & Chr(10) & ScreenItems("msg").Text ScreenItems("msg").Text = "Obj_SockClient.RemotePort=" & Obj_SockClient.RemotePort & Chr(13) & Chr(10) & ScreenItems("msg").Text ScreenItems("msg").Text = "Obj_SockClient.State=" & Obj_SockClient.State & Chr(13) & Chr(10) & ScreenItems("msg").Text '连接没有建立、连接错误、同级人员正在关闭连接,这三种情况下,先关闭连接,再尝试建立连接。 If (Obj_SockClient.State = 0) Or (Obj_SockClient.State = 9) Or (Obj_SockClient.State = 8) Then Obj_SockClient.Close Obj_SockClient.Connect End If ScreenItems("msg").Text = "Obj_SockClient.Connect=" & Obj_SockClient.State & Chr(13) & Chr(10) & ScreenItems("msg").Text End Function


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Sub DataArrival(ByVal Item, ByVal bytesTotal) On Error Resume Next Dim cnvt Dim obj_OutText Dim strReceive Dim strFromRec Dim strTest Set cnvt = CreateObject("ADS.ArrayConvert") Set obj_OutText = ScreenItems("objOutText") ' MsgBox "DataArrival:bytesTotal=" & bytesTotal strFromRec = "" Set strReceive = Null '从接收缓冲区取得数据,并清空缓冲区 Item.GetData strReceive strFromRec = cnvt.CvOctetStr2vHexStr(strReceive) 'obj_OutText.Text = "strFromRec=" & strTest & Chr(13) & Chr(10) & obj_OutText.Text If Len(strFromRec) > 0 Then getDataArrival(strFromRec) End If End Sub


 

最后

以上就是会撒娇宝马最近收集整理的关于在WINCC中使用WinSock控件与倍加福RFID进行TCP_IP通讯的全部内容,更多相关在WINCC中使用WinSock控件与倍加福RFID进行TCP_IP通讯内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(72)

评论列表共有 0 条评论

立即
投稿
返回
顶部