Beispiel 2: Erweiterte ADS-Funktionsbausteine
Die VB-Applikation sendet ein Array mit Integer-Werten zu einer SPS-Task. Die zuletzt gesendeten Werte werden einer Liste hinzugefügt und in der SPS in eine entsprechende Array-Variable kopiert. Die VB-Applikation benutzt einen WRITE-Request um die Daten zu senden. In der SPS wird der ADSWRITEIND-Funktionsbaustein benutzt um die Daten zu empfangen und ADSWRITERES-Funkstionbaustein um den WRITE-Request zu quittieren. Um mit der SPS-Task zu kommunizieren benutzt die VB-Applikation das ActiveX Control: AdsOcx.
Hier können Sie die kompletten Sourcen zu der Beispielapplikation entpacken: Beispielapplikation mit den erweiterten ADS-Funktionsbausteinen
Die VB-Applikation
In der Form_Load-Routine wird eine Verbindung zu der SPS-Task aufgebaut ( Port 802 auf dem lokalen Rechner ). Der gewünschte Dienst in der SPS-Task wird in dem Index-Group und Index-Offset Parameter verschlüsselt. Z.B.:
- IG:0x80000005 und
- IO:0x00000007-> Die gesendeten Daten in den Array in der SPS kopieren.
Damit die Requests an die SPS-Task weiter geleitet werden, muss in dem Index-Group-Parameter das höchstwertige Bit gesetzt werden.
Option Explicit
Dim AdsResult As Integer
Dim arrData(0 To 9) As Integer
Private Sub cmdWrite_Click()
Call List1.Clear
Dim i As Long
For i = LBound(arrData) To UBound(arrData)
arrData(i) = arrData(i) + 1 'change values
Call List1.AddItem("arrData(" & i & ") = " & arrData(i))
Next i
'calculate the byte length parameter
Dim cbWriteSize As Long
cbWriteSize = (UBound(arrData) - LBound(arrData) + 1) * LenB(arrData(LBound(arrData)))
AdsResult = AdsOcx1.AdsSyncWriteReq(&H80000005, &H7, cbWriteSize, arrData) 'send data to PLC
Label1.Caption = "Ads result: " & AdsResult
End Sub
Private Sub Form_Load()
AdsOcx1.AdsAmsServerNetId = AdsOcx1.AdsAmsClientNetId
AdsOcx1.AdsAmsServerPort = 802 'PLC task number'
Dim i As Long
For i = LBound(arrData) To UBound(arrData)
arrData(i) = i 'init data
Next i
End Sub
Das SPS Programm
Die Requests werden in der SPS-Task von einer Instanz des ADSWRITEIND-Funktionsbausteins als Indications abgefangen. Danach werden die Parameter Index-Group, Index-Offset und die gesendete Datenlänge auf Gültigkeit überprüft und die gewünschte Operation an der SPS-Variablen durchgeführt. Als Nächstes wird ein Response von einer Instanz des ADSWRITERES-Funktionsbausteins an den Aufrufer (eventuell mit einem Fehlercode) zurückgesendet. Zum Schluss werden die Flags CLEAR und RESPOND rückgesetzt um weitere Indications verarbeiten zu können.
![]() | Mit der steigenden Flanke am CLEAR-Eingang des ADSWRITEIND-Funktionsbausteins wird der Adresspointer auf die zuletzt gesendeten Daten ungültig ( == NULL ). Aus diesem Grund werden die gesendeten Daten zuerst in die SPS-Variable kopiert und dann der CLEAR-Eingang auf TRUE gesetzt. |
PROGRAM MAIN
VAR
fbWriteInd : ADSWRITEIND;
fbWriteRes : ADSWRITERES;
sNetId : T_AmsNetID;
nPort : T_AmsPort;
nInvokeId : UDINT;
nIdxGrp : UDINT;
nIdxOffs : UDINT;
cbWrite : UDINT;(* Byte size of written data *)
pWrite : POINTER TO BYTE;(* Pointer to written data buffer *)
nResult : UDINT;(* Write indication result error code *)
arrInt : ARRAY[0..9] OF INT;(* Server data *)
END_VAR
fbWriteRes( RESPOND := FALSE );(* Reset response function block *)
fbWriteInd( CLEAR := FALSE );(* Trigger indication function block *)
IF ( fbWriteInd.VALID ) THEN
sNetId := fbWriteInd.NETID;
nPort := fbWriteInd.PORT;
nInvokeId := fbWriteInd.INVOKEID;
nIdxGrp := fbWriteInd.IDXGRP;
nIdxOffs := fbWriteInd.IDXOFFS;
cbWrite := fbWriteInd.LENGTH;
pWrite := fbWriteInd.DATAADDR;
nResult := 16#701;(* ADS error: Service not supported by server *)
CASE nIdxGrp OF
16#80000005:
CASE nIdxOffs OF
16#00000007:
IF cbWrite <= SIZEOF( arrInt ) THEN
MEMCPY( ADR( arrInt ), pWrite, MIN( cbWrite, SIZEOF(arrInt) ) );
nResult := 0;
ELSE(* ADS error (example): Invalid size *)
nResult := 16#705;
END_IF
ELSE(* ADS error (example): Invalid index offset *)
nResult := 16#703;
END_CASE
ELSE(* ADS error (example): Invalid index group *)
nResult := 16#702;
END_CASE
fbWriteRes( NETID := sNetId,
PORT := nPort,
INVOKEID := nInvokeId,
RESULT := nResult,
RESPOND := TRUE ); (* Send write response *)
fbWriteInd( CLEAR := TRUE ); (* Clear indication entry *)
END_IF
Hier können Sie die kompletten Sourcen zu der Beispielapplikation entpacken: Beispielapplikation mit den erweiterten ADS-Funktionsbausteinen