Beispiel: Reaktion auf azyklische Leseanforderung

Allgemeines

Es soll auf azyklische Leseanforderungen des Masters reagiert werden und abhängig vom Slot und Index der Anforderung sollen Daten zurückgegeben werden.

Dazu muss ein Funktionsbaustein erstellt werden, der das Interface IF_AsyncRead implementiert.

In der von IF_AsycnRead vorgeschriebenen Methode AsyncRead des implementierten Funktionsbausteins kann der Programmcode geschrieben werden.

Im Beispiel-Code sollen auf Leseanforderungen auf Slot 1 und Index 120 die Daten eines Arrays, welches als globale Variable verfügbar ist, zurückgegeben werden, wenn die Länge der Anforderung innerhalb der Arraygrenzen ist.

Ansonsten soll ein negativer Response an den Master zurückgesendet werden.

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

G_abyDataTransfer ist dabei das Array, welches die Daten für Slot 1, Index 120 zurückgibt. Die Interpretation von Slot und Index ist frei definierbar. Gc_udiMaxDataTransfer enthält die Länge des Arrays G_abyDataTransfer.

Durch den In- / Outparameter iq_stError wird beeinflusst, ob der Slave dem Master einen positiven oder negativen Response zurücksendet. Wie in den Kommentaren im Beispiel erläutert, sollten die Werte iq_stError.byErrorDecode, iq_stError.byErrorCode1 und iq_stError.byErrorCode2 bei erfolgreicher Abarbeitung der Anfrage immer auf 0 gesetzt werden, da die Anfangswerte nicht 0 sein müssen. Ist z.B. auf Slot 1, Index 120 kein Datenmodul registriert (siehe Registrierung azyklischer Datenbereiche), enthalten die drei Variablen der Struktur entsprechende Fehlerwerte.

Steht iq_stError.byErrorDecode nach der Ausführung der Methode FB_UserCallback.AsyncRead() auf 0, wird eine positive Antwort einschließlich der angeforderten Daten an den Master zurückgesendet.

AsyncWrite, AsyncAlarmAck

Mit den anderen azyklischen Anforderungen des Masters ist analog zu AsyncRead zu verfahren.