Datentyp Date and Time weiterreichen

nutellahase

Level-2
Beiträge
180
Reaktionspunkte
28
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo!

Ich habe in einer Funktion den Datentyp DATE and TIME als Eingangsvariable definiert. Die Funktion wird im OB1 aufgerufen. Innerhalb der Funktion möchte ich jetzt z.B. den DT in das Format DATE zerlegen. Hierzu nehme ich den FC6 aus der IEC Bibliothek. Tja, leider lässt sich der Datentyp nicht so einfach übergeben. Da im OB1 die Variable bereits als Pointer übergeben wird habe ich nun folgendes gemacht:

Code:
      L     P##i_Datum_und_Uhrzeit      // Pointer auf Eingangsvariable (Datentyp DT)
      LAR1                              // ins Adressregister 1 laden
      L     W [AR1,P#0.0]               // DB-Nummer laden (siehe Aufbau Datentyp POINTER)
      T     #tmp_DBNr
      L     D [AR1,P#2.0]               // Speicherbereich und Adresse laden (siehe Aufbau Datentyp POINTER)
      T     #tmp_Adresse

In weiterer Folge erstell ich mir einen ANY-Pointer, ich weiß dass der Datentyp DT 8 BYTE umfasst!

Code:
      L     P##tmp_Any_Pointer
      LAR1  
      L     W#16#1002                   // HEX 10 für S7 und Datentyp BYTE (02)
      T     W [AR1,P#0.0]
      L     8                           // Datentyp Date_and_Time ist 8 Byte lang
      T     W [AR1,P#2.0]
      L     #tmp_DBNr                   // DB Nummer der übergebenen Eingangsvariable
      T     W [AR1,P#4.0]
      L     #tmp_Adresse                // Speicherbereich der übergebenen Eingangsvariable
      T     D [AR1,P#6.0]

Dann habe ich noch eine temporäre Date and Time Variable angelegt. Mittels Blockmove werden nun die Informationen auf die der ANY-Pointer zeigt in meine temp. Variable kopiert:

Code:
      CALL  "BLKMOV"
       SRCBLK :=#tmp_Any_Pointer
       RET_VAL:=#SFC20_Error
       DSTBLK :=#tmp_Date_Time

Nun kann ich meine Funktion FC6 aufrufen..

Code:
      CALL  "DT_DATE"
       IN     :=#tmp_Date_Time
       RET_VAL:=#o_Datum     // Ausgangsvariable vom Typ DATE

So das ganze funktioniert nur wenn ich im OB1 einen DT aus einem Datenbaustein übergebe. Möchte ich beispielsweise die Lokalvariable #OB1_Date_Time übergeben funktioniert es nicht!

Die einzige Lösung die ich dafür gefunden hab ist, dass ich das AR1 auf die vorherigen Lokaldaten lade und dann mittels absoluter Adressierung arbeite (was mir aber nicht gefällt!). Besonders wenn sich dann Adressen verschieben hätte ich damit ein Problem!

Code:
      L     P##i_Datum_und_Uhrzeit      // Pointer auf Eingangsvariable 
      LAR1                              // ins Adressregister 1 laden
      L     W [AR1,P#0.0]               // DB-Nummer laden (siehe Aufbau Datentyp POINTER)
      T     #tmp_DBNr
      L     D [AR1,P#2.0]               // Speicherbereich und Adresse laden (siehe Aufbau Datentyp POINTER)
      T     #tmp_Adresse
      LAR1  
      AUF   DB [#tmp_DBNr]
      L     D [AR1,P#0.0]
      T     LD    10                    // hier beginnt meine Lokalvariable tmp_Date_Time
      L     D [AR1,P#4.0]
      T     LD    14
Wieso funktioniert die Vorgehensweise mit den ANY-Pointer auf die Lokaldaten des OB1 nicht??? Mir ist auch klar, dass ich auf die einzelnen Bytes zugreifen könnte bzw. in SCL die AT-Sicht nutzen kann, ich wollte es aber mal in AWL probieren. ;)
 
Hallo,
ich verstehe dein Problem nicht so ganz ...
Du könntest z.B. im OB1 (oder sonstwo) eine Variable MyDateTime (vom Typ DT) im Temp-Bereich des Bausteins anlegen und diese an den SFC1 zum Füllen übergeben.
Direkt danach kannst du diese (nun gefüllte) Variable direkt an den FC6 (DT to Date) übergeben und der macht dir dann das Date daraus (was auch noch eine Temp-Variable des OB1 sein könnte).
Du mußt da mit ANY-Pointern gar nichts machen ... einfach die Variable symbolisch übergeben ...

Oder was wolltest du erreichen ?

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi Larry!

Ja das ist mir schon klar, ich war nur neugierig wie man einen DT weiter verschachtelt! Im Prinzip wollte ich einen FC erstellen der mir meinen DT mit den IEC Funktionen in die Formate DATE, TOD und Wochentag zerlegt. Hierzu wollte ich an der Schnittstelle den DT übergeben und als Ausgangsparameter bekomme ich meine drei Formate! Zugegeben könnte ich alle drei Funktionen im OB1 aufrufen aber ich wollte es kompakter in einer Funktion erhalten.

Wenn ich nun im OB1 mit dem SFC1 die Systemzeit auslese, sie in einem DB abspeichere und an meine Funktion übergebe klappt das auch! Nutze ich aber die Startinformation des OB1 (OB1_Date_Time) dann klappt nur die von mir zuletzt geschriebene Variante (also die mit der absoluten Adressierung)!

Ich habe nun das Pendant in SCL erstellt (ist auch viel einfacher):

Code:
FUNCTION "FC_DT_DATE_TOD_DAY" : VOID

VAR_INPUT
    i_Date_and_Time: DT;
END_VAR

VAR_OUTPUT
    o_Datum: DATE;
    o_Uhrzeit: TOD;
    o_Wochentag: INT;
END_VAR

VAR_TEMP
   tmp_Date_Time : DT;
END_VAR

tmp_Date_Time := i_Date_and_Time;

o_Datum     := "DT_DATE" (IN := tmp_Date_Time);
o_Uhrzeit   := "DT_TOD"  (IN := tmp_Date_Time);
o_Wochentag := "DT_DAY"  (IN := tmp_Date_Time);  
END_FUNCTION

Sieht man sich den übersetzten Code an macht der Compiler im Endeffekt dann das:

Code:
   SET   
      SAVE  
      =     L      8.1
     [B] L     P##i_Date_and_Time
      LAR1  
      L     W [AR1,P#0.0]
      T     LW    10
      AUF   DB [LW 10]
      L     D [AR1,P#2.0]
      LAR1  
      L     D [AR1,P#0.0]
      T     LD     0
      L     D [AR1,P#4.0]
      T     LD     4[/B]
      L     W#16#0
      T     LW    10
      L     DW#16#87000000
      T     LD    12
      UC    "DT_DATE"
            P#L 10.0
            P#L 16.0
      L     LW    16
      T     #o_Datum
      L     W#16#0
      T     LW    10
      L     DW#16#87000000
      T     LD    12
      UC    "DT_TOD"
            P#L 10.0
            P#L 16.0
      L     LD    16
      T     #o_Uhrzeit
      L     W#16#0
      T     LW    10
      L     DW#16#87000000
      T     LD    12
      UC    "DT_DAY"
            P#L 10.0
            P#L 16.0
      L     LW    16
      T     #o_Wochentag
      U     L      8.1
      SAVE  
      BE

Mich wundert nur wieso es mit einen ANY-Pointer nicht funktioniert bei den temp. Variablen von OB1 (der Pointer zeigt zumindest auf die richtige Adresse und hat auch die Lokaldaten des Vorgängers (V)). Nun ja mit dem SCL-Code funktioniert jedenfalls beides!
 
... ich bin mir da jetzt nicht ganz sicher, meine allerdings, dass du bei deinem IN an einem FC nur einen Pointer hast, der dahin zeigt wo der Inhalt des ANY-Pointers, der hier wirklich übergeben werden soll, steht.
SCL weiß das aber und verhält sich entsprechend. Grundsätzlich kannst du den OB1_Date_Time genauso behandeln ...

Gruß
Larry
 
... ich bin mir da jetzt nicht ganz sicher, meine allerdings, dass du bei deinem IN an einem FC nur einen Pointer hast, der dahin zeigt wo der Inhalt des ANY-Pointers, der hier wirklich übergeben werden soll, steht.
SCL weiß das aber und verhält sich entsprechend. Grundsätzlich kannst du den OB1_Date_Time genauso behandeln ...

Gruß
Larry
So wie ich das sehe hat der TE doch in den ersten beiden Codeschnipslen des 1. Posts genau das aufgedröselt. Er holt sich aus dem Pointer die DB-Nummer und die Adresse und baut sich damit einen Any-Pointer mit 8 Byte zusammen.

Interessant wäre demnach ob der Blockmove aus dem 3. Codeschnipsel was Vernünfiges kopiert.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann habe ich noch eine temporäre Date and Time Variable angelegt. Mittels Blockmove werden nun die Informationen auf die der ANY-Pointer zeigt in meine temp. Variable kopiert:

Code:
      CALL  "BLKMOV"
       SRCBLK :=#tmp_Any_Pointer
       RET_VAL:=#SFC20_Error
       DSTBLK :=#tmp_Date_Time
[...]

So das ganze funktioniert nur wenn ich im OB1 einen DT aus einem Datenbaustein übergebe. Möchte ich beispielsweise die Lokalvariable #OB1_Date_Time übergeben funktioniert es nicht!
Für die SFC20 "BLKMOV" sind als Quell- und Zielbereich die Speicherbereiche E, A, M, D, L zulässig. V ist nicht zulässig..

Mit der SFC20 können keine Speicherbereiche aus Vorgänger-Lokaldaten kopiert werden, weil schon die Lokaldaten des die SFC20 aufrufenden Bausteins die Vorgänger-Lokaldaten der SFC20 sind. Die SFC20 müßte quasi die Vorgänger-Vorgänger-Lokaldaten kopieren, was aber von Siemens nicht so implementiert wurde. Per POINTER übergebene Eingangsvariablen müssen ohne Aufruf eines weiteren Bausteins zuerst in die eigenen Lokaldaten kopiert werden und diese lokalen Kopien der Variablen können dann an weitere Bausteine übergeben werden.

Hier ein AWL-Beispiel für die Übergabe von DT als IN und OUT eines FC, Kopieren des IN/OUT-DT in/aus TEMP und Weitergabe des TEMP-DT an andere FC. Das Kopieren der IN/OUT-DT in/aus TEMP-DT wird nicht mit SFC20 gemacht, sondern einfach indirekt mit AR1 und AR2. Durch Benutzen von AR2 als Zielpointer kommt der Code ohne absolute L-Adressen aus.
Das Beispiel funktioniert, egal ob die übergebenen DT-Variablen in TEMP oder in DB liegen.

Harald
 
Zurück
Oben