Der Compiler übergibt diese symbolische STRUCT-Variable als ANY mit dem Datentyp Byte an den Baustein. Und genau das kannst du dir zu nutze machen, wenn du deine Kopie extern in einem "Arbeits-DB" anlegst. Wichtig ist die Verwendung des UDT im DB und als Parametertyp im FC/FB.
Versuche mal folgende Schritte um zu setzen:
- Eingangsparameter mit der DB-Nr. als INT anlegen (das war gefordert)
- IN_OUT als UDTx anlegen (später Parameter mit UDTx aus DB versorgen)
- DB of UDTx anlegen (wie deine 20 anderen DBs)
- Im Baustein eine temporäre Variable vom Typ ANY anlegen, incl. AT-Sicht
- Zuweisen des IN_OUT aus (2.) auf den TEMP_ANY aus (4.) in SCL
- Überschreiben der DB-Nr. im TEMP_ANY mit (1.) mittels der AT-Sicht
- Kopieren der Daten mittels der SFC20
- etc.
Mit dem Punkt 5. wird praktisch der temporäre ANY vorbelegt. Es muss nur noch die DB-Nummer überschrieben werden. Am Ende sind das in SCL bis jetzt drei übersichtliche Programmzeilen.
Anschließend kannst du mit der Kopie über den IN_OUT im Baustein symbolisch lesend und schreibend arbeiten.
Am Ende muss vermutlich alles wieder zurück kopiert werden?
Gruß, Onkel
Hi Onkel

