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.

Beispiel mit AdsReadInd-/AdsReadRes-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 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