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

分享

在WINCC中使用WinSock控件進(jìn)行TCP/IP通訊的例程

 阿毅s6kc8rp1nf 2017-10-13

 

WINCC中使用WinSock控件進(jìn)行TCP/IP通訊的例程

 

目錄

一、WinSock控件介紹(以VB語(yǔ)言表述)... 1

1、WinSock控件的主要屬性... 1

2、WinSock控件的主要方法... 2

3、WinSock控件的主要事件... 3

二、WinSock控件在WINCC中的使用... 3

1、WinSock控件注冊(cè)... 3

2、在WinCC中添加WinSock控件... 4

三、服務(wù)器端程序介紹... 4

四、WinCC畫(huà)面模板與結(jié)構(gòu)變量的配合使用... 6

1、結(jié)構(gòu)變量定義... 6

2、畫(huà)面模板組態(tài)... 7

3、調(diào)用畫(huà)面模板及修改變量前綴... 7

4、將畫(huà)面模板中的對(duì)象連接到變量... 8

五、建立TCP/IP連接... 8

六、接收數(shù)據(jù)包的處理... 10

附:在VBS中進(jìn)行數(shù)據(jù)處理的局限性及變通解決方法... 12


摘要:

關(guān)鍵詞:VB、VBS、WINCC、WINSOCK、DLL、UNICODE、ANSI、ASCII、畫(huà)面模板、結(jié)構(gòu)變量、數(shù)據(jù)轉(zhuǎn)換。

 

該文檔的軟件環(huán)境:

Microsoft Windows XP Professional 版本2002 SP3

SIMATIC WinCC V6.2 SP2 ASIA

‘SIMATIC STEP7 V5.4+SP5+HF3 Chinese

TCP&UDP測(cè)試工具 V1.02

 

目的:

使用WINCC用戶(hù)程序作為客戶(hù)端程序,與服務(wù)器通訊,通訊協(xié)議為標(biāo)準(zhǔn)TCP/IP協(xié)議,取得服務(wù)器發(fā)送過(guò)來(lái)的數(shù)據(jù)包,按數(shù)據(jù)包格式文本規(guī)定,解析數(shù)據(jù)包數(shù)據(jù),并將相關(guān)數(shù)據(jù)顯示在用戶(hù)程序畫(huà)面中。

 

一、WinSock控件介紹(以VB語(yǔ)言表述)

1、WinSock控件的主要屬性

1) Protocol屬性

通過(guò)Protocol屬性可以設(shè)置WinSock控件連接遠(yuǎn)程計(jì)算機(jī)使用的協(xié)議??蛇x的協(xié)議是TCP和UDP對(duì)應(yīng)的VB的常量分別是sckTCPProtocol和sckUDPProtocol,Winsock控件默認(rèn)協(xié)議是TCP。

注意:雖然可以在運(yùn)行時(shí)設(shè)置協(xié)議,但必須在連接未建立或斷開(kāi)連接后。

2) SocketHandle屬性

SocketHandle返回當(dāng)前socket連接的句柄,這是只讀屬性。

3) RemoteHostIP屬性

RemoteHostIP屬性返回遠(yuǎn)程計(jì)算機(jī)的IP地址。在客戶(hù)端,當(dāng)使用了控件的Connect方法后,遠(yuǎn)程計(jì)算機(jī)的IP地址就賦給了RemoteHostIP屬性,而在服務(wù)器端,當(dāng)ConnectRequest事件后,遠(yuǎn)程計(jì)算機(jī)(客戶(hù)端)的IP地址就賦給了這個(gè)屬性。如果使用的是UDP協(xié)議那么當(dāng)DataArrival事件后,發(fā)送UDP報(bào)文的計(jì)算機(jī)的IP才賦給了這個(gè)屬性。

4) ByteReceived屬性

返回當(dāng)前接收緩沖區(qū)中的字節(jié)數(shù)

5) State屬性

返回WinSock控件當(dāng)前的狀態(tài)

常數(shù)

描述

sckClosed

0

缺省值,關(guān)閉

SckOpen

1

打開(kāi)

SckListening

2

偵聽(tīng)

sckConnectionPending

3

連接掛起

sckResolvingHost

4

識(shí)別主機(jī)

sckHostResolved

5

已識(shí)別主機(jī)

sckConnecting

6

正在連接

sckConnected

7

已連接

sckClosing

8

同級(jí)人員正在關(guān)閉連接

sckError

9

錯(cuò)誤

 

2、WinSock控件的主要方法

1) Bind方法

用Bind方法可以把一個(gè)端口號(hào)固定為本控件使用,使得別的應(yīng)用程序不能再使用這個(gè)端口。

2) Listen方法

Listen方法只在使用TCP協(xié)議時(shí)有用。它將應(yīng)用程序置于監(jiān)聽(tīng)檢測(cè)狀態(tài)。

3) Connect方法

當(dāng)本地計(jì)算機(jī)希望和遠(yuǎn)程計(jì)算機(jī)建立連接時(shí),就可以調(diào)用Connect方法。

Connect方法調(diào)用的規(guī)范為:

Connect RemoteHost,RemotePort

4) Accept方法

當(dāng)服務(wù)器接收到客戶(hù)端的連接請(qǐng)求后,服務(wù)器有權(quán)決定是否接受客戶(hù)端的請(qǐng)求。

5) SendData方法

當(dāng)連接建立后,要發(fā)送數(shù)據(jù)就可以調(diào)用SendData方法,該方法只有一個(gè)參數(shù),就是要發(fā)送的數(shù)據(jù)。

6) GetData方法

當(dāng)本地計(jì)算機(jī)接收到遠(yuǎn)程計(jì)算機(jī)的數(shù)據(jù)時(shí),數(shù)據(jù)存放在緩沖區(qū)中,要從緩沖區(qū)中取出數(shù)據(jù),可以使用GetData方法。GetData方法調(diào)用規(guī)范如下:

GetData data,[type,][maxLen]

它從緩沖區(qū)中取得最長(zhǎng)為maxLen的數(shù)據(jù),并以type類(lèi)型存放在data中,GetData取得數(shù)據(jù)后,就把相應(yīng)的緩沖區(qū)清空。

