Beispiel mit AdsWriteInd-/AdsWriteRes-Funktionsbausteinen
Das Beispiel zeigt die Implementierung einer einfachen ADS-Server-Applikation in der SPS. Die Server Applikation kann auf die ADSWRITE-Requests einer ADS-Client-Applikation bearbeiten.
In der Beispielapplikation werden ADSWRITE-Requests verwendet um Array mit Integer-Werten in die SPS-Task zu übertragen. Die empfangenen Daten werden in der SPS in eine entsprechende Array-Variable kopiert.
Die kompletten Sourcen der ADS-Server-Applikation können hier entpackt werden: AdsWriteIndServerExample.zip
Eine zu dem ADS-Server passende ADS-Client-Applikation kann hier gefunden werden: Beispiel mit ADSWRITE-Funktionsbaustein.
ADS-Client-Applikation
Der gewünschte Dienst/Befehl 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. |
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. Im nächsten Zyklus 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. |
Deklarationsteil
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 : PVOID;(* Pointer to written data buffer *)
nResult : UDINT;(* Write indication result error code *)
arrInt : ARRAY[0..9] OF INT;(* Server data *)
END_VAR
Implementierung
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 := DEVICE_SRVNOTSUPP;
CASE nIdxGrp OF
16#80000005:
CASE nIdxOffs OF
16#00000007:
IF cbWrite <= SIZEOF( arrInt ) THEN
MEMCPY( ADR( arrInt ), pWrite, MIN( cbWrite, SIZEOF(arrInt) ) );
nResult := NOERR;
ELSE(* ADS error (example): Invalid size *)
nResult := DEVICE_INVALIDSIZE;
END_IF
ELSE(* ADS error (example): Invalid index offset *)
nResult := DEVICE_INVALIDOFFSET;
END_CASE
ELSE(* ADS error (example): Invalid index group *)
nResult := DEVICE_INVALIDGRP;
END_CASE
fbWriteRes( NETID := sNetId,
PORT := nPort,
INVOKEID := nInvokeId,
RESULT := nResult,
RESPOND := TRUE ); (* Send write response *)
fbWriteInd( CLEAR := TRUE ); (* Clear indication entry *)
END_IF