Beispiel 1: Erweiterte ADS-Funktionsbausteine
In der Beispielapplikation werden von einer VB-Applikation READ-Requests an die SPS-Task gesendet um eine SPS-Zählervariable zu inkrementieren/dekrementieren oder zurücksetzen. Beim Erfolg wird der Wert der Zählervariablen an die VB-Applikation zurück gesendet und auf der Form Ausgegeben. 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-Parameter verschlüsselt:
- IG:0x80000001 -> Die Zählervariable inkrementieren;
- IG:0x80000002 -> Die Zählervariable dekrementieren;
- IG:0x80000003 -> Die Zählervariable = 0 setzen;
Damit die Requests an die SPS-Task weiter geleitet werden, muss in dem Index-Group-Parameter das höchstwertige Bit gesetzt werden. Der Index-Offset-Parameter ist Null.
Option Explicit
Dim tmpData(1) As Integer
Dim AdsResult As Integer
Private Sub Command1_Click()
AdsResult = AdsOcx1.AdsSyncReadReq(&H80000001, &H0, 2, tmpData)
Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)
End Sub
Private Sub Command2_Click()
AdsResult = AdsOcx1.AdsSyncReadReq(&H80000002, &H0, 2, tmpData)
Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)
End Sub
Private Sub Command3_Click()
AdsResult = AdsOcx1.AdsSyncReadReq(&H80000003, &H0, 2, tmpData)
Label1.Caption = "Ads result:" & AdsResult & " PLC data:" & tmpData(0)
End Sub
Private Sub Form_Load()
AdsOcx1.AdsAmsServerNetId = AdsOcx1.AdsAmsClientNetId
AdsOcx1.AdsAmsServerPort = 802 'PLC task number'
End Sub
Das SPS Programm
Die Requests werden in der SPS-Task von einer Instanz des ADSREADIND-Funktionsbausteins als Indications abgefangen. Danach werden die Parameter Index-Group, Index-Offset und die angeforderte Datenlänge auf Gültigkeit überprüft. In der CASE-Anweisung wird die gewünschte Operation an der SPS-Variablen durchgeführt. Beim Erfolg wird ein Response von einer Instanz des ADSREADRES-Funktionsbausteins an den Aufrufer mit dem aktuellen Wert der SPS-Variablen zurückgesendet. Im Fehlerfall eine entsprechende Fehlermeldung. Zum Schluss werden die Flags CLEAR und RESPOND rückgesetzt um weitere Indications verarbeiten zu können.
PROGRAM MAIN
VAR
fbReadInd : ADSREADIND;(* Indication function block instance *)
fbReadRes : ADSREADRES;(* Response function block instance *)
sNetId : T_AmsNetID;
nPort : T_AmsPort;
nInvokeId : UDINT;
nIdxGrp : UDINT;
nIdxOffs : UDINT;
cbLength : UDINT;(* Requested read data/buffer byte size *)
cbRead : UDINT;(* Returned read data/buffer byte size *)
pRead : POINTER TO BYTE;(* Pointer to returned read data/buffer *)
nErrID : UDINT;(* Read indication result error code *)
nCounter : INT;(* Server data *)
END_VAR
fbReadRes( RESPOND := FALSE );(* Reset response function block *)
fbReadInd( CLEAR := FALSE );(* Trigger indication function block *)
IF fbReadInd.VALID THEN(* Check for new indication *)
sNetID := fbReadInd.NETID;
nPort := fbReadInd.PORT;
nInvokeID := fbReadInd.INVOKEID;
nIdxGrp := fbReadInd.IDXGRP;
nIdxOffs := fbReadInd.IDXOFFS;
cbLength := fbReadInd.LENGTH;
cbRead := 0;
pRead := 0;
nErrID := 16#701;(* ADS error: Service not supported by server *)
CASE nIdxGrp OF
(*------------------------------------------------------------------------------------*)
16#80000001:
CASE nIdxOffs OF
0:(* Increment counter value *)
IF cbLength >= SIZEOF(nCounter) THEN
nCounter := nCounter + 1;
cbRead := SIZEOF(nCounter);
pRead := ADR(nCounter);
nErrID := 0;
ELSE (* ADS error (example): Invalid size *)
nErrID := 16#705;
END_IF
ELSE (* ADS error (example): Invalid index offset *)
nErrID := 16#703;
END_CASE
(*------------------------------------------------------------------------------------*)
16#80000002:
CASE nIdxOffs OF
0:(* Decrement counter value *)
IF cbLength >= SIZEOF(nCounter) THEN
nCounter := nCounter - 1;
cbRead := SIZEOF(nCounter);
pRead := ADR(nCounter);
nErrID := 0;
ELSE(* ADS error (example): Invalid size *)
nErrID := 16#705;
END_IF
ELSE (* ADS error (example): Invalid index offset *)
nErrID := 16#703;
END_CASE
(*------------------------------------------------------------------------------------*)
16#80000003:
CASE nIdxOffs OF
0:(* Reset counter value *)
IF cbLength >= SIZEOF(nCounter) THEN
nCounter := 0;
cbRead := SIZEOF(nCounter);
pRead := ADR(nCounter);
nErrID := 0;
ELSE(* ADS error (example): Invalid size *)
nErrID := 16#705;
END_IF
ELSE (* ADS error (example): Service is not supported by server *)
nErrID := 16#701;(* ADS error: Service not supported *)
END_CASE
ELSE (* ADS error (example): Invalid index group *)
nErrID := 16#702;
END_CASE
fbReadRes( NETID := sNetID,
PORT := nPort,
INVOKEID := nInvokeID,
LEN := cbRead,
DATAADDR := pRead,
RESULT := nErrID,
RESPOND := TRUE );(* Send read response *)
fbReadInd( CLEAR := TRUE ); (* Clear indication entry *)
END_IF
Hier können Sie die kompletten Sourcen zu der Beispielapplikation entpacken: Beispielapplikation mit den erweiterten ADS-Funktionsbausteinen