7) PeekData方法

和GetData方法類(lèi)似,但PeekData在取得數(shù)據(jù)后并不把緩沖區(qū)清空。

 

3、WinSock控件的主要事件

1) ConnectRequest事件

當(dāng)本地計(jì)算機(jī)接收到遠(yuǎn)程計(jì)算機(jī)發(fā)送的連接請(qǐng)求時(shí),控件的ConnectRequest事件將會(huì)被觸發(fā)。

2) SendProgress事件

當(dāng)一端的計(jì)算機(jī)正在向另一端的計(jì)算機(jī)發(fā)送數(shù)據(jù)時(shí),SendProgress事件將被觸發(fā)。SendProgress事件記錄了當(dāng)前狀態(tài)下已發(fā)送的字節(jié)數(shù)和剩余字節(jié)數(shù)。

3) SendComplete事件

當(dāng)所有數(shù)據(jù)發(fā)送完成時(shí),被觸發(fā)。

4) DataArrival事件

當(dāng)建立連接后,接受到了新數(shù)據(jù)就會(huì)觸發(fā)這個(gè)事件。

注意:如果在接受到新數(shù)據(jù)前,緩沖區(qū)中非空,就不會(huì)觸發(fā)這個(gè)事件。

5) Error事件

當(dāng)在工作中發(fā)生任何錯(cuò)誤都會(huì)觸發(fā)這個(gè)事件。

 

二、WinSock控件在WINCC中的使用

1、WinSock控件注冊(cè)

在WinCC中使用WinSock控件前,需要先進(jìn)行注冊(cè)。

注冊(cè)方法如下:

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

[HKEY_CLASSES_ROOT\Licenses\2c49f800-c2dd-11cf-9ad6-0080c7e7b78d]

@="mlrljgrlhltlngjlthrligklpkrhllglqlrk"

保存文件退出。

先將mswinsck.ocx拷貝到system32下

再將注冊(cè)表文件添加到注冊(cè)表

然后"運(yùn)行",輸入"regsvr32 MSWINSCK.OCX",確定。

 

2、在WinCC中添加WinSock控件

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

在對(duì)象選項(xiàng)板中的WinSock控件拖入畫(huà)面中。

 

三、服務(wù)器端程序介紹

這里所要通訊的服務(wù)器端程序是運(yùn)行于南車(chē)資陽(yáng)機(jī)車(chē)有限公司生產(chǎn)的V280/285系列船用柴油機(jī)機(jī)旁控制屏監(jiān)控系統(tǒng)程序。

以下是協(xié)議文本:

通訊方式:TCP/IP

偵聽(tīng)端口:9105

機(jī)旁柜IP地址定義:由用戶(hù)根據(jù)具體網(wǎng)絡(luò)配置決定

PAC數(shù)據(jù)采集周期:1秒

上位機(jī)記取數(shù)據(jù)周期:1秒

數(shù)據(jù)包格式定義如下:

上位機(jī)發(fā)送命令到PAC的數(shù)據(jù)包定義:本數(shù)據(jù)包由上位機(jī)發(fā)送到PAC,PAC根據(jù)上位機(jī)發(fā)送的的命令執(zhí)行,同時(shí)返回最新的采集數(shù)據(jù)到上位機(jī)。

數(shù)據(jù)長(zhǎng)度:10字節(jié)。

數(shù)據(jù)類(lèi)型:byte。

數(shù)據(jù)包詳細(xì)定義:命令代碼1字節(jié)+備用代碼1字節(jié)+設(shè)定轉(zhuǎn)速4字節(jié)(single)+備用1字節(jié)

其中命令代碼意義:1=“讀數(shù)據(jù)”;18=“轉(zhuǎn)速升”;19=“轉(zhuǎn)速降”。

PAC發(fā)送到上位機(jī)的數(shù)據(jù)包定義:

數(shù)據(jù)長(zhǎng)度:650個(gè)字節(jié)。

數(shù)據(jù)類(lèi)型:BYTE。

數(shù)據(jù)包內(nèi)容詳細(xì)定義及代碼示意如下:

 

起始傳80個(gè)浮點(diǎn)數(shù),每個(gè)浮點(diǎn)數(shù)占用四個(gè)字節(jié),高位在后,低位在前。

00000000h: 33 33 E7 41 00 00 E8 41 66 66 EA 41 66 66 EA 41 ; 

00000010h: 33 33 EB 41 66 66 E6 41 00 00 E4 41 CD CC E0 41 ;

00000020h: 66 66 DA 41 00 00 DC 41 00 00 DC 41 00 00 DC 41 ;

00000030h: 66 66 DA 41 CD CC D4 41 CD CC D4 41 00 00 D0 41 ;

00000040h: 00 00 DC 41 00 00 DC 41 33 33 DB 41 CD CC D8 41 ;

00000050h: 9A 3F 1C 46 9A 3F 1C 46 9A 3F 1C 46 9A 3F 1C 46 ;

00000060h: 65 66 89 41 32 B3 95 41 CE CC 94 41 CC 2C 95 41 ;

00000070h: CD 2C 8C 41 33 93 91 41 01 E0 91 41 99 19 92 41 ;

00000080h: 01 C0 8F 41 01 00 8E 41 9A 59 94 41 00 00 00 00 ;

00000090h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

000000a0h: FC FF 0A 42 F6 FF FB 41 9A 3F 1C C6 9A 3F 1C C6 ;

000000b0h: 9A 3F 1C C6 9A 3F 1C C6 9A 3F 1C C6 A3 FF 89 40 ;

000000c0h: 9A 3F 1C C6 9A 3F 1C C6 9A 3F 1C C6 0F 00 B5 41 ;

000000d0h: 74 FF EF 3F 9A 3F 1C C6 66 66 B8 40 9A 99 FD 41 ;

000000e0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

000000f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000100h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000110h: 8F C2 04 42 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000120h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000130h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;.

續(xù):

