S7-1200-1500 案例之日期时间戳互换

一:相关软(硬)件:

1、编程软件:TIA_V15.1

2、仿真软件:PLCSIM

二:控制要求:

1、将日期时间转换为时间戳,例如:2024年9月2日16:51:21转换为时间戳:1725267081;

2、将时间戳转换为日期时间,例如:1725267081转换为日期时间:2024年9月2日16:51:21;

本文时间戳计算方法:计算1970年1月1日8时0分0秒以来的时间总秒数,首先计算闰年与平年个数,根据年份计算出总天数,再将总天数、当前小时、当前分钟分别别转换为秒数后相加,再加上当前的秒数。 

注:程序仅供参考!!! 

三、时间时间戳互换:

新建项目、新建UDT、新建FB块、添加变量、编写程序、调用FB块、关联变量、下载测试

1、新建自定义数据类型(UDT_SysTime):

新建UDT数据类型

2、新建FB块(Timestamp Swap):

建立变量表1

建立变量表2

3、编写程序:

读取系统时间

日期转换为时间戳

时间戳转换为日期

设置系统时间

完整程序:

    (*
    日期时间戳互换:Smart Auto Control -- WangQuanFuGui 原创
    时间戳:自197011800秒为时间戳的开始时间,每过一秒加1
    本文时间戳计算方法:计算197011800秒以来的时间总秒数,
    首先计算闰年与平年个数,根据年份计算出总天数,再将总天数、当前小时、当前分钟分别别转换为秒数后相加,再加上当前的秒数。
    *)
    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 原创
    时间戳:自197011800秒为时间戳的开始时间,每过一秒加1
    本文时间戳计算方法:计算197011800秒以来的时间总秒数,
    首先计算闰年与平年个数,根据年份计算出总天数,再将总天数、当前小时、当前分钟分别别转换为秒数后相加,再加上当前的秒数。
    *)

    4、主程序调用:

    时间时区设置:UTC(+08:00)北京

    新建DB块添加变量

    调用时间戳互换FB块、关联变量

    5、下载测试:

    下载测试1

    下载测试2

    下载测试3

    下载测试4

    下载测试5

    注:程序仅供参考!!! 

    (参考文章:S7-1200 -1500 案例之日期转换时间戳

    (参考文章:S7-1200 -1500 案例之读取设置本地时间

    (参考文章:S7-1200 -1500案例之设备维护倒计时

    (参考文章:S7-200 SMART 案例之设备轮询控制优化) 

    感谢您点赞、分享、给小编加鸡腿。

    如需程序源码请打赏小编或私信留言。

    参考文献《STEP7和WinCC Engineering系统手册》

    STEP 7 和 WinCC EngineeringV16-V20

    游客,如果您要查看本帖隐藏内容请回复
    全集成自动化获取 TIA Portal 相关信息的最短途径!

    https://docs.tia.siemens.cloud/

    搜索答案-智能支持系统

    https://www.ad.siemens.com.cn/service/answer/NewHl/HlSearch.aspx?boardId=1027&cid=1072&lcid=

    S7-200SMART快速访问链接

    https://w2.siemens.com.cn/smart/


    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?注册哦

    x
    主题回复
    倒序浏览

    525查看2回复

    風雲 2025-5-13 21:45:48
    好!感谢分享!1111111111
    lizhendongplc 2025-6-20 12:37:08
    太好了,支持一下,谢谢
    发新帖
    您需要登录后才可以回帖 登录 | 注册哦

    本版积分规则

    上一主题上一主题         下一主题下一主题