Step 7 SCL und Multiinstanz

Grimsey

Level-2
Beiträge
543
Reaktionspunkte
32
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich habe trotz Suche noch nicht die richtige Antwort auf meine Frage gefunden, daher erstelle ich hier mal ein neues Thema.
Ich würde gerne in SCL einen FB erstellen und diesen dann als Multi-Instanz in anderen FBs benutzen.
Wenn ich einen FB in KOP/AWL schreibe, dann muss ich innerhalb des FB das Adressregister retten und am Ende wieder herstellen damit der Baustein Multiinstanzfähig ist.

Ist das bei SCL auch notwendig? Wenn ja, wie muss ich das handhaben?
 
Sofern nötig erledigt das der SCL-Kompiler, imho hast du auf das AR in SCL auch gar keinen Zugriff.

Mfg
Manuel
 
Hallo nochmal,

ich muss das Thema hier noch einmal aufgreifen da ich gestern ein recht merkwürdiges Verhalten festgestellt habe und mir das nicht erklären kann bzw. ich den Fehler suche.
Ich habe, wie bereits oben erwähnt, einen FB in SCL geschrieben (Baustein A) der wiederum als Multiinstanz in einem anderen, von mir in SCL geschriebenen Baustein (Baustein B), aufgerufen werden soll.
Dazu habe ich den Baustein A in Baustein B als Multiiinstanz definiert.
Beim Testen bekomme ich nun einen Bereichslängenfehler beim Aufruf von Baustein B. Die Diagnose verweist dabei auf den Aufruf von Baustein A in Baustein B.
Baustein A habe ich einzeln für sich getestet und da funktioniert alles wie es soll.

Ich habe mir dann einmal den AWL-Code von Baustein B angeschaut und dort wird der globale Baustein A mit "UC" aufgerufen (siehe Screenshots).

Kann das denn überhaupt funktionieren??? In diesem Fall würden doch für Baustein A keine Lokaldaten mehr zur Verfügung stehen...

Definition MultiInstanz.pngAufruf MultiInstanz.pngAWL-Quelle.jpg
 
Sollte funktionieren...

Im Prinzip sind alle Aufrufe UC-Aufrufe. Der Call-Befehl ist eigentlich ein Makro, Im MC7-Code wird der Call so umgesetzt wie im SCL-Kompilat dargestellt.

Wo der Fehler jetzt liegt kann ich aber nicht sagen.
 
Ich verwende sehr viel Multiinstanzen in Verbindung mit SCL.

Probier mal den Bausteinkonsistenz zu überprüfen.

edit:
dtsclipper schrieb:
Kannst Du den Programm-Fehler OB [OB121] löschen und es noch mal probieren?
Dann sollte in der STACK-Anzeige die genaue Adresse stehen
Wenn das Bausteinkonsistenz Überprüfung gevolgt von ein erneuten Laden nichts gibts, dann dieses probieren.
 
Zuletzt bearbeitet:
Ich habe nochmals die Konsistenz geprüft und das gesamte Programm neu übersetzen lassen.
Der Fehler tritt nach wie vor auf.

Also OB121 gelöscht und zur Fehlerstelle gewechselt.

Hier wird mir dann ein anderer Baustein angezeigt, der mit aus den LagerDBs anhand einer Fachnummer, die Fach- und PalettenDaten ausgibt. Dieser Baustein wurde aber auch separat für sich getestet und funktioniert. Auch funktioniert er an anderen Stellen, wo er mehrfach aufgerufen wird. Ich vermute das das Problem in der Konstellation der Aufrufe besteht, ohne das ich sagen könnte wo genau.

SCL Multiinstanz Fehlerstelle.jpg
 
Der Aufruf von dem FC_FachAuslesen sieht wie folgt aus:
Aufruf FC106 in FB_SucheAlternative.png

