我是靠谱客的博主 会撒娇宝马,最近开发中收集的这篇文章主要介绍在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个输入输出框。在按钮点击事件中创建以下代码:

#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++的,没怎么弄明白要怎么声明里面的函数,还有类的问题。代码如下:

/* 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的通讯方式。其报文格式如下:

报文格式请参看手册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 键。
单击 确定。


 

'-------------------------------------------------------------------------------
'    连接倍加福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


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通讯所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部