DB Nr. an FC übergeben

1. Möglichkeit:
IN-Parameter vom Typ INT, z.B. #INDB
dann von IN-Parameter auf Temp-Parameter umwandeln
Code:
L #INDB
T #MEINDB
 
AUF DB[#MEINDB]
2. Möglichkeit:
IN-Parameter vom TYP BLOCK_DB deklarieren

Gruß Approx
 
Zuviel Werbung?
-> Hier kostenlos registrieren
IN-Parameter vom TYP BLOCK_DB deklarieren

Es sollte nur die 2. Möglichkeit von Approx benutzt werden, diese erzeugt aussagekräftige Referenzdaten.
Code:
VAR_INPUT
  DBNr : BLOCK_DB ;
END_VAR

AUF #DBNr
Bei der 1. Möglichkeit (AUF DB[#MEINDB]) muß für eine Programm-Analyse manuell jeder Bausteinaufruf angesehen
werden! Diese Möglichkeit ist eigentlich nur nötig, wenn die DB-Nummer vor dem Aufruf indirekt ermittelt wird.

Gruß
Harald
 
Ich denke eher, es sollte nur die 1. Möglichkeit benutzt werden.

Bei der 2. Möglichkeit kann man den FC nicht mehr aus einem übergeordneten FC heraus aufrufen und den DB weiterleiten, egal wie die DB-Nr. vorliegt. Geht es doch irgendwie? -> Bitte um Aufklärung ;)

Wie das mit den Referenzdaten ist, weiß ich nicht. Ist es irgendwie möglich, mehr als die Tatsache, dass DB X übergeben wurde, nachzuvollziehen? Werden AUF-Befehle nicht mit erfasst?

Die Parameterübergabe geht am einfachsten so:
AUF "db_whatever";
L DBNO;
T #tmp_int;
CALL ... := tmp_int, ...

Auch hier kenne ich keine bessere Möglichkeit, gibt es eine? Bei Direktübergabe würde der DB-Name nicht mehr im Code stehen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Warum DB-Übergabe als BLOCK_DB?

1. Möglichkeit:
IN-Parameter vom Typ INT, z.B. #INDB
dann von IN-Parameter auf Temp-Parameter umwandeln
Code:
L #INDB
T #MEINDB
 
AUF DB[#MEINDB]
2. Möglichkeit:
IN-Parameter vom TYP BLOCK_DB deklarieren
Ich denke eher, es sollte nur die 1. Möglichkeit benutzt werden.

Bei der 2. Möglichkeit kann man den FC nicht mehr aus einem übergeordneten FC heraus aufrufen und den DB weiterleiten, egal wie die DB-Nr. vorliegt. Geht es doch irgendwie? -> Bitte um Aufklärung ;)
An einen aufgerufenen FB kann man einen IN.BLOCK_DB weitergeben (aus FB und FC), an einen FC geht es nicht.
Wenn man also einen BLOCK_DB durchleiten will, muß man eben den aufgerufenen Baustein als FB schreiben.
Braucht man die DBNr-Weitergabe aber tatsächlich praktisch? Ich habe es noch nicht gebraucht.

An einen FB werden die Parameter über dessen Instanz-DB übergeben, an einen FC über den L-Stack (vorherige Lokaldaten).
Da hat Siemens wohl das entsprechende MC7-Macro für FC "vergessen". Eigentlich spricht nichts dagegen.

Übrigens witzig zu sehen, wie inkonsequent das S7-AWL ist:
Code:
VAR_INPUT
  DBNr : BLOCK_DB ;
  Offset : INT ;
END_VAR

[COLOR="Red"]      L     #DBNr       // Anweisung nicht erlaubt für BLOCK_DB-Befehls-Operanden
      LAR1  P##DBNr     // Symbol DBNr nicht gefunden oder nicht erlaubt in Anweisung mit Adress-Operator P#[/COLOR]

      L     P##DBNr     // das ist erlaubt
      LAR1              // ergibt aber einen sinnlosen Pointer ohne Bereichskennung


      L     #Offset     // das ist erlaubt - muß ja auch
[COLOR="red"]      LAR1  P##Offset   // Symbol Offset nicht gefunden oder nicht erlaubt in Anweisung mit Adress-Operator P#[/COLOR]

      L     P##Offset   // das ist erlaubt
      LAR1              // ergibt einen Pointer auf die vorherigen Lokaldaten


Wie das mit den Referenzdaten ist, weiß ich nicht. Ist es irgendwie möglich, mehr als die Tatsache, dass DB X
übergeben wurde, nachzuvollziehen? Werden AUF-Befehle nicht mit erfasst?
Da gibt es doch so clevere Programmierer, die machen jeglichen Datentransfer zwischen DB mit so einem Baustein:
Code:
VAR_INPUT
  Source_DB : INT ;     // müsste korrekterweise WORD sein, 
  Source_Offset : INT ; // aber INT läßt sich viel bequemer
  Dest_DB : INT ;       // mit dezimalen Aktualwerten versorgen
  Dest_Offset : INT ;   // (da muß der Programmierer nicht in Hex denken)
  Len : INT ;
END_VAR

      L     #Source_DB
      T     MW   200    // sogar zu faul, ein TEMP-WORD anzulegen!
      AUF   DB [MW 200]

      L     #Dest_DB
      T     MW   200
      AUF   DI [MW 200]

// indirekte BYTE-Kopierschleife (möglichst uneffizient geproggt)
//    ...
Die beiden AUF-Befehle tauchen in den Referenzdaten NICHT auf!!!
Die Benutzung der DB als Aktualwerte beim CALL taucht erst recht nicht auf (sind ja als INT deklariert).

Es hilft nur, auf Verdacht eine AWL-Quelle mit allen FB+FC+OB zu erzeugen und nach "AUF~~~D" zu suchen (~ ist Leerzeichen).
Damit hat man zunächst die "bösen" Bausteine ertappt.
Nun noch Viel Spaß beim ansehen ALLER Aufrufe dieser Bausteine und aufschreiben, welche DB dabei benutzt werden!

Wenn schon sowas fieses, dann sollte es wenigstens so sein:
Code:
VAR_INPUT
  Source_DB : BLOCK_DB ;
  Source_Offset : INT ;
  Dest_DB : BLOCK_DB ;
  Dest_Offset : INT ;
  Len : INT ;
END_VAR

      AUF   #Dest_DB
      TDB
      AUF   #Source_DB
// ( DBNO=#Source_DB / DINO=#Dest_DB )

// indirekte BYTE-Kopierschleife
//    ...
Nun steht die Benutzung der DB für jeden Baustein-Aufruf in den Referenzdaten, z.B. so: :)
DB 1 | FC11 | R | AWL | NW 1 Anw 1 /CALL
DB 2 | FC11 | R | AWL | NW 1 Anw 1 /CALL
DB 3 | FC11 | R | AWL | NW 2 Anw 1 /CALL
DB 3 | FC11 | R | AWL | NW 2 Anw 1 /CALL

Die eigentlichen AUF-Befehle im Baustein stehen aber trotzdem nicht in den Referenzdaten. :(
Man kann nun aber wenigstens ahnen, woher die Daten im DB kommen.


Die Parameterübergabe geht am einfachsten so:
AUF "db_whatever";
L DBNO;
T #tmp_int;
CALL ... := tmp_int, ...

Auch hier kenne ich keine bessere Möglichkeit, gibt es eine? Bei Direktübergabe würde der DB-Name nicht mehr im Code stehen.
Na, wenigstens schreibst Du die DB-Nummer als INT nicht direkt in den CALL ...

Bei BLOCK_DB als Formalparameter steht ganz sicher der DB-Name im Code, ggf. sogar symbolisch. Das geht einfach so:
Code:
      CALL  FC12
       DBNr :="db_whatever"     //z.B. DB123 eintippen
Und steht in den Referenzdaten als: DB 123 (db_whatever) | FC11 | R | AWL | NW 1 Anw 1 /CALL

Also, ich bin der Meinung, daß man wegen den Referenzdaten eine DB-Nummer immer als BLOCK_DB übergeben soll.
Und nur ausnahmsweise - wenn es wirklich zwingende Gründe gibt - die DB-Nummer als INT/WORD übergeben.

Gruß
Harald
 
Ich hatte das Problem, als ich einen gegebenen FC mit sehr vielen Parametern incl. BLOCK_DB aus einem FB aufrufen wollte, die DB-Nr. war als Variable vorgegeben.

Meine erste "Lösung" war, den Aufruf für alle denkbaren DB-Werte zu kopieren. :icon_redface:

Ich denke, das Problem bei der Übergabe ist, dass für jeden Parameter ein Pointer im Code selbst steht: (in einer Art Pseudoassempler)
...Code...
jmp to_call;
DATA P#...
DATA P#...
to_call: CALL ...
...Code...

Ein BLOCK_XX steht direkt drin, nicht als Pointer, dadurch ist er notwendigerweise konstant.

POINTER sind nicht konstant, man kann wahrscheinlich auch Pointer weiterleiten, etc.
Dadurch braucht man keine db_nr: INT; addr: DINT; als Parameter, ich bevorzuge POINTER oder gar VAR_IN_OUT xxx: udt_yyy;

Bei POINTERN ist nur innerhalb der FC hässlicher Code, der Aufruf kann ok sein. Bei VAR_IN_OUT UDTs ist der Code überall lesbar. Aber bei INT/DINT-Kombis für Pointer ist der Aufruf *und* der Code im FC schwierig.


Das AUF #variable nicht in den Referenzdaten ist, wundert mich nicht. Schließlich wurde die Variable irgendwann mal versorgt, hoffentlich mit einem DB, dann kann das in die Referenzdaten. Jetzt muss ich nur noch prüfen, ob AUF "konstanter_db" in die Referenzdaten kommt ...
 
Aufgabenstellung sind z.B. FIFO Register für Auftragsdaten. Die Auftragsdaten (Strukturen mit Werten und Srings ) kommen von einem übergeordneten System und werden in FIFO Register eingelagert.

Die FIFO Funtionalitäten sind in einem parametriebarem FB hinterlegt.

Die Datenstruktur bleibt die Gleiche, nur brauche. ich die Funktionalität mehrfach und die FiFOs liegen in verschiedenen DBs für verschiedene Linien.

Der DB Name soll an de FB übergeben werden.

Wurde vor 20 Jahren schon mit einer S7 400 realisiert. Dort hält mit Befehlen wie Auf DB, Auf DI, Pointern und Adressregistern.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... und was ist die FIFO-Struktur genau ?
Aber da du da gerade von Struktur schreibst ... wie wäre es wenn die Daten in den DB's als genau eben solche angelegt werden und du deinem Baustein dann die Struktur-Definition übergibst ?
Mit Pointern oder Ähnlichem würde ich heute nicht mehr rummachen - es gibt eigentlich so gut wie immer einen Weg (wenn man denn will) etwas so zu machen, dass man vollen Zugriff auf die Symbolik behält ...
 
Die Datenstruktur bleibt die Gleiche, nur brauche. ich die Funktionalität mehrfach und die FiFOs liegen in verschiedenen DBs für verschiedene Linien.

Der DB Name soll an de FB übergeben werden.
Das könntest du beispielsweise per "Array[0..X] of DB_ANY" realisieren.
Funktioniert übrigens auch mit Technologieobjekten siehe hier.

Wie aber läuft die Übergabe von optimierten variablen DBs an FCs und FBs für die 1500er Steuerungen.
- Variant / Ref_TO
- DB_ANY
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Damit hast du dann aber keinen symbolischen Zugang zu deinem DB-Inhalt (oder du müßtest ihn in deinem Baustein dann erst wieder um-casten was Rechenzeit benötigt) ... was spricht für dich gegen meinen Vorschlag ?
 
Damit hast du dann aber keinen symbolischen Zugang zu deinem DB-Inhalt...
1706776092172.png
Bei "DB_ANY" musst du lediglich sicherstellen, dass die "DB_ANY"-Variable (Referenz) an einen Unter-Baustein übergeben wird, der den tatsächlich übergebenen Typ als Aktualparameter erwartet.
Ab da hast du dann deinen symbolischen Zugang zum Techobjekt/DB.
Ref_TO mit DB_ANY geht aber auch.

Bei Variant kannst du nach einer Typprüfung "TypeOfElement()" per Ref_TO symbolisch zugreifen.
Hier musst du ebenfalls nicht per "MoveBlockVariant" das Ding durch die Gegend kopieren.


...was spricht für dich gegen meinen Vorschlag?
Was den FIFO angeht stimme ich dir ebenfalls zu.
Aber man( n ) kann ja nicht nur mit FIFOs spaß haben ;)
 
OKay ... Danke für den Hinweis ... Das man auf diese Weise mit Referenzen arbeiten kann hatte ich tatsächlich nicht auf dem Schrim ...
Ist jetzt, wenn man mit unterschiedlichen Typen in der Übergabe arbeitet, in der Umsetzung aber auch nicht ohne.
 
Zurück
Oben