Obj_SockClient.SendData cnvt.CvHexStr2vOctetStr(\ End If ?写入当前连接状态字 Set Tag_intTXStatus = HMIRuntime.Tags(\ Tag_intTXStatus.Value = Obj_SockClient.State Tag_intTXStatus.Write , 1 End Function
六、接收数据包的处理
当建立连接后,接受到了新数据就会触发这个DataArrival事件。这里只对前64个模拟量数据、16个开关量输入数据、10条汉字报警信息进行解析,并将解析后的数据赋值给相应的变量,汉字报警信息直接在窗口中的S7FlatEditBox控件中显示。
DataArrival事件的VBS代码如下:
Sub DataArrival(Byval Item, Byval bytesTotal) On Error Resume Next Dim Obj_SockClient Dim cnvt Dim obj_OutText Dim strReceive Dim strFromRec,strFromRec1 Dim i,j Dim Tag_f,Tag_b Dim strForBool,iForBoolCheck Set Obj_SockClient = ScreenItems(\Set cnvt = CreateObject(\Set obj_OutText = ScreenItems(\ ?接收数据包字节数应为650字节,否则不处理 If bytesTotal = 650 Then ?从接收缓冲区取得数据,并清空缓冲区 Item.GetData strReceive strFromRec = \'提取前333个字节所包含的信息,用于模拟量和开关量解析 For i = 0 To 333 'UBound(strReceive) ?将接收到的BYTE()型数据转换为String型数据
strFromRec = strFromRec & Right(\10
Next '解析出80个模拟量并赋值给相应的变量 For i = 1 To 8 For j = 1 To 8 Set Tag_f = HMIRuntime.Tags(\?此处使用了DLL中的数据转换函数,CvHexStr2vReal2的功能是将十六进制字符串表示的单精度浮点数转换成实际的浮点数值。该函数后面还要讲到。 Tag_f.Value = cnvt.CvHexStr2vReal2(Mid(strFromRec,((i-1)*8+j-1)*8+1,8)) Tag_f.Write,1 Next Next '解析开关量输入字节(2字节),并赋值给相应的变量 iForBoolCheck = 0 strForBool = Mid(strFromRec,643,2) & Mid(strFromRec,641,2) iForBoolCheck = Eval(\For i = 1 To 15 Set Tag_b = HMIRuntime.Tags(\ If (iForBoolCheck And 2^(i-1) ) = 0 Then Tag_b.Value = False Else Tag_b.Value = True End If Tag_b.Write ,1 Next End If '解析汉字报警信息10条(每条信息包含15个汉字) For i = 0 To 9 For j =0 To 14 ?提取汉字信息,并转换成Unicode字符串。 strFromRec1 = strFromRec1 & MidB(strReceive,i*30+j*2+335,2) Next strFromRec1 = strFromRec1 & vbCrLf Next obj_OutText.Text = strFromRec1 End Sub 11
附:在VBS中进行数据处理的局限性及变通解决方法
在VBS中对数据进行转换解析处理,是一个比较普遍的应用问题,并不仅限于在WINCC中的应用,而VBS在进行数据处理时的局限,也使得单靠VBS自身无法圆满的处理,需要借助其它手段,而VBS结合外部动态链接库是一个合理的解决方案。
VBS(Microsoft Visual Basic Scripting Edition)是一种脚本语言。可以看作是VB语言的简化版,可使用操作系统和其它程序所提供的程序库,由操作系统解释运行。WINCC V6.0首次集成了VBS,可以用来使运行环境动态化,也可以创建动作(action)和过程(procedure)来动态化图形对象。
注:脚本语言是使用一种特定的描述性语言,依据一定的格式编写的可执行文件,又称作宏或批处理文件,是为了缩短传统的编写-编译-链接-运行(edit-compile-link-run)过程而创建的计算机编程语言。一个脚本通常是解释运行而非编译,脚本程序在执行时,是由系统的一个解释器,将其一条条的翻译成机器可识别的指令,并按程序顺序执行。 VBS只有一种数据类型,即Variant(可变的)。VBS在处理数据时,按上下文对其处理的方式,把数据当作数字或字符串进行处理,也就是VBS觉得它像什么,就把它当作什么来进行处理。Variant包含的数值信息类型称为子类型,大多数情况下,可将所需的数据放进Variant中,而Variant也会按照最适用于其包含的数据的方式进行操作。
VBS这种处理数据的方法,有其优点和局限性。优点在于简单方便,局限性在于降低了可控性,特别是在处理低层数据代码时,难度较高,而有些要求没有办法达到。
比如在WINCC中使用MSCOMM控件进行数据收发时,MSCOMM控件处理的是BYTE()类型数据,在VBS中会将它作为VARIANT()类型数据进行处理,而这种数据类型无法通过串口发送出去,而在VBS中没有相应的函数将其转换成BYTE()类型数据。又比如在VBS中要将一个如“4199999A”的字符串转换成单精度浮点数据,会非常困难,则类似的转换在C或VB这类高级语言中却很容易。
在进行上述数据处理任务时,结合动态链接库是比较合理的方法。下面详细讲述一般需要用到的数据转换如何通过VB编写DLL来实现。
在切换到VB中进行编程之前,先了解熟悉VBS中的有关数据类型的处理。 1、在VBS中如何定义变量
在VBS中定义变量,只能使用一种定义方式,即Dim语句,变量类型只有一种,即VARIANT,而不是象在VB中可以显示定义变量为不同的数据类型,如String,Interger,Long等。
测试下列一段代码:
12
Dim A , B , C A = Array(10,20,30) B = Array(\ C = Array(CByte(A(0)),CByte(A(1)),CByte(A(2))) Msgbox typename(A) ?显示数据类型为Variant() Msgbox typename(A(0)) ?显示数据类型为Interger Msgbox typename(B) Msgbox typename(B(0)) Msgbox typename(C) Msgbox typename(C(0)) ?显示数据类型为Variant () ?显示数据类型为String ?显示数据类型为Variant () ?显示数据类型为Byte 测试结果显示,对于单个变量,虽然不能象在VB中显示定义其数据类型,但VBS可以大致判断其数据类型,也可以将数据通过强制转换成所需要的数据类型。但不管如何定义或转换,仅通过VBS中的定义方式和转换函数,无法改变数组的类型,最终结果只有一种数组类型,即Varaint()。
2、VBS中的字符编码
在VBS中,字符串以Unicode编码表示,编码的实现方案是UTF-16 LE。当VBS调用低层API函数(VBS不能直接调用,而是通过控件或DLL间接调用)时,大都会由系统自动将Unicode字符串转换成ANSI编码字符串。如通过Winsock控件发送字符串,在接收端接收到的字符串实际上是ANSI字符串。
在简体中文WinXP操作系统下,默认的ANSI编码是GBK字符集。
3、VBS的字符转换函数
Chr函数返回与指定的 ANSI 字符代码相对应的字符。
调用格式:Chr(charcode) charcode 参数是可以标识字符的数字。
说明:从0到31的数字表示标准的不可打印的 ASCII 代码。例如,Chr(10) 返回换行符。
注意:ChrB 函数与包含在字符串中的字节数据一起使用。ChrB 不是返回一个或两个字节的字符,而总是返回单个字节的字符。ChrW 是为使用 Unicode 字符的 32 位平台提供的。它的参数是一个 Unicode (宽字符)的字符代码,因此可以避免将 ANSI 转化为 Unicode 字符。 Asc 函数返回与字符串的第一个字母对应的 ANSI 字符代码。
Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,
13
则将发生运行时错误。
注意:AscB 函数和包含字节数据的字符串一起使用。 AscB 不是返回第一个字符的字符代码,而是返回首字节。 AscW 是为使用 Unicode 字符的 32 位平台提供的。 它返回 Unicode (宽型)字符代码,因此可以避免从 ANSI 到 Unicode 的代码转换。 总结如下:
chrb/ascb用来做ASCII转换,但并不仅包括前128个字符,而是全单字节字符,所以应该是用来做单字节字符的转换。
chr/asc用来做ANSI转换,在当前中文简体WINDOWS系统中,即对应于GBK字符集的转换。在WinXP中文版下的VB6.0中,Chr能够正确转换遇0~128和255的单字节字符码和GBK字符集中的双字节字符码,超出此范围的字符码或解释成NUL字符,或是其它未料结果。
chrw/ascw用来做Unicode转换。
4、在VBS中调用MSCOMM和WINSOCK的注意事项
在VBS中可以调用MSCOMM和WINSOCK通讯控件,以完成串口通讯和以太网通讯。通讯控件可以以字符串或字节数组方式进行数据发送或接收,但由于字节数组在VBS中不能显示定义,一个自然而然的想法是通过字符串方式进行数据发送或接收。
如果发送的数据范围在0x00~0x7F之间,可以通过Chr函数将十六进制数据转换成相应的ASCII码字符,并且组合成字符串数据流,由于在此数据范围内的字符码可各系统平台和软件环境中均可以得到唯一正确的解析,所以这个方法是可行的。
但如果发生冲突的数据超出此范围,再想通过Chr函数(或者ChrB/ChrW函数)将十六进制数据转换成字符,转换结果将不是我们所预期的结果,这与软件平台和操作系统平台有关,其中一些字符码被解释成空字符,或者是”?”,还有一些被解释成不同字符集下对应的不同的字符。所以在VBS中调用通讯控件进行数据发送或接收,使用字符串方式不是合理的方案。
在了解了VBS中进行数据处理的局限后,自然而然我们想到需要用其它的方法来解决这些问题,可行的方法是通过DLL外部调用。因为VB简单实用,在实际应用中,一些在VBS中不能处理或难以处理的任务,可以在VB中进行简单的处理,用VB来创建编译DLL容易掌握,将这些功能编译进DLL中,可以由VBS调用处理。
14