UDT in FB durchreichen

thomasgull

Level-2
Beiträge
166
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo ich habe eine Frage:

Ich habe einen UDT ( UDT3) der noch einen UDT ( UDT 4) enthält.

Nun die Frage, ich brauche den ganzen UDT (UDT 3) im FB ( FB 5) und im FC ( FC 6 ) der in dem FB ( FB 5 ) aufgerufen wird nur den UDT im UDT ( UDT 4 ).

Nun kann ich im FB ( FB 5 ) den UDT ( UDT 4) durchreichen?


Thomas
 

Anhänge

  • UDT1.JPG
    UDT1.JPG
    122,6 KB · Aufrufe: 136
Zuletzt bearbeitet:
Auf deinem Screenshot kann man leider nicht viel erkennen.
Jedoch gibt es eine Beschränkung wenn der UDT im IN_OUT Bereich liegt, da in den Fall auf den UDT nur ein Zeiger übergeben wird.

Wenn du den UDT im IN-Bereich des FB einträgst sollte es mit dem Durchreichen gehen. Verhindert jedoch schreibenden Zugriff auf die Daten. Das Problem lässt sich aber auch noch umschiffen ;-)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also mit einfachen Mitteln ist das so nicht zu lösen, zumindest nicht wenn man vollständig symbolisch programmieren möchte.
Mit ein bißchen Pointer- und Adressregisterfrickelei bekommt man das sicher hin, so auf die schnelle fällt mir jedoch nichts elegantes ein.

Abhängig von der Größe der Struktur würde ich evtl. die UDT einmal im IN und dann noch im OUT Bereich anlegen, und dann entsprechend kopieren.

Oder:
Die UDT4 im Stat-Bereich des aufrufenden FB anlegen, dort die Daten vor dem Aufruf mit L #xx T #yy hineinkopieren, und dann den FB #Modulaufruf mit diesen Daten beschalten, und nach aufruf wieder zurückkopieren.
Ich hoffe das war halbwegs verständlich ;-)
 
Im Anhang mal ein Screenshot wie ich das meinte. Je nach Größe der Struktur hält sich der Aufwand dann noch in Grenzen.
 

Anhänge

  • step7_udt_durchreichen.jpg
    step7_udt_durchreichen.jpg
    68,4 KB · Aufrufe: 141
So müsste auch gehen?

Vom Prinzip schon. tUDT liegt im Temp-Bereich? Ansonsten musst du noch den AR2-Offset bei Multiinstanzen beachten.

Funktioniert natürlich nur solange keiner auf die Idee kommt deine "Sub-UDT" in der übergeordneten UDT an anderer Stelle als am Anfang zu positionieren.
Und an den Offset der Sub-UDT kommst du ohne Hardcodierung bei einem IN_OUT Parameter nicht heran.
 
also...

1. das fummeln am AR2 ist in FBs recht gefährlich, du musst es nach verwendung unbedingt wieder zurücksichern. Der ganze Zugriff auf deine Statvariablen bassiert auf dem AR2, und wenn du den irgendwo verbiegst, dann pasen die Zugriffe danch nicht mehr...

also vorher
TAR2 #T_AR2
und danach
LAR2 #T_AR2

#T_AR2 ist DWORD im temp bereich


2. wie thomas schon sagte geht das mit INOUT so nicht, in dem Fall wird nicht die Struktur übergeben, sonder ein abgespeckter ANY-Zeiger, ein sogenanter "6-byte_pointer". das siehst du relativ leicht wenn du nach der struktur noch ne variable deklarierst, dann siehst du das der utd nur 6 byte hat...


3. den aufbau von anypointer findest du ind er faq hier oder in der hilfe gut beschrieben, er enrhält im wesenltichen den db, die startadresse und die länge des datenblocks.
ein "6-byte-pointer" enthält nur startadresse und länge

4. ich würde anstelle des udt am inout einfach einen any an die in-schnittstelle machen, da kannst du später auch deine struktur symbolisch dranpacken. du hast dann mittels des ans im baustein alles was du brauchst um deine daten zu adressieren.
der zugriff über inout mitels "6-byte-pointer" ist im mc7 code später auch nichts anderes als ein indirekter zugriff auf jede variable, sprich späte in der sps wird für jeden variablenzugriff ein pointer gerechnet - diese bausteine werden deshlab RIESIG im vergleich zur folgenden lösugn wo anfangs alle in den temp bereich kopiert und am ende wieder zurück wird.
(riesig und die pointerrechnerei geht auch noch auf die laufzeit)

