Example: Response to a Noncyclical Read Enquriy

General

The task is to respond to noncyclical read enquiries of the master and to return data depending on the slot and the index of the enquiries.

For this purpose, a function block has to be created which implements the interface IF_AsyncRead.

The program code can be written in the AsyncRead method of the implemented function unit which is prescribed by IF_AsycnRead.

In the example code, the data of an array which is available as global variable are to be returned in response to read enquiries on slot 1 and index 120, if the length of the enquiry is within the array limits.

In all other cases, a negative response is to be send back to the master.

METHOD AsyncRead : UDINT
VAR_INPUT
   (* Slot number of the process data object to be read*)
   i_bySlot : BYTE;
   (* Index of the process data object to be read*)
   i_byIndex : BYTE;
   (* Number of bytes to be read in the specified process data object*)
   i_byLength : BYTE;
END_VAR
VAR_IN_OUT
   (* Process data object data that has been read*)
   iq_abyData : ARRAY [0..(Gc_C1AsyncRead_MaxDataLength - 1)] OF BYTE;
   (* Number of bytes that has been read in the specified process data object*)
   iq_byReadLength : BYTE := 0;
   iq_stError : IoDrvPROFIBUSDPV1Slave.ST_PROFIBUSDPV1AsyncDataError;
END_VAR
VAR
   udiIndex : UDINT := 0;
   sInfo : STRING(255) := '';
END_VAR
// You can write your own code here.
// The code is called by the callback when an acyclic read operation is requested.
   // React on requests to slot 1, index 120
   IF (i_bySlot = 1 AND i_byIndex = 120) THEN
      // Check the requested data length
      IF (i_byLength <= Gc_C1AsyncRead_MaxDataLength) THEN
      // Insert data
      FOR (udiIndex := 0) TO (i_byLength-1) DO
         iq_abyData[udiIndex] := G_abyDataTransfer[udiIndex];
      END_FOR
      // Return read data length
      iq_byReadLength := i_byLength;
      // Before this method is called, the slave-device searches for registered data modules.
      // If no data module is registered for this slot and index, the values of stError.byErrorDecode,
      // iq_stError.byErrorCode1 and iq_stError.byErrorCode2 can be <> 0.
      // Therefore they must be set to 0 => indicates that data was read.
      iq_stError.byErrorDecode := 0;
      iq_stError.byErrorCode1 := 0;
      iq_stError.byErrorCode2 := 0;
   ELSE
      // Error: Invalid length requested
      // iq_stError.byErrorDecode <> 0 actuates a negative response to the master.
      // iq_stError.byErrorCode1 and iq_stError.byErrorCode2 refines the error.
      iq_byReadLength := 0;
      iq_stError.byErrorDecode := 1;
      iq_stError.byErrorCode1 := 16#01;
      iq_stError.byErrorCode2 := 16#00;
   END_IF
END_IF

In this case, G_abyDataTransfer is the array returning the data for slot 1, index 120. The interpretation of slot and index can be defined freely. Gc_udiMaxDataTransfer contains the length of the array G_abyDataTransfer.

It is determined by means of the in / out parameter iq_stError whether the slave sends back a positive or a negative response to the master. As explained in the notes on the example, the values iq_stError.byErrorDecode, iq_stError.byErrorCode1 and iq_stError.byErrorCode2 should always be set to 0 if the enquiry has been processed successfully, since the initial values do not have to be 0. If for example no data module is registered on slot 1, index 120 (see Registering noncyclical data areas), the three variables of the structure will contain the corresponding error values.

If iq_stError.byErrorDecode is set to 0 after the method FB_UserCallback.AsyncRead() has been executed, a positive response including the enquired data is sent back to the master.

AsyncWrite, AsyncAlarmAck

For the other noncyclical enquiries of the master, proceed in the same way as for AsyncRead.