Example with AdsReadInd /AdsReadRes function blocks
The example shows the implementation of a simple ADS Server application to the PLC. The server application can process the ADSREAD requests of an ADS Client application.
In the example application, ADSREAD requests are used to increment/decrement or reset a PLC counter variable in the PLC task. If successful the value of the counter variable is returned to the ADS Client application
The complete sources of the ADS server application can be unpacked here: AdsReadIndServerExample.zip
An ADS Client application suitable for the ADS Server can be found here: Example with ADSREAD function block.
ADS Client application
The required service in the PLC task is encoded in the index group parameter:
IG:0x80000001 → increment the counter variable;
IG:0x80000002 → decrement the counter variable;
IG:0x80000003 → set the counter variable = 0;
The index offset parameter is zero.
![]() | 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 ADSREAD requests are intercepted as indications in the PLC task by an instance of the ADSREADIND function block. Afterwards the index group and index offset parameters and the required data length and validity are checked. In the CASE instruction the desired operation with the PLC variables is carried out. If successful a response is sent back by an instance of the ADSREADRES function block to the caller with the current value of the PLC variables. In the case of an error an appropriate error message. In the next cycle the CLEAR and RESPOND flags on the function blocks are reset in order to be able to process further indications.
Declaration Part
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
Implementation
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