Step 7 Any-Pointer über Bausteinschnittstelle

Mathias

Level-1
Beiträge
51
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen

Ich bin dabei eine Kommunikation von CPU zu CPU über die PN Schnittstelle zu realisieren. Das Senden und Empfangen werden über die Bausteine Put und Get gelösst. Die losgelöste Funktion von Schrieben und Empfangen funktioniert tadellos, nun bin ich dabei die Funktion in Bausteine als Multiinstanz zu packen, dabei ist folgendes Problem entstanden:

Die Funktion Put und Get benötigen je 2 ANY Pointer für die Variabeln ADDR_1 und RD_1, nun möchte ich diese Variabeln in der Multiinstanz als IN resp. als IN_OUT Variabel gestalten. Bsp. IN_OUT Variabel E_Pointer_Send als ANY und IN_OUT Variabel E_Pointer_Recive als ANY. Danach wollte ich die IN_Out Variablen dem Baustein PUT zuweisen mit #E_Pointer_Send, dies funktioniert nicht.

Wie bringe ich die ANY Variabeln auf die Schnittstelle der Multiinstanz?

Im Anhnag ein Bild, besten Dank für Eure mithilfe.

Grüsse Mathias

PUTGET.JPG
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ANY-Parameter von IN/IN_OUT in TEMP umkopieren in Multiinstanz-FB

ANY-Parameter können nicht von IN/IN_OUT/OUT zu Bausteinaufrufen durchgereicht werden. Sie müssen vorher in TEMP umkopiert werden. Diese Parameter-Kopien in TEMP können dann an den Bausteinaufruf geschrieben werden.

(Glücklicherweise ist es bei ANY in AWL auch nicht möglich, von außen direkt in die Instanz zuzugreifen, was bei einfachen Datentypen allerdings möglich wäre ala "L #PLC1.S_PLC_GET.STATUS")

Achtung:
Der Speicherbereich, der per ANY "durchgereicht" wird, muß ein globaler Speicherbereich sein (wie z.B. P#DB10.DBX20.0 BYTE 30). Er darf nicht in TEMP liegen, das funktioniert nicht weil TEMP nur Baustein-relativ adressierbar ist.

ANY-Parameter von IN/IN_OUT in TEMP umkopieren in Multiinstanz-FB:
Code:
//Multiinstanz! AR2 Adressregister sichern
      TAR2  #tmp_DW_AR2_Save

//*** E_Any_farAdr kopieren *************************
//Pointer auf IN_OUT-Parameter E_Any_farAdr erstellen
      LAR1  P##E_Any_farAdr             // relative Adresse #E_Any_farAdr in dieser Instanz (DI)
      TAR2                              // Offset dieser Multiinstanz (DB)
      +AR1                              // 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_OUT.E_Any_farAdr nach TEMP.tmp_Any_farAdr kopieren
      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_OUT-Parameter E_Any_locAdr erstellen
      LAR1  P##E_Any_locAdr             // relative Adresse #E_Any_locAdr in dieser Instanz (DI)
      L     #tmp_DW_AR2_Save            // Offset dieser Multiinstanz (DB)
      +AR1                              // 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_OUT.E_Any_locAdr nach TEMP.tmp_Any_locAdr kopieren
//ALTERNATIVE Codevariante für besser verstehbar
      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

EDIT:
Achtung! Dieses Programmbeispiel funktioniert nur bis IDB mit max Größe 4kB. Eine Korrektur siehe Beitrag #17

Harald
 
Zuletzt bearbeitet:
Guten Morgen,
ich hab den von Harald im Post #3 geschriebenen Code in meinem Projekt benutzt.

Der Code dient dazu in einem FB 801 einen Pointer für SendData und RecvData über die Bausteinschnittstelle zu übergeben. Dieser FB801 wird dann in einem Multiinstanz FB800 aufgerufen. Wenn ich den FB801 mit dem Code von Harald nur einmal aufrufe im FB800 dann funktioniert alles. Sobald ich aber den Baustein über 16 mal aufrufe geht die CPU in Stop.

Wenn ich im Fenster Baugruppenzustand (Diagnosepuffer) auf die Schaltfläche Baustein öffnen klicke öffnet sich der Baustein FB801 und springt zu Harald's Code.

Vielleicht hatte von euch schon jemand das Problem und kann mir weiterhelfen.

Vielen dank im Voraus.


FB800.jpgBaugruppenzustand - Stacks.pngBaugruppenzustand - Diagnosepuffer.png

Code:
//AR2 Adressregister sichern      TAR2  #tmp_DW_AR2_Save


//*** SendData kopieren *************************
//Pointer auf IN_OUT-Parameter SendData erstellen
      LAR1  P##SendData                 // relative Adresse #SendData in dieser Instanz (DI)
      TAR2                              // Offset dieser Multiinstanz (DB)
      +AR1                              // AR1: absolute Adresse #SendData im IDB (DI)


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


//ANY IN_OUT.SendData nach TEMP.tmp_Any_SendData kopieren
      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]