PAC第一組IO輸入點(diǎn),2字節(jié);PAC第二組IO輸入點(diǎn),2字節(jié);PAC第一組IO輸出點(diǎn),1字節(jié);PAC第二組IO輸出點(diǎn),1字節(jié);PAC運(yùn)行狀態(tài),1字節(jié);PAC當(dāng)前執(zhí)行的命令,1字節(jié);備用,1字節(jié);當(dāng)前設(shè)定轉(zhuǎn)速,4字節(jié);報(bào)警數(shù)目,1字節(jié);報(bào)警信息,300字節(jié);備用,16字節(jié)。

00000140h: 05 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 ;.

00000150h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;.

00000160h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000170h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000180h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000190h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

000001a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

000001b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

000001c0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

000001d0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

000001e0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

000001f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000200h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;.

00000210h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000220h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000230h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000240h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000250h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000260h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000270h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ;

00000280h: 00 00 00 00 00 00 00 00 00 00            

 

四、WinCC畫(huà)面模板與結(jié)構(gòu)變量的配合使用

本用戶(hù)程序需要實(shí)時(shí)采集顯示三臺(tái)同類(lèi)型柴油機(jī)的運(yùn)行數(shù)據(jù),由于三臺(tái)柴油機(jī)的數(shù)據(jù)采集和顯示是相同的,而WinCC畫(huà)面模板與結(jié)構(gòu)變量配合使用可以在一個(gè)畫(huà)面中根據(jù)條件顯示具有相同類(lèi)型參數(shù)的多個(gè)對(duì)象,避免反復(fù)組態(tài)相同畫(huà)面布局的工作,減少項(xiàng)目后期某些細(xì)節(jié)部位的修改而帶來(lái)的工作量,所以本用戶(hù)程序采用畫(huà)面模板與結(jié)構(gòu)變量配合使用方法進(jìn)行組態(tài)設(shè)計(jì)。

《WinCC中的畫(huà)面模板》一文提出四種使用畫(huà)面模板的方法,這里采用第三種方法,即“使用變量前綴的畫(huà)面窗口”。

組態(tài)步驟如下所示:

1、結(jié)構(gòu)變量定義

在WinCC中定義一個(gè)結(jié)構(gòu)變量,結(jié)構(gòu)變量名稱(chēng)為sDieselData。結(jié)構(gòu)變量包括64個(gè)FLOAT型變量(數(shù)據(jù)包上傳80個(gè)模擬量,但實(shí)際使用只有小于64個(gè),出于編程方便起見(jiàn),使用8*8=64個(gè)單精度浮點(diǎn)變量),16個(gè)BIT型變量(只使用PAC的輸入點(diǎn)、其它開(kāi)關(guān)量不使用),1個(gè)SHORT變量(反映通訊狀態(tài))。

64個(gè)單精度浮點(diǎn)型變量的命名格式為:

fTag11、fTag12……fTag18

fTag21、fTag22……fTag28

………………………………

fTag81、fTag82……fTag88

16個(gè)BIT型變量命名格式為biTag1、biTag2……biTag16。

1個(gè)SHORT型變量名稱(chēng)為T(mén)XStatus。

結(jié)構(gòu)變量定義完成后,根據(jù)結(jié)構(gòu)變量定義三個(gè)內(nèi)部結(jié)構(gòu)變量,分別命名為“CNB”、“YYB”、“SXB”。

 

2、畫(huà)面模板組態(tài)

新建一個(gè)畫(huà)面,畫(huà)面名稱(chēng)為pDieselMod.pdl,并在畫(huà)面中加入一個(gè)WinSock控件、一些文字和輸入/輸入域,以及其它有些相關(guān)控件。如下圖如示:

 

 

3、調(diào)用畫(huà)面模板及修改變量前綴

新建的畫(huà)面模板需要在主畫(huà)面的一個(gè)子畫(huà)面窗口中顯示。主畫(huà)面文件名稱(chēng)為“pMain.pdl”,子畫(huà)面窗口名稱(chēng)為“pMainArea”。在用戶(hù)程序運(yùn)行時(shí),有一個(gè)界面中顯示了三臺(tái)柴油機(jī)的圖標(biāo),點(diǎn)擊某一個(gè)柴油機(jī)圖標(biāo),子畫(huà)面切換到相應(yīng)的柴油機(jī)狀態(tài)及參數(shù)界面。

圖標(biāo)的鼠標(biāo)動(dòng)作C代碼如下:

#include "apdefap.h"

void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName)

{

#pragma option(mbcs)

#define PIC_0 "pMain"

#define PIC_1 "pDieselMod.PDL"

 

SetPropChar(PIC_0,"pMainArea","TagPrefix","CNB.");  ‘此處”CNB.”在其余兩處為”YYB.”、”SXB.”

SetPictureName(PIC_0,"pMainArea",PIC_1);

}

上面代碼中關(guān)健代碼就是:SetPropChar(PIC_0,"pMainArea","TagPrefix","CNB.")。該行語(yǔ)句設(shè)置了子窗口pMainArea的變量前綴為”CNB.”。當(dāng)子窗口設(shè)置了變量前綴后,畫(huà)面窗口中的對(duì)象連接變量時(shí),變量一般會(huì)自動(dòng)加上前綴(連接包括動(dòng)態(tài)對(duì)話框、變量、C腳本及VBS腳本)。

注意:在設(shè)置了子窗口的變量前綴后,如果要切換顯示不帶變量前綴的畫(huà)面,則需設(shè)置子窗口的變量前綴為空。例外OpenPrevPicture()函數(shù)不受影響。

 

4、將畫(huà)面模板中的對(duì)象連接到變量

將畫(huà)面模板中的對(duì)象連接到相應(yīng)的變量,組態(tài)方法與常規(guī)組態(tài)相似,不同之處在于變更量名稱(chēng)需要去掉前綴,在腳本中所使用的變量同樣不要帶變量前綴,因?yàn)樽兞壳熬Y會(huì)自動(dòng)加上。在組態(tài)時(shí)會(huì)提示變量不存在,忽略即可。

 

五、建立TCP/IP連接

