读取PLC时间转换为UNIX 时间做网络同步比较

Posted 剑指工控

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了读取PLC时间转换为UNIX 时间做网络同步比较相关的知识,希望对你有一定的参考价值。

JZGKCHINA
工控技术分享平台

最近在安全行业里做读取PLC内部故障事件分析的工作,发现在PLC网络里采用NTP时间同步基本上没有,因为在工控领域PLC更多承担业务层面控制需求的实现,反而对于PLC本身的安全并没有过多的重视。

读取PLC时间转换为UNIX 时间做网络同步比较

多区域内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时间转成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


以上是关于读取PLC时间转换为UNIX 时间做网络同步比较的主要内容,如果未能解决你的问题,请参考以下文章

使用NTP对PLC或CP进行时间同步(西门子PLC1500)

002-官网安装openstack之-安装基础服务

西门子plc的opcua读取不到值

C语言读取PLC数据

如何从西门子plc S7-200中读取梯形图程序

plc的通讯协议是啥意思?