zum Zeitpunkt, an dem der Fehler auftritt steht dort eine Fachnummer....teste ich den FC für sich allein im OB mit dieser Fachnummer, gibt er das korrekte Ergebnis zurück.
Daher wundert es mich, dass es innerhalb des FBs da irgendein Problem gibt.
 
Bitte auch dies posten:

Der FC ist ein globaler FC, hier der Code dazu:

Code:
FUNCTION "FC_FachAuslesen" : VOIDTITLE =FachDaten und PalettenDaten auslesen
//dieser Baustein ermittelt der übgergebenen Fachnummer die Facheigenschaften und 
//die PalettenDaten des Fachs und gibt diese an die Eingangs-AnyPointer zurück
AUTHOR : ROP
VERSION : 0.1




VAR_INPUT
  iFachnummer : DINT ;    //Fachnummer
  iZielPalettenDaten : ANY ;    
  iZielFachDaten : ANY ;    
END_VAR

VAR_TEMP
  tPointerPalettenDaten : ANY ;    //Pointer für Palettendaten
  tPointerFachDaten : ANY ;    //Pointer für Facheigenschaften
  tZielPattenDaten : ANY ;    
  tZielFachDaten : ANY ;    
  retval : INT ;    

  tSYS : STRUCT     //Systemvariablen
   AR1 : DWORD ;    //Adressregister sichern
   AR2 : DWORD ;    //Adressregister sichern
   INSTANZOFS : DWORD ;    //Instanzdatenoffset sichern
  END_STRUCT ; 
   
  FachDaten : STRUCT     
   PalettenDaten : "UDT_Palette";    
   Facheigenschaften : "UDT_Facheigenschaften";    
  END_STRUCT ;   
 
  tDBNrRegal : INT ;    //Nr des DBs des Quellfachs
  tOffsetFach : DINT ;    
  tOffsetEigenschaften : DINT ;    
  tGasse : INT ;    
  tRegal : INT ;    
  tX : INT ;    
  tY : INT ;    
  tZ : INT ;    
  tZwischenergebnis : INT ;    
  tWerteGueltig : BOOL ;    
  tEinsmerker : BOOL ;    
END_VAR

BEGIN

NETWORK
TITLE ==== System save === 
// 
      TAR1  #tSYS.AR1; // Sichern AR1
      TAR2  #tSYS.AR2; // Sichern AR2


      TAR2  ; 
      UD    DW#16#FFFFFF; // Bereichskennung ausmaskieren
      T     #tSYS.INSTANZOFS; // Sichern Instanzdatenanfang

NETWORK
TITLE =


      UN    #tEinsmerker; 
      S     #tEinsmerker; 

