Beispiel mit AdsReadInd-/AdsReadRes-Funktionsbausteinen
Das Beispiel zeigt die Implementierung einer einfachen ADS-Server-Applikation in der SPS. Die Server-Applikation kann die ADSREAD-Requests einer ADS-Client-Applikation bearbeiten.
In der Beispielapplikation werden ADSREAD-Requests verwendet um in der SPS-Task eine SPS-Zählervariable zu inkrementieren/dekrementieren oder zurückzusetzen. Beim Erfolg wird der Wert der Zählervariablen an die ADS-Client-Applikation zurück gesendet
Die kompletten Sourcen der ADS-Server-Applikation können hier entpackt werden: AdsReadIndServerExample.zip
Eine zu dem ADS-Server passende ADS-Client-Applikation kann hier gefunden werden: Beispiel mit ADSREAD-Funktionsbaustein.
ADS-Client-Applikation
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;
Der Index-Offset-Parameter ist Null.
![]() | Damit die Requests an die SPS-Task weiter geleitet werden, muss in dem Index-Group-Parameter das höchstwertige Bit gesetzt werden. |
SPS-Programm
Die ADSREAD-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. Im nächsten Zyklus werden die Flags CLEAR und RESPOND an den Funktionsbausteinen zurückgesetzt um weitere Indications verarbeiten zu können.
Deklarationsteil
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 : PVOID;(* Pointer to returned read data/buffer *)
nErrID : UDINT;(* Read indication result error code *)
nCounter : INT;(* Server data *)
END_VAR
Implementierung
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 := DEVICE_SRVNOTSUPP;
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 := NOERR;
ELSE (* ADS error (example): Invalid size *)
nErrID := DEVICE_INVALIDSIZE;
END_IF
ELSE (* ADS error (example): Invalid index offset *)
nErrID := DEVICE_INVALIDOFFSET;
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 := NOERR;
ELSE(* ADS error (example): Invalid size *)
nErrID := DEVICE_INVALIDSIZE;
END_IF
ELSE (* ADS error (example): Invalid index offset *)
nErrID := DEVICE_INVALIDOFFSET;
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 := NOERR;
ELSE(* ADS error (example): Invalid size *)
nErrID := DEVICE_INVALIDSIZE;
END_IF
ELSE (* ADS error (example): ervice is not supported by server *)
nErrID := DEVICE_SRVNOTSUPP;
END_CASE
ELSE (* ADS error (example): Invalid index group *)
nErrID := DEVICE_INVALIDGRP;
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