要求是在柴油機(jī)狀態(tài)及參數(shù)畫(huà)面顯示時(shí)自動(dòng)建立TCP/IP連接,如果連接沒(méi)有建立,則將相應(yīng)的結(jié)構(gòu)變量清零,并且每隔兩秒重建連接。

連接建立后,發(fā)送讀數(shù)據(jù)命令數(shù)據(jù)包。

在畫(huà)面對(duì)象屬性的“顯示”屬性中加入如下VBS代碼(觸發(fā)器選擇2s周期):

Function Visible_Trigger(Byval Item)

Dim Obj_SockClient

Dim cnvt

Dim obj_Screen

Dim obj_pScreen

Dim Tag_intTXStatus

Dim i,j

Dim Tag_f,Tag_b

 

‘獲得當(dāng)前窗口中的WinSock對(duì)象

Set Obj_SockClient = ScreenItems("objSock")

‘獲得顯示當(dāng)前畫(huà)面的子窗口對(duì)象

Set obj_Screen = HMIRuntime.Screens("pMain").ScreenItems("pMainArea")

‘這是一個(gè)轉(zhuǎn)換DLL,后面還要講到

Set cnvt = CreateObject("ADS.ArrayConvert")

 

‘以下是建立連接前的參數(shù)初始化工作,遠(yuǎn)程地址和端口號(hào)根據(jù)實(shí)際情況修改,此處設(shè)置是為了方便測(cè)試工作,可使用TCP&UDP測(cè)試工具進(jìn)行測(cè)試。

Obj_SockClient.Protocol = "sckTCPProtocol"

Select Case obj_Screen.TagPrefix

     Case "CNB."

            Obj_SockClient.RemoteHost = "192.168.1.100"

            Obj_SockClient.RemotePort = 4002

     Case "YYB."

            Obj_SockClient.RemoteHost = "192.168.1.100"

            Obj_SockClient.RemotePort = 4003

     Case "SXB."

            Obj_SockClient.RemoteHost = "192.168.1.100"

            Obj_SockClient.RemotePort = 4004

     Case Else

            Exit Function

End Select

 

‘連接沒(méi)有建立、連接錯(cuò)誤、同級(jí)人員正在關(guān)閉連接,這三種情況下,先關(guān)閉連接,再?lài)L試建立連接。

If (Obj_SockClient.State = 0) Or (Obj_SockClient.State = 9) Or (Obj_SockClient.State = 8) Then

    Obj_SockClient.Close

   Obj_SockClient.Connect

 End If

 

‘如果連接沒(méi)有建立,則使相應(yīng)的FLOAT型結(jié)構(gòu)變量清零。

 If Obj_SockClient.State <> 7 Then

    For i = 1 To 8

            For j = 1 To 8

                   Set Tag_f = HMIRuntime.Tags("fTag" & i & j)

                   Tag_f.Value = 0

                   Tag_f.Write,1

            Next

     Next

 

‘如果連接沒(méi)有建立,則使相應(yīng)的BIT型結(jié)構(gòu)變量復(fù)位。

     For i = 1 To 15

            Set Tag_b = HMIRuntime.Tags("biTag" & i)

            Tag_b.Value = False

            Tag_b.Write ,1

     Next

 Else

‘如果連接建立,則發(fā)送訊數(shù)據(jù)命令數(shù)據(jù)包

     Obj_SockClient.SendData cnvt.CvHexStr2vOctetStr("01000000000000000000")

 End If

 

‘寫(xiě)入當(dāng)前連接狀態(tài)字

 Set Tag_intTXStatus = HMIRuntime.Tags("TXStatus")

 Tag_intTXStatus.Value = Obj_SockClient.State

 Tag_intTXStatus.Write , 1

 

End Function

 

六、接收數(shù)據(jù)包的處理

當(dāng)建立連接后,接受到了新數(shù)據(jù)就會(huì)觸發(fā)這個(gè)DataArrival事件。這里只對(duì)前64個(gè)模擬量數(shù)據(jù)、16個(gè)開(kāi)關(guān)量輸入數(shù)據(jù)、10條漢字報(bào)警信息進(jìn)行解析,并將解析后的數(shù)據(jù)賦值給相應(yīng)的變量,漢字報(bào)警信息直接在窗口中的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("objSock")

Set cnvt = CreateObject("ADs.ArrayConvert")

Set obj_OutText = ScreenItems("objOutText")

 

‘接收數(shù)據(jù)包字節(jié)數(shù)應(yīng)為650字節(jié),否則不處理

If bytesTotal = 650 Then

 

‘從接收緩沖區(qū)取得數(shù)據(jù),并清空緩沖區(qū)

Item.GetData strReceive

strFromRec = ""

'提取前333個(gè)字節(jié)所包含的信息,用于模擬量和開(kāi)關(guān)量解析

For i = 0 To 333 'UBound(strReceive)

     ‘將接收到的BYTE()型數(shù)據(jù)轉(zhuǎn)換為String型數(shù)據(jù)

     strFromRec = strFromRec & Right("0" & Hex(Ascb(Midb(strReceive , i + 1 ,1))) , 2 )

Next

 

'解析出80個(gè)模擬量并賦值給相應(yīng)的變量

For i = 1 To 8

     For j = 1 To 8

            Set Tag_f = HMIRuntime.Tags("fTag" & i & j)

            ‘此處使用了DLL中的數(shù)據(jù)轉(zhuǎn)換函數(shù),CvHexStr2vReal2的功能是將十六進(jìn)制字符串表示的單精度浮點(diǎn)數(shù)轉(zhuǎn)換成實(shí)際的浮點(diǎn)數(shù)值。該函數(shù)后面還要講到。

            Tag_f.Value = cnvt.CvHexStr2vReal2(Mid(strFromRec,((i-1)*8+j-1)*8+1,8))

            Tag_f.Write,1

     Next

Next

 

'解析開(kāi)關(guān)量輸入字節(jié)(2字節(jié)),并賦值給相應(yīng)的變量

iForBoolCheck = 0

strForBool = Mid(strFromRec,643,2) & Mid(strFromRec,641,2)

iForBoolCheck = eval_r("&H" & strForBool)

For i = 1 To 15

     Set Tag_b = HMIRuntime.Tags("biTag" & i)

     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

 

