读取PLC时间转换为UNIX 时间做网络同步比较
最近在安全行业里做读取PLC内部故障事件分析的工作,发现在PLC网络里采用NTP时间同步基本上没有,因为在工控领域PLC更多承担业务层面控制需求的实现unix媒体转换,反而对于PLC本身的安全并没有过多的重视。 多区域内PLC时间同步就是安全设置的必要一步,因为这个会涉及PLC内部的事件和记录是否能够按照真实的时间进行提取和分析。那在不同网段读取不同厂商PLC时间进行比较和同步就成为一个比较麻烦的事情。不同厂商PLC的日期和时间比较需要用到一个INT数组数据来比较。所以才有了这需求打算采用Unix 时间来做时间对比,因为所有厂商的PLC的日期和时间都可以转成Unix 时间。 先说一下什么是Unix 时间:Unix时间(英文为Unix epoch, Unix time, POSIX time 或 Unix timestamp) 是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。UNIX时间的0按照ISO 8601规范为 :1970-01-01T00:00:00Z. 一个小时表示为UNIX时间格式为:3600秒;一天表示为UNIX时间为86400秒,闰秒不计算。 时间 秒 1 分钟 60 秒 1 小时 3600 秒 1 天 86400 秒 1 周 604800 秒 1 月 (30.44 天) 2629743 秒 1 年 (365.24 天) 31556926 秒 下面我将采用结构化文本的形式来开发这个PLC时间转成Unix时间,为了方便大家在其他的PLC中实现时间格式的转换。 // Convert system time to unix time // (seconds until 1970-01-01 00:00) // Create by jiansiting FUNCTION Unixtime : DWORD VAR_INPUT END_VAR VAR_TEMP leapyears: INT; days_from_1970 : DINT; days_from_BeginOfYear : ARRAY[1..12] OF INT; l_unixtime: DINT; sfc1_ret_val : INT; CDT_systemtime : DATE_AND_TIME; systemtime AT CDT_systemtime : STRUCT year_CDT: BYTE; // 1970 ... 2038 month_CDT: BYTE; day_CDT: BYTE; hour_CDT: BYTE; minute_CDT: BYTE; second_CDT: BYTE; END_STRUCT; year: INT; // 1970 ... 2038 month: INT; day: INT; hour: INT; minute: INT; second: INT; END_VAR leapyears:= 0; days_from_1970 := 0; // days of current month without leap day days_from_BeginOfYear[1] := 0; days_from_BeginOfYear[2] := 31; days_from_BeginOfYear[3] := 59; days_from_BeginOfYear[4] := 90; days_from_BeginOfYear[5] := 120; days_from_BeginOfYear[6] := 151; days_from_BeginOfYear[7] := 181; days_from_BeginOfYear[8] := 212; days_from_BeginOfYear[9] := 243; days_from_BeginOfYear[10] := 273; days_from_BeginOfYear[11] := 304; days_from_BeginOfYear[12] := 334; // read system time sfc1_ret_val := READ_CLK(CDT := CDT_systemtime); year:= BCD_TO_INT(systemtime.year_CDT) + 2000; month:= BCD_TO_INT(systemtime.month_CDT); day:= BCD_TO_INT(systemtime.day_CDT); hour:= BCD_TO_INT(systemtime.hour_CDT); minute:= BCD_TO_INT(systemtime.minute_CDT); second:= BCD_TO_INT(systemtime.second_CDT); // sum of leap years since 1979 (without current leap year) leapyears := ((year-1)-1968)/4-((year-1)-1900)/100+((year-1)-1600)/400; days_from_1970 := (year-1970)*365 + leapyears+ days_from_BeginOfYear[month] + day-1; IF ( (month > 2) AND ((year MOD 4 = 0) AND ((year MOD 100 0) OR (year MOD 400 = 0))) ) THEN days_from_1970 := days_from_1970 + 1; // + leap day, if year is leap year END_IF; // OUTPUT in s l_unixtime := second + 60 * ( minute + 60 * (hour + 24 * days_from_1970) ); // if error return 0 IF sfc1_ret_val 0 THEN Unixtime := 0; ELSE Unixtime := DINT_TO_DWORD(l_unixtime); END_IF; END_FUNCTION (编辑:92站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |