FUNCTION "BT_LT_3_CET" : VOID
TITLE =BT_LT_3: Convert base time to local time (Summertime/Wintertime)
//BT_LT_3_CET: Version für 31x-PN-CPU, wo bei NTP-Synchronisation keine
//Zeitzonen-Korrektur angegeben werden kann und dadurch die CPU-Uhr in UTC läuft
//
//BT_LT_3 ermittelt, ob der am Eingang BT angegebene Zeitpunkt (UTC) in der
//Sommerzeit liegt und gibt am Ausgang LT die lokale Uhrzeit (CET oder CEST) aus.
//BT muß ein gültiges DATE_AND_TIME inkl. Wochentag sein.
//
//Ersatz für FC61 BT_LT aus der S7-Standard-Library auf S7-300, die keinen
//Uhrzeitstatus besitzen (Im Uhrzeitstatus der CPU sind die Basiszeit sowie
//die für den jeweiligen Ort geltende Zeitzone, eine Sommerzeit-Kennung sowie
//eine Kennung für die Ankündigungsstunde hinterlegt und werden von der CPU
//aktualisiert.) BT_LT_3 benutzt keinen Regel-DB. BT_LT_3 ist fest auf die
//Zeitzone CET eingestellt und berücksichtigt nur den Uhrzeit-Versatz in der
//Sommerzeit. Die Sommerzeit gilt vom letzten Sonntag im März 01:00 UTC (02:00
//CET) bis zum letzten Sonntag im Oktober 01:00 UTC (03:00 CEST).
//
//BT_LT_3 benutzt intern die folgende Function der S7-Standard-Library –
//IEC Function Blocks: FC(1) AD_DT_TM
AUTHOR : PN_DP
FAMILY : TIMEFUNC
NAME : BT_LT_3
VERSION : 1.1
VAR_INPUT
BT : DATE_AND_TIME ; //Basiszeit UTC (z.B. CPU-Clock)
END_VAR
VAR_OUTPUT
LT : DATE_AND_TIME ; //Lokalzeit CET / CEST
SUMMER : BOOL ; //Sommerzeitkennung (0: Winter / 1: Sommer)
END_VAR
VAR_TEMP
tmpBT : DATE_AND_TIME ;
tmpLT : DATE_AND_TIME ;
DB_No : INT ;
LT_Offset : TIME ;
March : BOOL ;
END_VAR
BEGIN
NETWORK
TITLE =Basiszeit von IN-Aktualparameter BT in TEMP kopieren
//DATE_AND_TIME (DT) wird bei FC als 6-Byte-POINTER übergeben und kann nicht
//direkt weitergereicht werden. Deshalb IN.BT nach TEMP umkopieren.
//Pointer auf IN-Aktualparameter BT erstellen
L P##BT; // Adresse IN.BT
LAR1 ;
L W [AR1,P#0.0]; // POINTER.DB_Nr
T #DB_No;
L D [AR1,P#2.0]; // POINTER.Bereichsadresse
LAR1 ; // AR1: Adresse des IN-DT
LAR2 P##tmpBT; // AR2: Adresse des TEMP-DT
//DATE_AND_TIME (8 Byte) BT von IN nach TEMP kopieren
AUF DB [#DB_No];
L D [AR1,P#0.0];
T LD [AR2,P#0.0];
L D [AR1,P#4.0];
T LD [AR2,P#4.0];
NETWORK
TITLE =Ermitteln ob Sommerzeit ist und Lokalzeit CET/CEST berechnen
//Die Sommerzeit gilt vom letzten Sonntag im März 01:00 UTC = 02:00 CET
//bis zum letzten Sonntag im Oktober 01:00 UTC = 03:00 CEST
//AR2: Pointer auf tmpBT
//Der letzte Sonntag im März bzw. Oktober kann auf 25. bis 31. fallen
//vor 25.03. ist Winterzeit
L LW [AR2,P#1.0]; // tmpBT.Monat (BCD) + Tag (BCD)
L DW#16#325; // vor 25.03. ist WZ
<I ;
SPB WINZ;
//nach 31.10. ist Winterzeit
POP ; // tmpBT.Monat (BCD) + Tag (BCD)
L W#16#1031; // nach 31.10. ist WZ
>I ;
SPB WINZ;
//nach 31.03. (= 01.04.) bis vor 25.10. (= 24.10.) ist Sommerzeit
POP ; // tmpBT.Monat (BCD) + Tag (BCD)
L W#16#331; // bis 31.03. Umschaltwoche zu SZ
<=I ;
= #March; // Umschaltwoche WZ zu SZ
SPB SPEZ;
POP ; // tmpBT.Monat (BCD) + Tag (BCD)
L W#16#1025; // bis vor 25.10. ist SZ
<I ;
SPB SOMZ;
//hier nur noch 25.03.-31.03. und 25.10.-31.10.
//letzter Sonntag ?
SPEZ: L LB [AR2,P#7.0]; // tmpBT.Wochentag 1=So ... 7=Sa
UW W#16#F; // nur Bits .0-.3 (4 LSB)
L B#16#1;
-I ; // WoT: 0=So, 1=Mo, ... 6=Sa
SPZ SONN; // jetzt ist der Umschalt-Sonntag
//Akku1: Wochentag 0=So ... 6=Sa
L LB [AR2,P#2.0]; // tmpBT.Tag (BCD)
BTI ; // Tag (INT)
TAK ; // Akku1: WoT, Akku2: Tag
-I ;
//Ergebnis 19..24 sind Tage vor Umschalt-Sonntag
L 25;
<I ;
SPBN NACH;
//Vor Umschalt-Tag bzw. -Uhrzeit
VOR: U #March;
SPB WINZ; // März: noch ist Winterzeit
SPA SOMZ; // Okt.: noch ist Sommerzeit
//Nach Umschalt-Tag bzw. -Uhrzeit
NACH: U #March;
SPB SOMZ; // März: nun ist Sommerzeit
SPA WINZ; // Okt.: nun ist Winterzeit
//es ist jetzt der Umschalt-Sonntag
SONN: L LB [AR2,P#3.0]; // tmpBT.Stunde (BCD)
L B#16#1; // vor 01:00 UTC ?
<I ;
SPB VOR;
SPA NACH;
//Signalisierung + Berechnung Sommerzeit oder Winterzeit
SOMZ: S #SUMMER;
L T#2H; // Sommerzeit CEST = BT(UTC) + 2 Stunden
SPA TLTO;
WINZ: R #SUMMER;
L T#1H; // Winterzeit CET = BT(UTC) + 1 Stunde
TLTO: T #LT_Offset;
//Lokalzeit berechnen mit: IEC Function Blocks FC1 "AD_DT_TM"
CALL "AD_DT_TM" (
T := #tmpBT,
D := #LT_Offset,
RET_VAL := #tmpLT);
NETWORK
TITLE =Lokalzeit von TEMP in OUT-Aktualparameter LT kopieren
//DATE_AND_TIME (DT) wird bei FC als 6-Byte-POINTER übergeben, OUT kann nicht
//direkt von anderen FC beschrieben werden. Deshalb mit TEMP-Kopie arbeiten.
//Pointer auf OUT-Aktualparameter LT erstellen
L P##LT; // Adresse OUT.LT
LAR1 ;
L W [AR1,P#0.0]; // POINTER.DB_Nr
T #DB_No;
L D [AR1,P#2.0]; // POINTER.Bereichsadresse
LAR1 ; // AR1: Adresse des OUT-DT
LAR2 P##tmpLT; // AR2: Adresse des TEMP-DT
//DATE_AND_TIME (8 Byte) LT von TEMP nach OUT kopieren
AUF DB [#DB_No];
L LD [AR2,P#0.0];
T D [AR1,P#0.0];
L LD [AR2,P#4.0];
T D [AR1,P#4.0];
//BIE/ENO auf TRUE setzen
SET ;
SAVE ;
END_FUNCTION