'解析漢字報(bào)警信息10條(每條信息包含15個(gè)漢字)

For i = 0 To 9

     For j =0 To 14

‘提取漢字信息,并轉(zhuǎn)換成Unicode字符串。

            strFromRec1 = strFromRec1 & MidB(strReceive,i*30+j*2+335,2)

     Next

     strFromRec1 = strFromRec1 & vbCrLf

Next

obj_OutText.Text = strFromRec1

    

End Sub


附:在VBS中進(jìn)行數(shù)據(jù)處理的局限性及變通解決方法

在VBS中對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換解析處理,是一個(gè)比較普遍的應(yīng)用問(wèn)題,并不僅限于在WINCC中的應(yīng)用,而VBS在進(jìn)行數(shù)據(jù)處理時(shí)的局限,也使得單靠VBS自身無(wú)法圓滿的處理,需要借助其它手段,而VBS結(jié)合外部動(dòng)態(tài)鏈接庫(kù)是一個(gè)合理的解決方案。

VBS(Microsoft Visual Basic Scripting Edition)是一種腳本語(yǔ)言??梢钥醋魇?a title="VB" href="http://zh./zh-cn/VB">VB語(yǔ)言的簡(jiǎn)化版,可使用操作系統(tǒng)和其它程序所提供的程序庫(kù),由操作系統(tǒng)解釋運(yùn)行。WINCC V6.0首次集成了VBS,可以用來(lái)使運(yùn)行環(huán)境動(dòng)態(tài)化,也可以創(chuàng)建動(dòng)作(action)和過(guò)程(procedure)來(lái)動(dòng)態(tài)化圖形對(duì)象。

注:腳本語(yǔ)言是使用一種特定的描述性語(yǔ)言,依據(jù)一定的格式編寫(xiě)的可執(zhí)行文件,又稱(chēng)作宏或批處理文件,是為了縮短傳統(tǒng)的編寫(xiě)-編譯-鏈接-運(yùn)行(edit-compile-link-run)過(guò)程而創(chuàng)建的計(jì)算機(jī)編程語(yǔ)言。一個(gè)腳本通常是解釋運(yùn)行而非編譯,腳本程序在執(zhí)行時(shí),是由系統(tǒng)的一個(gè)解釋器,將其一條條的翻譯成機(jī)器可識(shí)別的指令,并按程序順序執(zhí)行。

VBS只有一種數(shù)據(jù)類(lèi)型,即Variant(可變的)。VBS在處理數(shù)據(jù)時(shí),按上下文對(duì)其處理的方式,把數(shù)據(jù)當(dāng)作數(shù)字或字符串進(jìn)行處理,也就是VBS覺(jué)得它像什么,就把它當(dāng)作什么來(lái)進(jìn)行處理。Variant包含的數(shù)值信息類(lèi)型稱(chēng)為子類(lèi)型,大多數(shù)情況下,可將所需的數(shù)據(jù)放進(jìn)Variant中,而Variant也會(huì)按照最適用于其包含的數(shù)據(jù)的方式進(jìn)行操作。

VBS這種處理數(shù)據(jù)的方法,有其優(yōu)點(diǎn)和局限性。優(yōu)點(diǎn)在于簡(jiǎn)單方便,局限性在于降低了可控性,特別是在處理低層數(shù)據(jù)代碼時(shí),難度較高,而有些要求沒(méi)有辦法達(dá)到。

比如在WINCC中使用MSCOMM控件進(jìn)行數(shù)據(jù)收發(fā)時(shí),MSCOMM控件處理的是BYTE()類(lèi)型數(shù)據(jù),在VBS中會(huì)將它作為VARIANT()類(lèi)型數(shù)據(jù)進(jìn)行處理,而這種數(shù)據(jù)類(lèi)型無(wú)法通過(guò)串口發(fā)送出去,而在VBS中沒(méi)有相應(yīng)的函數(shù)將其轉(zhuǎn)換成BYTE()類(lèi)型數(shù)據(jù)。又比如在VBS中要將一個(gè)如“4199999A”的字符串轉(zhuǎn)換成單精度浮點(diǎn)數(shù)據(jù),會(huì)非常困難,則類(lèi)似的轉(zhuǎn)換在C或VB這類(lèi)高級(jí)語(yǔ)言中卻很容易。

在進(jìn)行上述數(shù)據(jù)處理任務(wù)時(shí),結(jié)合動(dòng)態(tài)鏈接庫(kù)是比較合理的方法。下面詳細(xì)講述一般需要用到的數(shù)據(jù)轉(zhuǎn)換如何通過(guò)VB編寫(xiě)DLL來(lái)實(shí)現(xiàn)。

在切換到VB中進(jìn)行編程之前,先了解熟悉VBS中的有關(guān)數(shù)據(jù)類(lèi)型的處理。

1、在VBS中如何定義變量

在VBS中定義變量,只能使用一種定義方式,即Dim語(yǔ)句,變量類(lèi)型只有一種,即VARIANT,而不是象在VB中可以顯示定義變量為不同的數(shù)據(jù)類(lèi)型,如String,Interger,Long等。

測(cè)試下列一段代碼:

Dim A , B , C

A = Array(10,20,30)

B = Array("10","20","30")

C = Array(CByte(A(0)),CByte(A(1)),CByte(A(2)))

 

Msgbox typename(A)         ‘顯示數(shù)據(jù)類(lèi)型為Variant()

Msgbox typename(A(0))     ‘顯示數(shù)據(jù)類(lèi)型為Interger

Msgbox typename(B)          ‘顯示數(shù)據(jù)類(lèi)型為Variant ()

Msgbox typename(B(0))     ‘顯示數(shù)據(jù)類(lèi)型為String

Msgbox typename(C)          ‘顯示數(shù)據(jù)類(lèi)型為Variant ()

Msgbox typename(C(0))     ‘顯示數(shù)據(jù)類(lèi)型為Byte

