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.

Beispiel mit AdsWriteInd-/AdsWriteRes-Funktionsbausteinen 1:

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.

Beispiel mit AdsWriteInd-/AdsWriteRes-Funktionsbausteinen 2:

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