TIA Any-Pointer übergeben

holgero

Level-1
Beiträge
255
Reaktionspunkte
30
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,
ich versuche gerade einen FB zu programmieren.
Über die IN/OUT-Bausteinschnittstelle möchte ich eine Variable vom Typ ANY übergeben.
Mit dieser Variable will ich nun den Baustein "DPRD_DAT" (SFC14 in Step7 / konsistente Daten eines DP-Nomrslaves lesen) beschalten.
Leider gelingt mir das nicht. Weder in Step7 Classic noch im TIA-Portal.

Entweder ich habe die richtige Syntax noch nicht gefunden, oder es geht aus irgend einem Grund gar nicht :-|

Ich kann den Datentyp ANY in den Bereichen IN, OUT, IN_OUT und TEMP deklarieren.
Das beschalten des "DPRD_DAT" gelingt aber nur, wenn es eine TEMP-Variable ist.
Hat jemand eine Idee, wie ich es richtig machen könnte?

DPRD_DAT RECORD OUTPUT ANY E, A, M, D, L
Zielbereich für die gelesenen Nutzdaten. Er muß genauso lang sein, wie Sie für die selektierte Baugruppe mit STEP 7 projektiert haben. Es ist nur der Datentyp BYTE zulässig.Hinweis: Beachten Sie, dass der Parameter RECORD bei S7-300-CPUs immer die vollständige Angabe der DB-Parameter erfordert (Bsp.: P#DB13.DBX0.0 Byte 100). Das Weglassen einer expliziten DB-Nr. ist für S7-300-CPUs unzulässig und führt zu einer Fehlermeldung im Anwenderprogramm.

Vielen Dank im Voraus
Holger
 
Sieh dir mal folgenden Beitrag an: #7

Es gibt dazu auch noch mehr im Forum, Stichwort z.Bsp. "Any durchreichen".
Du mußt den Inhalt des Any auf einen Temp-Any "umlegen" und diesen dann verwenden. Genau das passiert im oberen Beispiel.
Für SCL findet sich sicher auch noch ein Code-Sample im Forum.
 
Pointer auf Übergabeparameter FB

Sieh dir mal folgenden Beitrag an: #7
Achtung!
Der Link zeigt Code für einen FC, da wird der ANY als 6-Byte Pointer auf den ANY übergeben (byReference).

Holger will aber einen FB programmieren. Da wird der ANY direkt übergeben (byValue). Sehr wahrscheinlich wird der FB auch noch multiinstanzfähig sein, da muß dann zur Adresse des ANY-Parameters auch noch der Instanz-Versatz aus AR2 addiert werden. In nicht-multinstanzfähigen FB ist AR2=P#DBX0.0 (0 + Bereichskennung "DB"), da schadet das Addieren des AR2 nicht.

Pointer auf eine FB-(Multi-)Instanzvariable erstellen:
Code:
//*** FB Multiinstanz ***
//Pointer auf IN-Parameter Input_1 erstellen
      L     P##Input_1                  // relative Adresse #Input_1 in dieser Instanz (Kennung DI)
      TAR2                              // Offset dieser Multiinstanz (Kennung DB)
      UD    DW#16#FFFFFF                // Bereichskennung (DB) ausblenden
      +D
      LAR1                              // AR1: absolute Adresse #Input_1 im IDB (Kennung DI)

//funktioniert auch so 'rum
      TAR2                              // Offset dieser Multiinstanz (Kennung DB)
      UD    DW#16#FFFFFF                // Bereichskennung (DB) ausblenden
      L     P##Input_1                  // relative Adresse #Input_1 in dieser Instanz (Kennung DI)
      +D
      LAR1                              // AR1: absolute Adresse #Input_1 im IDB (Kennung DI)


Achtung!
Wenn in multiinstanzfähigen FB das AR2-Register verändert wird, dann kann bis zur Wiederherstellung des AR2 nicht auf Instanzvariablen zugegriffen werden! Der AWL-Compiler geht davon aus, daß in AR2 der Instanzoffset steht und generiert unsichtbar bei jedem Zugriff auf Instanzvariablen eine Addition des Offsets aus AR2.

In allen FB darf außerdem das DI-Register nicht verändert werden, wenn man auf Instanzdaten zugreifen will.
Ab dem Moment, wo man AR2 oder das DI-Register verändert hat, kann man nicht mehr auf die Instanzdaten (IN/OUT/IN_OUT/STAT) zugreifen! Solange, bis man AR2 und DI wiederhergestellt hat.
Falls das Verändern von AR2 oder DI nötig ist: AR2 und DI und ggf. Instanzdaten vorher in TEMP kopieren und ggf. nachher wieder zurück.


Beim Erstellen von Pointern auf TEMP oder auf globalen Speicher muß kein Instanz-Versatz addiert werden.


Hier ein Beispiel zum Umkopieren von ANY-Parametern von IN/OUT/IN_OUT in TEMP in Multiinstanz-FB:
Code:
//Multiinstanz! AR2 Adressregister sichern
      TAR2  #tmp_DW_AR2_Save

//*** E_Any_farAdr kopieren *************************
//Pointer auf IN-Parameter E_Any_farAdr erstellen
      L     P##E_Any_farAdr             // relative Adresse #E_Any_farAdr in dieser Instanz (DI)
      TAR2                              // Offset dieser Multiinstanz (DB)
      UD    DW#16#FFFFFF                // Bereichskennung (DB) ausblenden
      +D
      LAR1                              // AR1: absolute Adresse #E_Any_farAdr im IDB (DI)

//Pointer auf TEMP-Variable tmp_Any_farAdr erstellen
      LAR2  P##tmp_Any_farAdr           // AR2: Adresse des TEMP-ANY


//ANY IN.E_Any_farAdr nach TEMP.tmp_Any_farAdr kopieren
//  (Variante mit Bereichsübergreifender, registerindirekter Adressierung)
      L     D [AR1,P#0.0]               // (S7-ID + Datentyp + Wiederholfaktor)
      T     D [AR2,P#0.0]
      L     W [AR1,P#4.0]               // (DB_Nr)
      T     W [AR2,P#4.0]
      L     D [AR1,P#6.0]               // (Bereichsadresse)
      T     D [AR2,P#6.0]


//*** E_Any_locAdr kopieren *************************
//Pointer auf IN-Parameter E_Any_locAdr erstellen
      L     P##E_Any_locAdr             // relative Adresse #E_Any_locAdr in dieser Instanz (DI)
      L     #tmp_DW_AR2_Save            // Offset dieser Multiinstanz (DB)
      UD    DW#16#FFFFFF                // Bereichskennung (DB) ausblenden
      +D
      LAR1                              // AR1: absolute Adresse #E_Any_locAdr im IDB (DI)

//Pointer auf TEMP-Variable tmp_Any_locAdr erstellen
      LAR2  P##tmp_Any_locAdr           // AR2: Adresse des TEMP-ANY


//ANY IN.E_Any_locAdr nach TEMP.tmp_Any_locAdr kopieren
//  (ALTERNATIVE Codevariante für besser verstehbar mit Bereichsinterner, registerindirekter Adressierung)
      L     DID [AR1,P#0.0]             // (S7-ID + Datentyp + Wiederholfaktor)
      T     LD [AR2,P#0.0]
      L     DIW [AR1,P#4.0]             // (DB_Nr)
      T     LW [AR2,P#4.0]
      L     DID [AR1,P#6.0]             // (Bereichsadresse)
      T     LD [AR2,P#6.0]


//*** Ende Parameter vorbereiten ********************
//VOR Zugriffen auf Instanzobjekte das AR2 unbedingt wiederherstellen!
      LAR2  #tmp_DW_AR2_Save            //AR2 Adressregister wiederherstellen


//*** GET mit ANY-Parametern aufrufen ***************
      CALL  #S_PLC_GET
       REQ   :=...
       ID    :=...
       NDR   :=...
       ERROR :=...
       STATUS:=...
       ADDR_1:=#tmp_Any_farAdr
       RD_1  :=#tmp_Any_locAdr


Der ANY, der beim FB-Aufruf übergeben wird, muß auf globalen Speicher oder FB-Instanz-Speicher zeigen (E, A, M, D). Er darf nicht auf TEMP zeigen, weil TEMP relativ im L-Stack des aktuellen Baustein adressiert wird. Die Adresse im TEMP des aufrufenden Bausteins würde als Adresse im TEMP des aufgerufenen (aktuellen) Bausteins interpretiert werden, was falsch ist.

Harald
 
Zurück
Oben