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