Example with AdsWriteInd/AdsWriteRes function blocks

The example shows the implementation of a simple ADS Server application to the PLC. The server application can process the ADSWRITE requests of an ADS Client application.

In the example application ADSWRITE requests are used to transfer arrays with integer values to the PLC task. The received data are copied in the PLC into an appropriate array variable.

The complete sources of the ADS server application can be unpacked here: AdsWriteIndServerExample.zip

An ADS Client application suitable for the ADS Server can be found here: Example with ADSWRITE function block.

ADS Client application

The desired service/command from the PLC task is encoded in the index group and index offset parameters. E.g.:

IG:0x80000005 and IO:0x00000007→ copy the sent data to the array in the PLC.

Example with AdsWriteInd/AdsWriteRes function blocks 1:

So that the requests can be routed to the PLC task, the highest value bit must be set in the index group parameter.

PLC program

The requests are intercepted as indications in the PLC task by an instance of the ADSWRITEIND function block. Following this, the index group, index offset and transmitted data length parameters are checked for validity, and the desired operation is carried out on the PLC variable. The next step is for a response to be returned to the caller (including an error code, if appropriate) by an instance of the ADSWRITERES-function block. In the next cycle the CLEAR and RESPOND flags are reset in order to be able to process further indications.

Example with AdsWriteInd/AdsWriteRes function blocks 2:

With the rising edge at the CLEAR input of the ADSWRITEIND function block the address pointer to the most recently sent data becomes invalid ( == ZERO ).

For this reason the sent data is first copied into the PLC variable before the CLEAR input is set to TRUE.

Declaration Part

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

Implementation

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