測(cè)試結(jié)果顯示,對(duì)于單個(gè)變量,雖然不能象在VB中顯示定義其數(shù)據(jù)類(lèi)型,但VBS可以大致判斷其數(shù)據(jù)類(lèi)型,也可以將數(shù)據(jù)通過(guò)強(qiáng)制轉(zhuǎn)換成所需要的數(shù)據(jù)類(lèi)型。但不管如何定義或轉(zhuǎn)換,僅通過(guò)VBS中的定義方式和轉(zhuǎn)換函數(shù),無(wú)法改變數(shù)組的類(lèi)型,最終結(jié)果只有一種數(shù)組類(lèi)型,即Varaint()。

 

2、VBS中的字符編碼

在VBS中,字符串以Unicode編碼表示,編碼的實(shí)現(xiàn)方案是UTF-16 LE。當(dāng)VBS調(diào)用低層API函數(shù)(VBS不能直接調(diào)用,而是通過(guò)控件或DLL間接調(diào)用)時(shí),大都會(huì)由系統(tǒng)自動(dòng)將Unicode字符串轉(zhuǎn)換成ANSI編碼字符串。如通過(guò)Winsock控件發(fā)送字符串,在接收端接收到的字符串實(shí)際上是ANSI字符串。

在簡(jiǎn)體中文WinXP操作系統(tǒng)下,默認(rèn)的ANSI編碼是GBK字符集。

 

3、VBS的字符轉(zhuǎn)換函數(shù)

Chr函數(shù)返回與指定的 ANSI 字符代碼相對(duì)應(yīng)的字符。

調(diào)用格式:Chr(charcode) charcode 參數(shù)是可以標(biāo)識(shí)字符的數(shù)字。

說(shuō)明:從0到31的數(shù)字表示標(biāo)準(zhǔn)的不可打印的 ASCII 代碼。例如,Chr(10) 返回?fù)Q行符。

注意:ChrB 函數(shù)與包含在字符串中的字節(jié)數(shù)據(jù)一起使用。ChrB 不是返回一個(gè)或兩個(gè)字節(jié)的字符,而總是返回單個(gè)字節(jié)的字符。ChrW 是為使用 Unicode 字符的 32 位平臺(tái)提供的。它的參數(shù)是一個(gè) Unicode (寬字符)的字符代碼,因此可以避免將 ANSI 轉(zhuǎn)化為 Unicode 字符。

Asc 函數(shù)返回與字符串的第一個(gè)字母對(duì)應(yīng)的 ANSI 字符代碼。

Asc(string) string 參數(shù)是任意有效的字符串表達(dá)式。如果 string 參數(shù)未包含字符,則將發(fā)生運(yùn)行時(shí)錯(cuò)誤。

注意:AscB 函數(shù)和包含字節(jié)數(shù)據(jù)的字符串一起使用。 AscB 不是返回第一個(gè)字符的字符代碼,而是返回首字節(jié)。 AscW 是為使用 Unicode 字符的 32 位平臺(tái)提供的。 它返回 Unicode (寬型)字符代碼,因此可以避免從 ANSI 到 Unicode 的代碼轉(zhuǎn)換。

總結(jié)如下:

chrb/ascb用來(lái)做ASCII轉(zhuǎn)換,但并不僅包括前128個(gè)字符,而是全單字節(jié)字符,所以應(yīng)該是用來(lái)做單字節(jié)字符的轉(zhuǎn)換。

chr/asc用來(lái)做ANSI轉(zhuǎn)換,在當(dāng)前中文簡(jiǎn)體WINDOWS系統(tǒng)中,即對(duì)應(yīng)于GBK字符集的轉(zhuǎn)換。在WinXP中文版下的VB6.0中,Chr能夠正確轉(zhuǎn)換遇0~128和255的單字節(jié)字符碼和GBK字符集中的雙字節(jié)字符碼,超出此范圍的字符碼或解釋成NUL字符,或是其它未料結(jié)果。

chrw/ascw用來(lái)做Unicode轉(zhuǎn)換。

 

4、在VBS中調(diào)用MSCOMM和WINSOCK的注意事項(xiàng)

在VBS中可以調(diào)用MSCOMM和WINSOCK通訊控件,以完成串口通訊和以太網(wǎng)通訊。通訊控件可以以字符串或字節(jié)數(shù)組方式進(jìn)行數(shù)據(jù)發(fā)送或接收,但由于字節(jié)數(shù)組在VBS中不能顯示定義,一個(gè)自然而然的想法是通過(guò)字符串方式進(jìn)行數(shù)據(jù)發(fā)送或接收。

如果發(fā)送的數(shù)據(jù)范圍在0x00~0x7F之間,可以通過(guò)Chr函數(shù)將十六進(jìn)制數(shù)據(jù)轉(zhuǎn)換成相應(yīng)的ASCII碼字符,并且組合成字符串?dāng)?shù)據(jù)流,由于在此數(shù)據(jù)范圍內(nèi)的字符碼可各系統(tǒng)平臺(tái)和軟件環(huán)境中均可以得到唯一正確的解析,所以這個(gè)方法是可行的。

但如果發(fā)生沖突的數(shù)據(jù)超出此范圍,再想通過(guò)Chr函數(shù)(或者ChrB/ChrW函數(shù))將十六進(jìn)制數(shù)據(jù)轉(zhuǎn)換成字符,轉(zhuǎn)換結(jié)果將不是我們所預(yù)期的結(jié)果,這與軟件平臺(tái)和操作系統(tǒng)平臺(tái)有關(guān),其中一些字符碼被解釋成空字符,或者是”?”,還有一些被解釋成不同字符集下對(duì)應(yīng)的不同的字符。所以在VBS中調(diào)用通訊控件進(jìn)行數(shù)據(jù)發(fā)送或接收,使用字符串方式不是合理的方案。

 

在了解了VBS中進(jìn)行數(shù)據(jù)處理的局限后,自然而然我們想到需要用其它的方法來(lái)解決這些問(wèn)題,可行的方法是通過(guò)DLL外部調(diào)用。因?yàn)閂B簡(jiǎn)單實(shí)用,在實(shí)際應(yīng)用中,一些在VBS中不能處理或難以處理的任務(wù),可以在VB中進(jìn)行簡(jiǎn)單的處理,用VB來(lái)創(chuàng)建編譯DLL容易掌握,將這些功能編譯進(jìn)DLL中,可以由VBS調(diào)用處理。