//*** RecvData kopieren *************************
//Pointer auf IN_OUT-Parameter RecvData erstellen
      LAR1  P##RecvData                 // relative Adresse #RecvData in dieser Instanz (DI)
      L     #tmp_DW_AR2_Save            // Offset dieser Multiinstanz (DB)
      +AR1                              // AR1: absolute Adresse #RecvData im IDB (DI)


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


//ANY IN_OUT.RecvData nach TEMP.tmp_Any_RecvData kopieren
//ALTERNATIVE Codevariante für besser verstehbar
      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
 
Zuletzt bearbeitet:
Danke schonmal für deine Antwort dtsclipper,
das hast du warscheinlich an dem AR1 Di erkannt da dies ein wenig zu hoch ist. Hättest du einen Lösungsvorschlag wie mann dem entgegen wirken kann.

Vielen Dank
 
Ähh - nein.

Die Info habe ich aus Deinem Diagnosebild, da steht Zugriffsfehler auf Instanz-DB mit der Zugriffsadresse 61718.

Das scheint mir zu hoch.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe trotzdem keine Ahnung wie ich den Fehler beseitigen kann. Auch wenn der Pointer über das Ende des DBs hinauszeigt was muss ich machen damit er dies nicht mehr macht. Und wieso tritt der Fehler erst bei mehreren Bausteinaufrufe auf. Ich such zwar schon die ganze Zeit im I-Net bei Siemens usw aber ich finde dort nix.


 
Mit dem Programm kopierst Du ja Pointeradressen, also Typ, Bereich und Länge.

Mein Verdacht tendiert dahin das irgendwo im Basisdaten-DB ein Zahlenfehler steckt.

Eine mögliche Testreihe ist den Haupt-FB800 immer nur um einen Aufruf zu verlängern bis es nicht mehr geht und dann dan letzten Aufruf ( der es dann ja zerschossen hat ) zu kontrollieren.
 
Das konnte ich schon feststellen. Wenn ich wie im obrigen Bild FB800

Zuerst hatte ich im FB800 den FB801 32 mal aufgerufen und die Bausteine über den EN Eingang einzeln Enabled. Bis zum 16 Baustein war kein Fehler aufgetreten. Wenn ich dann den Baustein 17 Enable bringt der mir den beschriebenen Fehler.

Danach hab ich alle Bausteine höher 17 (COM_CP2_ID01) aus dem FB800 und der Deklarationstabelle gelöscht. Der Fehler bestand immer noch.
Daraufhin hab ich alle Bausteine vor dem 17 (COM_CP2_ID01) gelöscht aber in der Deklarationstabelle die 16 belassen.
Der Fehler war immer noch da. Erst wenn ich den Baustein 17 (COM_CP2_ID01) Disable läuft die CPU ohne Fehler an.

Dann hat das doch bestimmt mit den Adressen zu tun. Komischerweise immer wenn die Adresse höher 4000 ist.


