Запоминаем время при запуске, а дальше добавляем к нему разницу в TIME(). Получается не совсем точно, но равномерно. Впрочем, точнее и не будет без внешнего источника времени. Можно было бы ещё среднее посчитать, но овчинка выделки не стоит. Кому надо — берите:
Код:
FUNCTION_BLOCK SteadyClock
VAR_INPUT
ReInit: BOOL := TRUE;
END_VAR
VAR_OUTPUT
OutDT: DT;
OutDWORD: DWORD;
OutSTD: SystemTimeDate;
END_VAR
VAR
InitUptime: TIME;
InitDateTime: DWORD;
InitSTD: SystemTimeDate;
DummyTime64: SysTime64;
GetTime: CurTimeEx;
ExtractDate: ExtractDate;
END_VAR
IF ReInit THEN
SysMemSet(ADR(InitSTD), 0, SIZEOF(InitSTD));
SysMemSet(ADR(DummyTime64), 0, SIZEOF(DummyTime64));
GetTime(SystemTime := DummyTime64, TimeDate := InitSTD);
InitDateTime :=
DATE_TO_DWORD(PackDate(InitSTD.Year, InitSTD.Month, InitSTD.Day)) +
TIME_TO_DWORD(PackTime(InitSTD.Hour, InitSTD.Minute, InitSTD.Second, InitSTD.Milliseconds)) / 1000;
InitUptime := TIME();
ReInit := FALSE;
END_IF
OutDWORD := InitDateTime + TIME_TO_DWORD((TIME() - InitUptime)) / 1000;
OutDT := DWORD_TO_DT(OutDWORD);
ExtractDate(dat := DT_TO_DATE(OutDT), y => OutSTD.Year, m => OutSTD.Month, d => OutSTD.Day);
OutSTD.Second := DWORD_TO_UINT(OutDWORD MOD 60);
OutSTD.Minute := DWORD_TO_UINT((OutDWORD / 60) MOD 60);
OutSTD.Hour := DWORD_TO_UINT((OutDWORD / 3600) MOD 24);
Используются функции из библиотек SysLibTime, SysLibMem и TimeExp с сайта codesys.ru.