5. vorschlag
IN als any wo de struktur später aussen dran kommt(UDT_blabla)
ANY im temp bereich deklarieren (ANY_Aktoren)
struktur im temp bereich deklarieren (blabla)
mit dem any einen pointer für nen blockmov (sfc20) bauen und umkopieren

Pointer einlesen

Code:
  L     P##UDT_blabla
      LAR1  
      L     B [AR1,P#0.0]               // Syntax-ID aus dem Any-Pointer auslesen
      T     #SyntaxID
      L     B [AR1,P#1.0]               // Bereichstyp auslesen (B#16#2 = Byte;  B#16#3 = Int; B#16#4 = Word;  B#16#7 = DInt; B#16#8 = DWord)
      T     #Bereichstyp
      L     W [AR1,P#2.0]               // Anzahl der zu übertragenden Werte (Byte/Word)
      T     #Anzahl_Werte
      L     W [AR1,P#4.0]               // DB-Nummer auslesen
      T     #DB_Nr
      L     D [AR1,P#6.0]               // Pointer Startadresse auslesen
      T     #Startadresse


pointer für blockmove bauen

Code:
 L     P##ANY_blabla
      LAR1  
      L     #SyntaxID
      T     B [AR1,P#0.0]               // Syntax-ID in den Any-Pointer schreiben
      L     #Bereichstyp
      T     B [AR1,P#1.0]               // Bereichstyp schreiben (B#16#2 = Byte; B#16#4 = Word)
      L     #Anzahl_Werte
      T     W [AR1,P#2.0]               // Anzahl der zu übertragenden Werte (Byte/Word)
      L     #DB_Nr
      T     W [AR1,P#4.0]               // DB-Nummer schreiben
      L     #Startadresse
      T     D [AR1,P#6.0]               // Pointer Startadresse schreiben

daten in dem temp breich kopieren

Code:
      CALL  "BLKMOV"
       SRCBLK :=#ANY_blabla
       RET_VAL:=#retval
       DSTBLK :=#blabla

hier steht dein programm wo du die daten im temp bereich manipulierst bzw. die temp struktur auch an die aufgerufenen fcs übergibst (in denen kannst du ja so wie du es hast arbeiten - achte nur auf die codelänge wegen der zugriffe, wenn dir der code zu lange wird, kannst du es ja auch so machen wie beim fb


am ende des fb muss der inhalt der temp struktur zurück in die anparametrierte struktur...

Code:
      CALL  "BLKMOV"
       SRCBLK :=#blabla
       RET_VAL:=#retval
       DSTBLK :=#ANY_blabla
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Sehr schön zusammengefasst Markus.

Auch dass ein UDT-Parameter viel Speicher und Rechenleistung frisst ist gut zu erwähnen.
Jedoch muss ich sagen, dass ich mich da mittlerweile nicht mehr drum schere. Die neuen 315 CPU sind so leistungsfähung, dass ich keine Lust mehr habe irgendwo zu Lasten der Übersichtlichkeit was an der Performance oder Speicherauslastung zu optimieren. Bei mir kommt erst der Algorithmus, dann die Optimierung (wenn es Engpässe gibt).
Wenn man sich die Codesys-Steuerungen ansieht: da kann man nichtmal mehr sehen wie viel Speicher sein einzelner Baustein benötigt.

Mit einem Any-Pointer kann ich alles machen, jedoch gebe ich damit auch jedwede Typ-Überprüfung seitens des Compilers auf (der Step7-Editor ist ein Compiler, wenn auch abgespeckt). Vergleichbar ist das in groben Zügen mit dem Void-Zeiger in der C-Programmierung. Dort hat der Compilier auch fast keine Möglichkeiten mehr die Korrektheit der Typen zu überprüfen.
 
ist das ein Problem mit dem Temp bereich? ist ja nur für den Transfer in den IO bereich des nächsten Baustein.


Thomas
 
Zuletzt bearbeitet:
ist das ein Problem mit dem Temp bereich? ist ja nur für den Transfer in den IO bereich des nächsten Baustein.

Der Speicherbereich auf den der Zeiger dann im unterlagerten FB zeigt ist damit vom Typ "vorherige Lokaldaten" (V, Kennung 0x87).
Ich habe damit schonmal rumexperimentiert und in PLCSim funktioniert das auf jeden Fall. Ich erinnere mich aber an ein Handbuch in dem stand, dass es diesen Speicherbereich nur bei den 400er CPUs gibt. Die Step7-Hilfe weist diese Beschränkung jedoch nicht aus.:confused:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ist das ein Problem mit dem Temp bereich? ist ja nur für den Transfer in den IO bereich des nächsten Baustein.


Thomas

achso.. du meinst falll die aufgerufenen bausteine auch im temp bereich rumfummeln?
ja, das kann ein problem geben bzw. ist nicht sauber... in dem fall legst du halt die struktur in den stat bereich des fb...

sorry - das war ein fehler von mir!
 
Hallo Markus!
Sorry, daß ich den Thread aus der Versenkung hebe, vielleicht gibt es anderenorts schon weiterführende Infos...
Das mit dem stat bereich ist gut, du meinst also die parametrierte UDT auch im Statbereich parametrieren und über den Anypointer mit BLKMOV die UDT dort hin kopieren?
Aber wie kann ich die Adresse des UDT im STATbereich ermitteln wenn sich die UDT oder andere Parameter am FB geändert haben?
grüße
thomas
 
Man könnte (?) auch "TRICK 22:eek:" benutzen ... nämlich den Befehl :

TDB

Die DB ,DIB sollen ... über TEMP Bereich kommunizieren ! Adressierung mit P##xxx und AR1 ...etc
" P##xxx " wäre der erste Formalparameter in FB ....(der ist zugleich auch erster in DIB nach TDB )... alle Positionen in DIB nach TDB wären so über dem AR1 aufm DB-Anfang bezogen erreichbar .

Keine Sorge beim OB1-zyklischem FB Aufruf wird immer die richtige DIB gewählt (die ist ja in der CALL FB Definition gegeben )
Umkopieren würde dann über eine einfache Schleife gehen ... ohne ANY ... ohne BLOCKMOVE :ROFLMAO:
Alles symbolisch in TEMP ... SELBSTVERSTÄNDLICH ;)

(TEMP Daten werden von dem TDB Befehl nicht verändert)
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
@SPS.at:
was genau möchtest du machen ?
Der IN-Parameter (oder OUT-Parameter) eines FB ist vom Typ her festgelegt - den kannst du nicht variieren. Der Bereich bildet den ganzen UDT ab - das gibt also kein Problem.

@Sioan - 00alex:
Bitte nicht überall herum-spammen ... !!!

Gruß
Larry
 
Aber wie kann ich die Adresse des UDT im STATbereich ermitteln wenn sich die UDT oder andere Parameter am FB geändert haben?

Du kannst symbolisch auf die UDT im Stat-Bereich zugreifen.
Hier ein Code-Schnippsel von mir

Code:
// ----------------
// Any-Pointer PSrc
// ----------------
// Adresse des Anypointer PSrc
      L     P##PSrc
      LAR1  
// System-Code für Anypointer
      L     B#16#10
      T     B [AR1,P#0.0]
// Datentype Byte
      L     B#16#2
      T     B [AR1,P#1.0]
// DB-Nr 
      L     #BahnDBNr
      T     W [AR1,P#4.0]
// StartByte-Nr
      L     P#DBX 0.0                   // Daten Platz 1
      T     D [AR1,P#6.0]
// Anzahl der Bytes zum Kopieren
      L     280                         // Grösse UDT_Bahn
      T     W [AR1,P#2.0]
// Daten von BahnDB nach Instanzdaten "Bahn" kopieren
      CALL  "BLKMOV"
       SRCBLK :=#PSrc
       RET_VAL:=#iRetVal
       DSTBLK :=#Bahn

PSrc ist als Any-Pointer im Temp-Bereich definiert.
Bahn ist als UDT im Stat-Bereich definert.

Gruß
Dieter
 
Danke für die Antworten!
@larry
Es geht nach wie vor um das Durchreichen von IN/OUT-UDT's
@blockmove
Ganz steige ich bei deinem Beispiel noch nicht durch...
Du kopierts die Daten von der unter PSrc hinterlegten Adresse auf den InstanzDB?
Die Destinationadresse im IDB beginnt bei 0.0 und das UDT ist 280 Byte lang - bin ich soweit richtig?
Was aber wenn sich die Länge des UDT ändert? Oder jemand einen zusätzlichen IN am FB Parametriert?
grüße
thomas
 
Zurück
Oben