1、Variant數(shù)組轉(zhuǎn)換成Byte數(shù)組

如前面提到在VBS中進(jìn)行定義或轉(zhuǎn)換,只能得到Variant類(lèi)型數(shù)組,而在VB中將Variant類(lèi)型數(shù)組轉(zhuǎn)換成Byte型數(shù)組非常簡(jiǎn)單,如下面這個(gè)函數(shù)就可以實(shí)現(xiàn)這個(gè)功能:

Public Function CvVariantArray2vByteArray(inVarArray As Variant) As Variant

 

Dim i As Integer, byteArray() As Byte

 

ReDim byteArray(UBound(inVarArray))

 

For i = 0 To UBound(inVarArray)

    byteArray(i) = inVarArray(i)

Next i

 

CvVariantArray2vByteArray = byteArray

 

End Function

在上面這個(gè)函數(shù)中,僅僅做了兩件事,一是定義一個(gè)Byte數(shù)組,二是將Variant數(shù)組元素拷貝到Byte數(shù)組中。

 

2、十六進(jìn)制數(shù)據(jù)格式字符串轉(zhuǎn)換成相應(yīng)的Byte數(shù)組

十六進(jìn)制數(shù)據(jù)格式字符串是指字符串中的字符(兩個(gè)一組)以十六進(jìn)制數(shù)據(jù)格式表示,范圍在“00”至“FF”之間,如下面這個(gè)字符串:

“EB9000FF”

將這樣一個(gè)字符串轉(zhuǎn)換成相應(yīng)的Byte數(shù)組,其轉(zhuǎn)換結(jié)果是:

BYTE(3) = (0xEB,0x90,0x00,0xFF)

相應(yīng)的VB函數(shù)代碼如下所示:

Public Function CvHexStr2vOctetStr(vInstr As Variant) As Variant

' Use this to convert a Variant containing an ASCII encoded Hex string to a Variant Array of bytes

' this allows vbs to create Variants for ADSTYPE_OCTETSTRING from strings of ASCII characters 0-9 A-F

   

    Dim vOutArray() As Byte, i As Long

    Dim v As Variant

    ReDim vOutArray(0 To Len(vInstr) \ 2 - 1)

    For i = 1 To Len(vInstr) \ 2

        vOutArray(i - 1) = Val("&H" & Mid(vInstr, 2 * i - 1, 1)) * 16 + Val("&H" & Mid(vInstr, 2 * i, 1))

    Next i

    CvHexStr2vOctetStr = vOutArray

End Function

該函數(shù)的工作原理如下(以“EB9000FF”為例):

字符串vInstr = “EB9000FF” 是一個(gè)Unicode字符串,在內(nèi)存中的存放的十六進(jìn)制字節(jié)序?yàn)椤?5-00-42-00-39-00-30-00-30-00-30-00-46-00-46-00”,字符串長(zhǎng)是8(Len函數(shù))。

新建一個(gè)Byte數(shù)組,數(shù)組元素個(gè)數(shù)為4。

Mid函數(shù)是從指定字符串中返回指定數(shù)目的字符(注意不是字節(jié)),該函數(shù)以字符為基本操作元素,不是字節(jié),由于在VB中,字符以Unicode格式(UCS-2/UTF-16 LE,雙字節(jié))表示,F(xiàn)or循環(huán)開(kāi)始時(shí)(i = 0),Mid(vInstr, 2 * i - 1, 1)首先取出第一個(gè)字符,即“E”(雙字節(jié)十六進(jìn)制“0045”,小端序),這個(gè)字符是十六制格式的,所以在前面加上“&H”前綴表示十六進(jìn)制書(shū)寫(xiě)格式,將這個(gè)十六進(jìn)制格式字符經(jīng)Val函數(shù)轉(zhuǎn)換成對(duì)應(yīng)的數(shù)字,即14,由于這個(gè)字符是字節(jié)中的高4位,所以需要*16,等于224。

類(lèi)似,取出同一字節(jié)中的低4位“B”并轉(zhuǎn)換成相應(yīng)的數(shù)字11,并與高4位數(shù)字相加,最終結(jié)果是235,在內(nèi)存中存放的十六進(jìn)制字節(jié)為“EB”。

循環(huán)結(jié)束后,得到字節(jié)數(shù)組(0xEB,0x90,0x00,0xFF)。

 

3、四字節(jié)十六進(jìn)制數(shù)據(jù)格式字符串轉(zhuǎn)換成單精度浮點(diǎn)數(shù)據(jù)

在IEEE 754標(biāo)準(zhǔn)中定義了單精度浮點(diǎn)數(shù)采用32位二進(jìn)制數(shù)據(jù)(4字節(jié))表示,二進(jìn)制數(shù)據(jù)按位分割成符號(hào)位、指數(shù)域和尾數(shù)域,將浮點(diǎn)數(shù)轉(zhuǎn)換成實(shí)數(shù),需要按公式進(jìn)行計(jì)算。如果在VBS中處理這樣的轉(zhuǎn)換,需要進(jìn)行移位、判斷、計(jì)算等多步處理,比較繁瑣,運(yùn)行效率也不見(jiàn)得有多高,而在VB中進(jìn)行這樣的轉(zhuǎn)換處理是很方便的。

比如在VBS中使用通訊控件接收數(shù)據(jù),在接收到的數(shù)據(jù)包中有四個(gè)字節(jié)的數(shù)據(jù)(9A,99, E5,41),這四個(gè)字節(jié)的數(shù)據(jù)表示一個(gè)IEEE單精度浮點(diǎn)數(shù),在字節(jié)流中以小端序(LE)傳輸(41是高有效字節(jié)MSByte),以DWORD表示即為0x41E5999A,轉(zhuǎn)換成單精度浮點(diǎn)數(shù)即為28.7。