,
erst einmal Danke für die Erklärung!
Ich muss mir Deine Schritte einmal anschauen. Wobei der Eingangsparameter mit der DB-Nr. nicht zwangsläufig sein muss, warscheinlich würde diese [Nummer] zB per H-Funktion oder andersweitig innerhalb der Funktion selbst ausgelesen werden. Oder ich ermittle diese Nummer ausserhalb und rufe dann diesen FB mit den entsprechenden Parameten auf ...
Ob am Ende alles weider zurück kopiert werden muss, kann ich noch nicht sagen, aber denken einmal wennich noch eine Prüfung der Daten einbau wird dies ggf. möglich sein. Daher denke ich einmal "ja"
Hallo Boxy,
ich hatte Dir in
#7 empfohlen, den UDT zu übergeben, dann könntest Du ganz einfach sowas tun:
Code:
VAR_IN_OUT
ioType : UDT2101; [COLOR=#008080]//(der UDT wird als 6-Byte-POINTER übergeben)[/COLOR]
END_VAR
VAR_TEMP
iResult : INT;
END_VAR
VAR
Abbild : UDT2101; [COLOR=#008080]//lokale Arbeits-Kopie des UDT[/COLOR]
END_VAR
[COLOR=#008080]//einen kleinen UDT DWord-weise kopieren:[/COLOR]
Abbild := ioType;
[COLOR=#008080]//oder einen großen UDT besser mit BLKMOV kopieren:[/COLOR]
iResult := BLKMOV(SRCBLK := ioType, DSTBLK := Abbild);
Warum willst Du die DB-Nummer übergeben? (da erscheint die DB-Verwendung nicht in den Referenzdaten/Querverweisen)
Soll der FB an mehreren Programmstellen mit jeweils festen Aktualparametern aufgerufen werden?
Oder soll bei einem FB-Aufruf die DB-Nummer aus einer Variable kommen?
Beginnt der UDT in den DB immer an Adresse DBX0.0?
Eigentlich ist folgendes angedacht, der Anwender programmiert zB eine H-Funtion (zB NC-Programm) und übergibt somit eine Nummer, welchen Ablauf er starten möchte und dann wird zB mitteles M-Funkion dieser Ablauf gestartet.
In den Quell DBs werden diese Ablaufe über Masken usw. eingegeben / parametriert.
Durch den Start und der Funktionsnummer, wird nun dieser Ablauf welcher in dem spezifischen DB hinterliegt quasi ausgelesen und interpretiert.
Alternativ kann es ja auch sein, das man über eine Taste die Funktion bzw. einen spezifischen Ablauf starten möchte, dann wird ebenfalls eine Nummer entsprechend übergeben und den Ablauf gestartet. In weiterer Ausbaustufe kommt auch noch Vorabe von einer Automation usw. hinzu.
Daher denke ich, es könnte sein das dieser Baustein dann mehrfach aufgerufen werden könnte, aber ein zentrale Verwaltung wäre bestimmt auch möglich.
Der UDT bzw. die Quell DBs beginnen, wenn jeder Ablauf in einem eigen DB leigt immer eigentlich bei DBX0.0, da diese DBs vom Typ UDT dann sind.
Bei FB
- nur in VAR_IN_OUT kann man einen "getypten" Pointer erstellen/übergeben
- der UDT bzw. STRUCT wird als 6-Byte POINTER übergeben (nicht ANY)
- es wird nur die Anfangsadresse des UDT übergeben, die Länge und die Struktur kennt der Compiler von der Typ-Deklaration
- den Pointer kann man in SCL symbolisch in eine ANY-Variable kopieren, dabei übernimmt der Compiler die übergebene Anfangsadresse und ergänzt die ersten 4 Byte des ANY passend zur Typdeklaration des Übergabeparameters, z.B. P#DB120.DBX0.0 BYTE 100
- der IN_OUT-Parameter muß nicht beschaltet werden, bei Aufruf in SCL kann er ganz weggelassen werden
Das kann man sich für das basteln eines ANY zunutze machen, so daß der Compiler automatisch den ANY-"Header" (ID + Datentyp + Länge entsprechend UDT) ausfüllt und muß dann nur noch die Anfangsadresse (DB-Nummer + Anfangsadresse mit Bereichskennung) eintragen. Dabei reicht es allerdings nicht, nur die DB-Nummer einzutragen, man sollte auch sicherstellen daß die Bereichskennung "DB" ist und die Anfangsadresse des UDT in dem DB korrekt ist.
Code:
VAR_INPUT
inDBNo : INT;
END_VAR
VAR_IN_OUT
ioType : UDT2101; [COLOR=#008080]//(der UDT wird als 6-Byte-POINTER übergeben)[/COLOR]
END_VAR
VAR_TEMP
iResult : INT;
pAnyPointer : ANY;
sAnyPointer AT pAnyPointer : STRUCT [COLOR=#008080]//ANY Struktur:[/COLOR]
AID : BYTE; [COLOR=#008080]// ANY-ID B#16#10 für S7[/COLOR]
TYP : BYTE; [COLOR=#008080]// Datentyp[/COLOR]
ANZ : INT; [COLOR=#008080]// Wiederholfaktor[/COLOR]
DBN : INT; [COLOR=#008080]// DB-Nummer, falls Any auf DB[/COLOR]
PTR : DWORD; [COLOR=#008080]// Bereichsadresse mit Bereichskennung in MSB[/COLOR]
END_STRUCT;
END_VAR
VAR
Abbild : UDT2101; [COLOR=#008080]//lokale Arbeits-Kopie des UDT[/COLOR]
END_VAR
[COLOR=#008080]//ANY zu UDT2101 vorbelegen (P#<???> BYTE nnn)[/COLOR]
pAnyPointer := ioType; [COLOR=#008080]//POINTER to UDT2101[/COLOR]
[COLOR=#008080]//die übergebene DB-Nummer in den ANY eintragen:[/COLOR]
sAnyPointer.DBN := inDBNo; [COLOR=#008080]//DB-Nummer[/COLOR]
[COLOR=#008080]//der UDT beginnt immer an DBX0.0![/COLOR]
sAnyPointer.PTR := DW#16#84000000; [COLOR=#008080]//P#DBX0.0[/COLOR]
[COLOR=#008080]//UDT von <inDBNo>.DBX0.0 in lokales Abbild kopieren[/COLOR]
iResult := BLKMOV(SRCBLK := pAnyPointer, DSTBLK := Abbild);
Man kann auch einen ANY direkt auf die Adresse einer existierenden UDT-Variable setzen (und danach z.B. die DB-Nummern ändern):
Code:
pAnyPointer := "DB120".UDT2101Variable; [COLOR=#008080]//P#DB120.DBXy.0 BYTE xxx[/COLOR]
allerdings kann auf diese Art eine beliebige Variable angegeben werden - der Compiler prüft da nicht, ob die Variable vom gewünschten Datentyp (UDT2101) ist und die Längenangabe im ANY kann dann falsch sein!
Harald
Ich Danke auch Dir für die Erklärung

und werde mich mal damit vertiefen.
Denke mir ist nun klar geworden warum es einfacher wäre den UDT zu übergeben und daraufhin den DB einzuflicken

Aber flasch war die Übung mit dem "Händischen" erstellen des Any-Pointers nun auch nicht
Diese Tricks muss man halt kennen, was mir gerade aber nicht so recht lar ist, was übergebe ich da beim Aufruf?
Code:
VAR_IN_OUT
ioType : UDT2101; [COLOR=#008080]//(der UDT wird als 6-Byte-POINTER übergeben)[/COLOR]
END_VAR
Wird da ein DB parametriert beim Aufruf oder?
Danke ecuh für eueren Support