NETWORK
TITLE =Fachnummer in Koordinaten zerlegen


      CALL "FC_KonvertFachnummer" (
           iFachnummer              := #iFachnummer,
           oRegalnummer             := #tRegal,
           oX                       := #tX,
           oY                       := #tY,
           oZ                       := #tZ);
      NOP   0; 

NETWORK
TITLE =Koordinaten auf gültigen Wertebereich prüfen
//Regal >= 1 <= 14
//X     >= 1 <= 61
//Y     >= 1 <= 12
//Z     >= 1 <= 2
      U     #tEinsmerker; 
      =     L    161.0; 
      U     L    161.0; 
      U(    ; 
      L     #tRegal; 
      L     1; 
      >=I   ; 
      )     ; 
      U(    ; 
      L     #tRegal; 
      L     14; 
      <=I   ; 
      )     ; 
      =     #tWerteGueltig; 
      U     L    161.0; 
      U     #tWerteGueltig; 
      U(    ; 
      L     #tX; 
      L     1; 
      >=I   ; 
      )     ; 
      U(    ; 
      L     #tX; 
      L     61; 
      <=I   ; 
      )     ; 
      =     #tWerteGueltig; 
      U     L    161.0; 
      U     #tWerteGueltig; 
      U(    ; 
      L     #tY; 
      L     1; 
      >=I   ; 
      )     ; 
      U(    ; 
      L     #tY; 
      L     12; 
      <=I   ; 
      )     ; 
      =     #tWerteGueltig; 
      U     L    161.0; 
      U     #tWerteGueltig; 
      U(    ; 
      L     #tZ; 
      L     1; 
      >=I   ; 
      )     ; 
      U(    ; 
      L     #tZ; 
      L     2; 
      <=I   ; 
      )     ; 
      =     #tWerteGueltig; 

NETWORK
TITLE =Bausteinende wenn Werte nicht gültig


      UN    #tWerteGueltig; 
      SPB   ende; 

NETWORK
TITLE =Quell-Gasse aus Regalnummer ermitteln


      L     #tRegal; 
      +     1; 
      L     2; 
      /I    ; 
      T     #tGasse; 


NETWORK
TITLE =DB-Nr berechnen/festlegen
//tDBNrRegal = 100 + (tGasse*10) + ((tRegal / tGasse) - 1)*2 + tZ
      L     #tRegal; 
      L     #tGasse; 
      /I    ; 
      +     -1; 
      L     2; 
      *I    ; 
      T     #tZwischenergebnis; // Regaloffset 0 oder 2


      L     #tGasse; // 10er Schritte DB-Nr.
      L     10; 
      *I    ; 
      +     100; // Grundoffset DB-Nr.
      L     #tZwischenergebnis; 
      +I    ; 
      L     #tZ; // Fachtiefe 1 oder 2
      +I    ; 
      T     #tDBNrRegal; 

NETWORK
TITLE =Offset (Fach) innerhalb vom Lager-DB berechnen
//Offset pro X-Koordinate = 1008 Byte
//Offset pro Y-Koordnate = 84 Byte
//
//Offset = [(iX-1)*1008] + [(iY-1)*84]
      L     #tX; 
      L     1; 
      -I    ; 
      ITD   ; 
      L     L#1008; 
      *D    ; 
      T     #tOffsetFach; 


      L     #tY; 
      L     1; 
      -I    ; 
      ITD   ; 
      L     L#84; 
      *D    ; 
      L     #tOffsetFach; 
      +D    ; 
      T     #tOffsetFach; 

NETWORK
TITLE =Anypointer bilden


NETWORK
TITLE =Any-Pointer PalettenDaten


      L     B#16#10; // ID (S7)
      T     LB     0; 


      L     B#16#2; // Byte (siehe Hilfe "Format des Parametertyps ANY")
      T     LB     1; 


      L     80; // Länge: 80 byte
      T     LW     2; 


      L     #tDBNrRegal; 
      T     LW     4; // Quell-DB


      L     #tOffsetFach; // ab Adresse 0.0 (festlegen!)
      SLD   3; // 2*8 (nicht ändern!)            
      L     P#DBX 0.0; // Datenbaustein-Kennung (nicht ändern!)
      OD    ; 
      T     LD     6; 

NETWORK
TITLE =Any-Pointer Facheigenschaften


      L     B#16#10; // ID (S7)
      T     LB    10; 


      L     B#16#2; // Byte (siehe Hilfe "Format des Parametertyps ANY")
      T     LB    11; 


      L     4; // Länge: 4 byte
      T     LW    12; 


      L     #tDBNrRegal; 
      T     LW    14; // Ziel-DB: = DBNrRegal


      L     #tOffsetFach; // ab Adresse 0.0  (=variabel)
      L     L#80; 
      +D    ; 
      T     #tOffsetEigenschaften; 


      L     #tOffsetEigenschaften; 
      SLD   3; // *8 (nicht ändern!)            
      L     P#DBX 0.0; // Datenbaustein-Kennung (nicht ändern!)
      OD    ; 
      T     LD    16; 

NETWORK
TITLE =AnyPointer ZielPalettenDaten


      L     P##iZielPalettenDaten; 
      TAR2  ; 
      UD    DW#16#FFFFFF; 
      +D    ; 
      LAR1  ; 
      L     D [AR1,P#0.0]; 
      T     LD    20; 
      L     D [AR1,P#4.0]; 
      T     LD    24; 
      L     W [AR1,P#8.0]; 
      T     LW    28; 

NETWORK
TITLE =AnyPointer ZielFachDaten


      L     P##iZielFachDaten; 
      TAR2  ; 
      UD    DW#16#FFFFFF; 
      +D    ; 
      LAR1  ; 
      L     D [AR1,P#0.0]; 
      T     LD    30; 
      L     D [AR1,P#4.0]; 
      T     LD    34; 
      L     W [AR1,P#8.0]; 
      T     LW    38; 

NETWORK
TITLE =Daten ausgeben

NETWORK
TITLE =PalettenDaten


      CALL "BLKMOV" (
           SRCBLK                   := #tPointerPalettenDaten,
           RET_VAL                  := #retval,
           DSTBLK                   := #tZielPattenDaten);
      NOP   0; 

NETWORK
TITLE =Facheigenschaften


      CALL "BLKMOV" (
           SRCBLK                   := #tPointerFachDaten,
           RET_VAL                  := #retval,
           DSTBLK                   := #tZielFachDaten);
      NOP   0; 

NETWORK
TITLE ==== System recovery === 
// 
ende: LAR1  #tSYS.AR1; // Load AR1
      LAR2  #tSYS.AR2; // Load AR2


      SET   ; 
      SAVE  ; 
      CLR   ; 
END_FUNCTION
 
Zuletzt bearbeitet:
Oha, ein Multiinstanz-FC... :cool:

Kann es sein, daß dieser Schweine-Baustein vor langer langer Zeit von irgendjemandem zusammengeschrieben wurde und heute niemand mehr weiß, wie er funktionieren sollte? Und später kam irgendein Genie auf die Idee, den ursprünglichen FB einfach in FC umzubenennen, weil man da so schön den lästigen Instanz-DB weglassen kann?

Ist Dir bewußt, daß der FC in dem "heimlichen" Übergabeparameter AR2 bestimmte Werte erwartet? Wie stellst Du gezielt sicher, daß in AR2 ein sinnvoller/richtiger Wert drinsteht, besonders wenn Du den FC statt aus einem FB aus dem OB1 aufrufst?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Baustein ist nicht alt und auch nicht vor langer langer Zeit geschrieben.
Und ein Multiinstanz-FC geht doch gar nicht anzulegen ;) Und einen FC kann man doch mehrmals aufrufen...

Ich habe jetzt jedenfalls den kompletten Aufruf des Bausteins "FB_SucheAlternative" aus dem übergeordneten Baustein herausgenommen, also den Multiinstanzaufruf entfernt, und damit funktioniert es jetzt korrekt.
 
..Ich habe jetzt jedenfalls den kompletten Aufruf des Bausteins "FB_SucheAlternative" aus dem übergeordneten Baustein herausgenommen, also den Multiinstanzaufruf entfernt, und damit funktioniert es jetzt korrekt.
Und damit gibst du dich zufrieden?

...Und ein Multiinstanz-FC geht doch gar nicht anzulegen ...
Nein, aber du hast so etwas wie einen Anti-Multiinstanz-FC erfunden :ROFLMAO:. Was machst du denn mit dem AR2 in deiner FC?
 
Nein, aber du hast so etwas wie einen Anti-Multiinstanz-FC erfunden :ROFLMAO:. Was machst du denn mit dem AR2 in deiner FC?

na, erfunden hat er es nicht - ist halt zufällig drauf gestoßen.
es gibt versierte programmierer, die das zur jahrtausendwende sehr erfolgreich in unterschiedlichen maschinen verteilt haben. einen promovierten dieser art kenne ich.
 
Zurück
Oben