這樣的字節(jié)流在通訊控件接收到以后,存放在Byte數(shù)組中,在內(nèi)存中存儲(chǔ)的字節(jié)為9A-99-E5-41,其實(shí)這正是IEEE單精度浮點(diǎn)數(shù)在內(nèi)存中的存放格式,如果能將該內(nèi)存區(qū)(4字節(jié))拷貝給一個(gè)float型變量,就可以很方便的完成轉(zhuǎn)換工作。但在VBS中沒(méi)有直接對(duì)內(nèi)存區(qū)進(jìn)行操作的命令或函數(shù),所以這個(gè)轉(zhuǎn)換工作需要放在DLL中進(jìn)行。

這個(gè)四字節(jié)的Byte數(shù)組,可以直接通過(guò)VB函數(shù)轉(zhuǎn)換成float。出于學(xué)習(xí)的目的,先將Byte數(shù)組轉(zhuǎn)換成字符串,再將字符串轉(zhuǎn)換成float。

將Byte數(shù)組轉(zhuǎn)換成字符串的工作放在VBS中進(jìn)行,代碼如下:

‘將接收到的BYTE()型數(shù)據(jù)轉(zhuǎn)換為String型數(shù)據(jù)

For i = 0 To 3

     strFromRec = strFromRec & Right("0" & Hex(AscB(MidB(strReceive , i + 1 ,1))) , 2 )

Next

上面代碼中strReceive變量存放的即為接收到的Byte數(shù)組數(shù)據(jù),在VBS中可以使用Mid(或MidB)函數(shù)直接操作Byte數(shù)組(一般用來(lái)操作字符串String),其中MidB函數(shù)中的參數(shù)以字節(jié)為操作對(duì)象,MidB函數(shù)返回一個(gè)ASCII字符(數(shù)據(jù)類(lèi)型是字符串,但在字存中還是一個(gè)字節(jié)數(shù)據(jù),該字節(jié)數(shù)據(jù)為ASCII字符對(duì)應(yīng)的ASCII字符碼,范圍“00”~“FF”之間)。

上面的代碼是依次提取字節(jié)流中的字節(jié),然后通過(guò)AscB函數(shù)將提取的ASCII字符轉(zhuǎn)換成對(duì)應(yīng)的ASCII字符碼,再用Hex函數(shù)將字符碼轉(zhuǎn)換成十六進(jìn)制數(shù)據(jù)格式表示的字符串。其中Right函數(shù)的使用是為了保持0~F字符碼轉(zhuǎn)換后的雙字符格式。

 

將字符串轉(zhuǎn)換成float的VB函數(shù)代碼如下:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

‘------------------------------------------------------------------------------

Public Function CvHexStr2vReal2(vInstr As Variant) As Variant

Dim l As Long

Dim f As Single

Dim str As String

Dim i As Integer

 

str = ""

For i = 4 To 1 Step -1

    str = str & Mid(vInstr, i * 2 - 1, 2)

Next i

l = Val("&H" & str)

CopyMemory f, l, 4

 

CvHexStr2vReal2 = f

   

End Function

上面的程序代碼中,首先對(duì)輸入的字符串進(jìn)行了高低位互換,這是可以理解的,因?yàn)閷?duì)于字符串或字節(jié)數(shù)組,在內(nèi)存中的存放是按書(shū)寫(xiě)順序由高到低存放的,在使用Val函數(shù)將字符串表達(dá)式傳換成對(duì)應(yīng)的整型數(shù)據(jù)前,字符串中的字節(jié)順序排列是9A99E541,直接使用Val函數(shù)轉(zhuǎn)換成整型數(shù)據(jù)是0x9A99E541,由于VB中整型數(shù)據(jù)是小端序存儲(chǔ)方式,則在內(nèi)存中的存放順序是,由低地址到高地址是41-E5-99-9A,使用API函數(shù)CopyMemory進(jìn)行內(nèi)存拷貝是按字節(jié)順序依次拷貝的,拷貝到浮點(diǎn)數(shù)變量?jī)?nèi)存中也是由低地址到高地址41-E5-99-9A排列,而VB對(duì)浮點(diǎn)型數(shù)據(jù)內(nèi)存的解析同樣采用小端序方式解析出來(lái),最終得出的不是正確的結(jié)果,所以必須進(jìn)行高低位字節(jié)的轉(zhuǎn)換處理。

函數(shù)代碼的工作過(guò)程是這樣的:首先將輸入的字符串進(jìn)行高低字節(jié)互換,然后將互換后的字符串用Val函數(shù)按十六進(jìn)制數(shù)據(jù)格式轉(zhuǎn)換成整型數(shù)據(jù),再用CopyMemory函數(shù)將整型數(shù)據(jù)內(nèi)存區(qū)拷貝到浮點(diǎn)數(shù)內(nèi)存區(qū),最后函數(shù)返回的數(shù)據(jù)就是轉(zhuǎn)換后的浮點(diǎn)數(shù)。

在函數(shù)轉(zhuǎn)換處理過(guò)程中的變量在內(nèi)存中的存放情況如下所示:

輸入字符串:“9A99E541”

輸入字符串在內(nèi)存中存儲(chǔ)的十六進(jìn)制數(shù)據(jù)及順序:

39-00-41-00-39-00-39-00-45-00-35-00-34-00-31-00

高低位互換后的字符串在內(nèi)存中存儲(chǔ)的十六進(jìn)制數(shù)據(jù)及順序:

34-00-31-00-45-00-35-00-39-00-39-00-39-00-41-00

轉(zhuǎn)換成整型后在內(nèi)存中存儲(chǔ)的十六進(jìn)制數(shù)據(jù)及順序:

9A-99-E5-41

轉(zhuǎn)換成單精度數(shù)據(jù)后在內(nèi)存中存儲(chǔ)的十六進(jìn)制數(shù)據(jù)及順序:

9A-99-E5-41

函數(shù)返回結(jié)果:28.7


參考資料:

1、VBS用戶(hù)手冊(cè)

2、WinCC中的畫(huà)面模板

3、在VB6中用CopyMemory拷貝字符串的種種貓膩

4、關(guān)于字符編碼,你所需要知道的

5、深入淺出浮點(diǎn)數(shù)

 

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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多