Einen fertigen Datum/Uhrzeit-String-Formatierer gibt es anscheinend nicht, die Aufgabe ist aber einfach zu lösen. Man muß nur die ersten 6 Byte eines DATE_AND_TIME in 12 Ziffern (CHAR) umwandeln und dann in der gewünschten Reihenfolge nebst Trennzeichen in die Ausgabe-Strings kopieren.
Eine effiziente BCD(Hex)-zu-CHAR-Wandlung kann man in AWL schnell "zu Fuß" programmieren, man kann aber auch den FC95 HTA dafür nehmen. Da man für den Zugriff auf die zusammengesetzten Datentypen DATE_AND_TIME und STRING an FC-IN und FC-OUT indirekte Adressierung braucht, ist das ganze aber besser lesbar und schneller getippt in SCL zu lösen.
Hier eine Variante in SCL welche ohne weitere Bausteine auskommt
Code:
FUNCTION DT_STRNG : VOID
TITLE='DATE_AND_TIME in Datum-String und Uhrzeit-String konvertieren'
VERSION : '1.0'
AUTHOR : PN_DP
NAME : DT_STRNG
FAMILY : CONVERT
VAR_INPUT
IN : DATE_AND_TIME ;
END_VAR
VAR_OUTPUT
D : STRING[10] ; // String für Datum '31.12.2089'
baD AT D : ARRAY[-1..10] OF BYTE ;
T : STRING[8] ; // String für Uhrzeit '23:59:59'
baT AT T : ARRAY[-1..8] OF BYTE ;
END_VAR
VAR_TEMP
tmpDT : DATE_AND_TIME ;
baDT AT tmpDT : STRUCT
Year : BYTE ; // Jahr BCD (19)90..(20)89
Month : BYTE ; // Monat BCD 01..12
Day : BYTE ; // Tag BCD 01..31
Hour : BYTE ; // Stunde BCD 00..23
Minute : BYTE ; // Minute BCD 00..59
Second : BYTE ; // Sekunde BCD 00..59
msMSD : BYTE ;
wDay_msLSD : BYTE ;
END_STRUCT ;
tmpD : STRING[10] ; // String für Datum '31.12.2089'
tbaD AT tmpD : ARRAY[-1..10] OF BYTE ;
tmpT : STRING[8] ; // String für Uhrzeit '23:59:59'
tbaT AT tmpT : ARRAY[-1..8] OF BYTE ;
tmpWord : WORD ;
tmpW AT tmpWord : STRUCT
B1 : BYTE ;
B0 : BYTE ;
END_STRUCT ;
END_VAR
// IN-DATE_AND_TIME in TEMP kopieren
tmpDT := IN ;
// Datum --> '31.12.2089'
tmpD := '00.00.2000' ; // String initialisieren
tmpW.B0 := baDT.Day ; // Tag
tmpW.B1 := DWORD_TO_BYTE( SHR(IN:=BYTE_TO_DWORD(baDT.Day), N:=4) ) ;
tmpWord := tmpWord AND W#16#0F0F OR W#16#3030 ;
tbaD[1] := tmpW.B1 ;
tbaD[2] := tmpW.B0 ;
tmpW.B0 := baDT.Month ; // Monat
tmpW.B1 := DWORD_TO_BYTE( SHR(IN:=BYTE_TO_DWORD(baDT.Month), N:=4) ) ;
tmpWord := tmpWord AND W#16#0F0F OR W#16#3030 ;
tbaD[4] := tmpW.B1 ;
tbaD[5] := tmpW.B0 ;
tmpW.B0 := baDT.Year ; // Jahr
tmpW.B1 := DWORD_TO_BYTE( SHR(IN:=BYTE_TO_DWORD(baDT.Year), N:=4) ) ;
tmpWord := tmpWord AND W#16#0F0F OR W#16#3030 ;
tbaD[9] := tmpW.B1 ;
tbaD[10] := tmpW.B0 ;
baD := tbaD ; // Datum-String nach OUTPUT kopieren
// Uhrzeit --> '23:59:59'
tmpT := '00:00:00' ; // String initialisieren
tmpW.B0 := baDT.Hour ; // Stunde
tmpW.B1 := DWORD_TO_BYTE( SHR(IN:=BYTE_TO_DWORD(baDT.Hour), N:=4) ) ;
tmpWord := tmpWord AND W#16#0F0F OR W#16#3030 ;
tbaT[1] := tmpW.B1 ;
tbaT[2] := tmpW.B0 ;
tmpW.B0 := baDT.Minute ; // Minute
tmpW.B1 := DWORD_TO_BYTE( SHR(IN:=BYTE_TO_DWORD(baDT.Minute), N:=4) ) ;
tmpWord := tmpWord AND W#16#0F0F OR W#16#3030 ;
tbaT[4] := tmpW.B1 ;
tbaT[5] := tmpW.B0 ;
tmpW.B0 := baDT.Second ; // Sekunde
tmpW.B1 := DWORD_TO_BYTE( SHR(IN:=BYTE_TO_DWORD(baDT.Second), N:=4) ) ;
tmpWord := tmpWord AND W#16#0F0F OR W#16#3030 ;
tbaT[7] := tmpW.B1 ;
tbaT[8] := tmpW.B0 ;
baT := tbaT ; // Uhrzeit-String nach OUTPUT kopieren
END_FUNCTION
// Optimierungs-Unterstützung des SCL-Compilers (K05.03.05.00_01.03.00.01):
// - direktes Bearbeiten der IN- und OUT-Parameter benötigt ca. doppelt soviel Programmgröße wie Bearbeiten in TEMP
// - SHR(IN:=ByteVar, N:=4) benötigt 22 Byte mehr als DWORD_TO_BYTE(SHR(IN:=BYTE_TO_DWORD(ByteVar), N:=4))
// - Division durch 16 statt SHR 4 oder nicht Zwischenspeichern in tmpWord benötigen geringfügig mehr
// - (T := tmpT) String-Kopieren benötigt fast 200 Byte mehr als Array kopieren (baT := tbaT)
Und eine zweite Variante in SCL, welche den FC95 HTA aus den TI-S7 Converting Blocks nutzt.
Sieht kürzer aus, braucht aber mit dem FC HTA zusammen etwas mehr Programmspeicher.
Code:
FUNCTION DT_STRNG2 : VOID
TITLE='DATE_AND_TIME in Strings konvertieren'
VERSION : '1.0'
AUTHOR : PN_DP
NAME : DT_STRNG
FAMILY : CONVERT
VAR_INPUT
IN : DATE_AND_TIME ;
END_VAR
VAR_OUTPUT
D : STRING[10] ; // String für Datum '31.12.2089'
baD AT D : ARRAY[-1..10] OF BYTE ;
T : STRING[8] ; // String für Uhrzeit '23:59:59'
baT AT T : ARRAY[-1..8] OF BYTE ;
END_VAR
VAR_TEMP
tmpDT : DATE_AND_TIME ;
tmpArray : ARRAY[1..12] OF BYTE ;
END_VAR
// IN-DATE_AND_TIME in TEMP kopieren
tmpDT := IN ;
// und mit FC HTA in CHARs wandeln --> 'YYMMDDHHMMSS'
HTA(IN:=tmpDT, N:=6, OUT:=tmpArray);
// Datum --> '31.12.2089'
baD[-1] := 10 ; // max Stringlänge
baD[0] := 10 ; // akt. Stringlänge
baD[1] := tmpArray[5] ; // Tag
baD[2] := tmpArray[6] ;
baD[3] := CHAR_TO_BYTE('.') ;
baD[4] := tmpArray[3] ; // Monat
baD[5] := tmpArray[4] ;
baD[6] := CHAR_TO_BYTE('.') ;
baD[7] := CHAR_TO_BYTE('2') ;
baD[8] := CHAR_TO_BYTE('0') ;
baD[9] := tmpArray[1] ; // Jahr
baD[10] := tmpArray[2] ;
// Uhrzeit --> '23:59:59'
baT[-1] := 8 ; // max Stringlänge
baT[0] := 8 ; // akt. Stringlänge
baT[1] := tmpArray[7] ; // Stunde
baT[2] := tmpArray[8] ;
baT[3] := CHAR_TO_BYTE(':') ;
baT[4] := tmpArray[9] ; // Minute
baT[5] := tmpArray[10] ;
baT[6] := CHAR_TO_BYTE(':') ;
baT[7] := tmpArray[11] ; // Sekunde
baT[8] := tmpArray[12] ;
END_FUNCTION
Beide Varianten funktionieren korrekt nur im Datumsbereich 01.01.2000 bis 31.12.2089, weil die zweistellige Jahresangabe des DATE_AND_TIME einfach immer zu 20xx erweitert wird!
Harald