Deklarationstabelle.jpg
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
[COLOR="#FF0000"][B]//[/B]AR2 Adressregister sichern      TAR2  #tmp_DW_AR2_Save[/COLOR]
[/QUOTE]
Steht das wirklich so in Deinem Programm oder ist der Fehler beim Kopieren ins Forum passiert?
Also ist das TAR2... in Deinem Programm tatsächlich auskommentiert?

Weil AR2 in Multiinstanz-FB schon benutzt wird um den Offset dieser Instanz im Mutter-IDB anzugeben, darf AR2 nicht verändert werden bzw. wenn man es verändert, dann muß der Inhalt gesichert und vor dem Zugriff auf Instanz-Variablen wieder hergestellt werden.
In Deinem Programm wird womöglich AR2 nicht gesichert aber später mit einem zufälligen Wert aus dem TEMP "wiederhergestellt".
#tmp_DW_AR2_Save muß ein DWORD in TEMP sein. Es darf nicht in STAT liegen, weil es dann nach dem Ändern von AR2 nicht "wiedergefunden" wird.

Harald
 
Hallo Harald das war ein Fehler beim Kopieren ins Forum ist mir aber selbst nicht aufgefallen.
So wie ich das verstehe sollte das mit deinem Code funktionieren und diese Problem nicht auftreten.
Hab dir nochmal ein Bild vom Baustein angehängt.

Vielen Dank


FB801 NW7.jpg
 
Wenn ich im Fenster Baugruppenzustand (Diagnosepuffer) auf die Schaltfläche Baustein öffnen klicke öffnet sich der Baustein FB801 und springt zu Harald's Code.
Zu welcher Programmzeile genau?
An der Unterbrechungsstelle hat AR1 einen völlig falschen Wert.
Veränderst Du das AR2 schon vor diesem Netzwerk 7?

Hast Du PLCSIM?
Ich empfehle, nur die 20. Instanz aufzurufen und mit PLCSIM die Werte in AR1 zu kontrollieren. Dabei zunächst die Kopierbefehle überspringen und dann nach und nach wieder aktivieren.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich Simuliere es momentan mit PLCSim. Aber der Fehler ist beim Kollegen auf der Baustelle aufgetreten.
Das AR2 wir meines Wissens nicht vorher verändert.

Wieso mit der 20. Instanz anfangen ? Das versteh ich noch nicht ganz.

Wenn ich auf Baustein öffnen klicke geht er zur markierten Zeile siehe Bild.

Danke Harald.


FB801 NW7 Fehlerzeile.png
 
Zuletzt bearbeitet:
Korrektur wg. +AR1

Ich habe den Fehler gefunden: :oops:
Die Operation +AR1 addiert AKKU1-L als vorzeichenbehaftete 16-Bit-Zahl - addiert oder subtrahiert also einen 15-Bit-Offset!
Die Version in Beitrag #3 funktioniert nur mit IDB bis max. 4KByte.

Hilfe zu AWL - +AR1 Addiere AKKU 1 zum Adreßregister 1 schrieb:
+AR1 (Addiere zu AR1) addiert einen Versatz, der entweder in der Anweisung oder in AKKU1-L angegeben wird, zum Inhalt von AR1. Die Ganzzahl (16 Bit) wird zunächst vorzeichenrichtig auf 24 Bit erweitert und danach zu den niederwertigsten 24 Bit von AR1 (Teil der relativen Adresse in AR1) addiert. Der Teil der Bereichskennung in AR1 (Bits 24, 25 und 26) wird nicht verändert.

+AR1: Die Ganzzahl (16 Bit), die zum Inhalt von AR1 addiert werden soll, wird durch den Wert in AKKU1-L angegeben. Zulässig sind Werte von -32768 bis +32767.


Hier die korrigierte Version:
ANY-Parameter von IN/IN_OUT in TEMP umkopieren 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
[COLOR="#0000CD"]      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)[/COLOR]

//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
      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
[COLOR="#0000CD"]      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)[/COLOR]

//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
      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

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Guten Morgen,
ein großes Lob an Harald und Thomas für die super Hilfe. Ich werde den Code jetzt in meinem Programm aktualisieren und euch Rückmeldung geben ob es bei mir funktioniert.
 
Zurück
Oben