摘要:要把日期时间转变成时间戳,打个比方:2024 年 9 月 2 日 16 点 51 分 21 秒转成时间戳就是 1725267081 。把时间戳转变成日期时间,比如:1725267081 转成日期时间就是 2024 年 9 月 2 日 16 点 51 分 21
S7-1200 - 1500 案例之日期时间戳互换
一、相关软(硬)件:
编程软件:TIA_V15.1仿真软件:PLCSIM二、控制要求:
要把日期时间转变成时间戳,打个比方:2024 年 9 月 2 日 16 点 51 分 21 秒转成时间戳就是 1725267081 。把时间戳转变成日期时间,比如:1725267081 转成日期时间就是 2024 年 9 月 2 日 16 点 51 分 21 秒 。本文的时间戳计算办法是这样的:算一算从 1970 年 1 月 1 日 8 时 0 分 0 秒到现在的总秒数。首先得算出闰年和平年的个数,根据年份算出总天数,然后把总天数、当前的小时、当前的分钟分别都变成秒数加起来,最后再加上当前的秒数。
注:这个程序仅供参考!!!
三、时间时间戳互换:(新建项目、新建 UDT、新建 FB 块、添加变量、编写程序、调用FB块、关联变量、下载测试)
新建UDT数据类型
2、新建FB块(Timestamp Swap):
建立变量表1
建立变量表2
3、编写程序:
读取系统时间
日期转换为时间戳
时间戳转换为日期
设置系统时间
完整程序:
(日期时间戳互换:Smart Auto Control – WangQuanFuGui 原创
时间戳:把 1970 年 1 月 1 日 8 时 0 分 0 秒当作时间戳开始的时间,每过一秒就加 1 。
本文时间戳的计算方法:先算一下从 1970 年 1 月 1 日 8 时 0 分 0 秒到现在的总秒数,首先得算闰年和平年各有多少个,然后根据年份算出总天数,接着把总天数、当前的小时、当前的分钟分别转换成秒数加起来,最后再加上当前的秒数。)
REGION ReadTime //读取系统时间
#ReturnVal0 := RD_LOC_T(#SysTimeR); //把系统时间进行转换
#ReadSysTime.Year := UINT_TO_DINT(#SysTimeR.YEAR);
#ReadSysTime.Month := USINT_TO_DINT(#SysTimeR.MONTH);
#ReadSysTime.Day := USINT_TO_DINT(#SysTimeR.DAY);
#ReadSysTime.Hour := USINT_TO_DINT(#SysTimeR.HOUR);
#ReadSysTime.Minute := USINT_TO_DINT(#SysTimeR.MINUTE);
#ReadSysTime.Second := USINT_TO_DINT(#SysTimeR.SECOND);
#ReadSysTime.Microsecond := UDINT_TO_DINT(#SysTimeR.NANOSECOND);
END_REGION
//日期转换时间戳
REGION ReadTimestamp //初始化
#DaysSince1970 := 0;
#SecondsInDay := 86400;
#leapYearsCount := 0;
#commonYearsCount := 0;
#CurrentDaysCount := 0;
//每月的天数是[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
#MonthDays[0] := 31;
#MonthDays[1] := 28;
#MonthDays[2] := 31;
#MonthDays[3] := 30;
#MonthDays[4] := 31;
#MonthDays[5] := 30;
#MonthDays[6] := 31;
#MonthDays[7] := 31;
#MonthDays[8] := 30;
#MonthDays[9] := 31;
#MonthDays[10] := 30;
#MonthDays[11] := 31;
//计算从1970年到当前年份前一年闰年平年个数
FOR #Year := 1970 TO #ReadSysTime.Year - 1 DO
//判断是否为闰年 #isLeapYear := (#Year MOD 4 = 0 AND #Year MOD 100 0) OR (#Year MOD 400 = 0);
//闰年平年个数计算
IF #isLeapYear THEN
#leapYearsCount := #leapYearsCount + 1; ELSE #commonYearsCount := #commonYearsCount + 1; END_IF; END_FOR;
//判断当前年份是否为闰年
#isLeapYear := (#ReadSysTime.Year MOD 4 = 0 AND #ReadSysTime.Year MOD 100 0) OR (#ReadSysTime.Year MOD 400 = 0); IF #isLeapYear THEN #MonthDays[1] := 29; END_IF;
//计算当前年份前一个月的总天数
FOR #Month := 0 TO #ReadSysTime.Month - 2 DO #CurrentDaysCount := #CurrentDaysCount + #MonthDays[#Month]; END_FOR;
//计算当前月份前一天的总天数
#CurrentDaysCount := #CurrentDaysCount + #ReadSysTime.Day - 1;
//计算1970年至今总天数计算
#DaysSince1970 := (#leapYearsCount * 366) + (#commonYearsCount * 365) + #CurrentDaysCount;
//计算时间戳(1970至今的总秒数)
#ReadTimestamp := #DaysSince1970 * #SecondsInDay + ((#ReadSysTime.Hour - 8) * 3600) + (#ReadSysTime.Minute * 60) + #ReadSysTime.Second;
END_REGION
////时间戳转换为日期
REGION _WriteTimestamp_ //初始化 #SecondsBeiJing := 28800; #DaysSince1970 := 0; #Year := 1970; #Month := 0;
//计算自1970年1月1日以来的天数和当天的秒数
#DaysSince1970 := (#WriteTimestamp + #SecondsBeiJing) / #SecondsInDay; #CurrentSecond := (#WriteTimestamp + #SecondsBeiJing) MOD #SecondsInDay;
// 计算从1970年开始到目标日期的年、月、日
WHILE #DaysSince1970 >= 365 DO #isLeapYear := (#Year MOD 4 = 0 AND #Year MOD 100 0) OR (#Year MOD 400 = 0); IF #isLeapYear THEN IF #DaysSince1970 >= 366 THEN #DaysSince1970 := #DaysSince1970 - 366; #Year := #Year + 1; END_IF; ELSE #DaysSince1970 := #DaysSince1970 - 365; #Year := #Year + 1; END_IF; END_WHILE;
// 计算当前年的月份和天数
#isLeapYear := (#Year MOD 4 = 0 AND #Year MOD 100 0) OR (#Year MOD 400 = 0); IF #isLeapYear THEN #MonthDays[1] := 29; ELSE #MonthDays[1] := 28; END_IF;
//计算当前年的月份和天数
WHILE #DaysSince1970 >= #MonthDays[#Month] DO #DaysSince1970 := #DaysSince1970 - #MonthDays[#Month]; #Month := #Month + 1; END_WHILE;
//计算当前年、月、日、时、分、秒
#WriteSysTime.Year := #Year; #WriteSysTime.Month := #Month + 1; #WriteSysTime.Day := #DaysSince1970 + 1; #WriteSysTime.Hour := (#CurrentSecond / 3600) MOD 24; #WriteSysTime.Minute := (#CurrentSecond MOD 3600) / 60; #WriteSysTime.Second := #CurrentSecond MOD 60;END_REGION
REGION _SetTime_
//设置时间脉冲沿
#SetTimeU := #SetSysTime AND NOT #SetTimeS; #SetTimeS := #SetSysTime;
//设置系统时间 IF
#SetTimeU THEN
//系统时间转换
#SysTimeW.YEAR := DINT_TO_UINT(#WriteSysTime.Year);
#SysTimeW.MONTH := DINT_TO_USINT(#WriteSysTime.Month);
#SysTimeW.DAY := DINT_TO_USINT(#WriteSysTime.Day);
#SysTimeW.HOUR := DINT_TO_USINT(#WriteSysTime.Hour); #SysTimeW.MINUTE := DINT_TO_USINT(#WriteSysTime.Minute); #SysTimeW.SECOND := DINT_TO_USINT(#WriteSysTime.Second);
//设置系统时间
#ReturnVal1 := WR_LOC_T(LOCTIME := #SysTimeW, DST := #SetDST); END_IF;END_REGION
(日期时间戳互换:Smart Auto Control – WangQuanFuGui 原创
时间戳呢,是从 1970 年 1 月 1 日 8 时 0 分 0 秒开始的,每过一秒就加 1 。
这篇文章里时间戳的计算办法是:先算从 1970 年 1 月 1 日 8 时 0 分 0 秒到现在的总秒数。首先得算出闰年和平年分别有多少个,然后根据年份算出总天数,接着把总天数、现在的小时、现在的分钟分别转换成秒数加起来,最后再加上现在的秒数。)
4、主程序调用:
时间时区设置:UTC(+08:00)北京
新建DB块添加变量
调用时间戳互换FB块、关联变量
5、下载测试:
下载测试1
下载测试2
下载测试3
下载测试4
下载测试5
参考文献《STEP7和WinCC Engineering系统手册》
STEP 7 和 WinCC EngineeringV16-V20
全集成自动化获取 TIA Portal 相关信息的最短途径!
搜索答案-智能支持系统
https://www.ad.siemens.com.cn/service/answer/NewHl/HlSearch.aspx?boardId=1027&cid=1072&lcid=
S7-200SMART快速访问链接
S7-1200-1500 案例之日期时间戳互换 PLC论坛-全力打造可编程控制器专业技术论坛 -
来源:PLC技术玩一点号