字节转换算法应用_读取本地时间

文章目录


前言

西门子博途编程平台中,可以使用RD_LOC_T指令读取本地时间。调用该指令时,其输出的变量可选择DTL或Date_And_Time数据类型。

本文将对RD_LOC_T指令的使用方法进行阐述,并详细对比DTL和Date_And_Time数据类型在程序处理中的区别,同时对字节和整型数据类型之间的转换方法进行讲解。


一、功能概述

  1. 读取本地时间;
  2. 读取DTL类型变量中的年、月、日、星期、时、分、秒等数据;
  3. 读取Date_And_Time类型变量中的年、月、日、星期、时、分、秒等数据。

二、程序编写

1. 组态

打开设备视图,选择CPU的属性-时间,将时区改为(UTC+08:00)北京时间。

2. 新建FB块"FB617_SYSTIME"

本程序仅作为实验验证,用于阐述DTL和Date_And_Time数据类型在编程上的区别。

建立如下引脚变量:

图1

其中,变量"SystemTimeByte"仅作为"SystemTimeDT"的拆分,不占用存储空间。使用AT指令,将其拆分为8个字节,用于读取不同字节的数据。AT指令的使用方法,详见文章《十二、SCL核心应用课项目实战_运行设备累计功能实现》

"TempByte"作为"SystemTimeByte"数组的映射,仅用于DB块监控。

3. 编程

1. DTL类型

图2

首先使用DTL类型变量,下载程序,打开自动生成的背景数据块并监控,如图3所示。

图3

可以看到,DTL类型的变量占用12个字节,输出的值包含以下数据。若想使用某个数据,直接在程序中调用对应变量即可。

c 复制代码
 Year: WORD;     // 年 (1-9999)
 Month: BYTE;    // 月 (1-12)
 Day: BYTE;      // 日 (1-31)
 Weekday: BYTE;  // 星期 (1=周日, 7=周六)
 Hour: BYTE;     // 时 (0-23)
 Minute: BYTE;   // 分 (0-59)
 Second: BYTE;   // 秒 (0-59)
 Nanosecond: DWORD; // 纳秒 (0-999,999,999)

2. Date_And_Time类型

同理,将DTL类型变量替换为Date_And_Time类型变量,再次下载程序,监控DB块数据,如图5所示。

图4

图5

可以看到,DT类型的变量占用8个字节,其中每个字节都以 BCD 码形式存储日期时间的各个部分。相较于DTL类型变量,无法直接读取相应的年、月、日、星期、时、分、秒等数据,需要通过编写程序进行拆分。

3. Date_And_Time类型变量拆分

如图1所示,我们已将Date_And_Time类型变量拆分成了8个Byte类型变量组成的数组。对应字节存储以下信息:

c 复制代码
字节0-1: 年(后两位,范围1990-2089)
字节2: 月
字节3: 日
字节4: 小时
字节5: 分钟
字节6: 秒
字节7: 星期(高4位为0,低4位表示星期几,其中1表示周日,2表示周一,...,7表示周六)

已知,星期数据存储在最后一个字节(即第 8 个字节,索引为 7)的低4位中,而对于其他字节(比如年份、月份等),每个字节存储两个BCD数字(高4位和低4位各代表一个数字)。故数据提取思路如下:

  1. 将DT转换为字节数组,以便访问每个字节,使用AT指令实现;
  2. 对于星期数据,将#SystemTimeByte[7]与16#0F进行"与"运算;
  3. 具体原理:16#0F是十六进制数,转换为二进制是0000 1111,当用一个字节(8位)的数据和16#0F进行AND运算时,高4位会与0000相与,结果一定是0;低4位与1111相与,结果保持原来的值,故可以得到存储星期信息的低4位字节数据;
  4. 而对于其它数据,需要分别提取高4位和低4位,然后组合起来;
  5. 具体方法:对于每个字节,拆分为高4位和低4位,高4位定义为字节为0,低4位定义为字节1,分别提取字节0和字节1的低4位数据(与16#0F进行AND操作);
  6. 其中,高4位数据,使用"右移位"指令将其移至低4位,然后与16#0F进行AND操作;
  7. 最后,将字节0的低4位乘以10,加上字节1的低4位,得到实际的两位数数据;
  8. 注意:年数据只有年份信息,没有世纪信息,如果要加上世纪信息,需要进一步编程处理,具体方法见代码。

代码如下:

c 复制代码
REGION 提取年份
    
    // Date_And_Time只支持1990-2089年
    // 如果提取的两位数≥90:年份 = 1900 + 两位数
    // 如果提取的两位数<90:年份 = 2000 + 两位数
    
    #TempTens := (SHR(IN := #SystemTimeByte[0], N := 4)) AND 16#0F;
    #TempOnes := #SystemTimeByte[0] AND 16#0F;
    #Year := (#TempTens * 10) + #TempOnes;
    
    IF #Year >= 90 THEN
        #Year := 1900 + #Year;
    ELSE
        #Year := 2000 + #Year;
    END_IF;
    
END_REGION

REGION 提取月份
    
    #TempTens := (SHR(IN := #SystemTimeByte[1], N := 4)) AND 16#0F;
    #TempOnes := #SystemTimeByte[1] AND 16#0F;
    #Month := (#TempTens * 10) + #TempOnes;
    
END_REGION

REGION 提取日期
    
    #TempTens := (SHR(IN := #SystemTimeByte[2], N := 4)) AND 16#0F;
    #TempOnes := #SystemTimeByte[2] AND 16#0F;
    #Day := (#TempTens * 10) + #TempOnes;
    
END_REGION

REGION 提取小时
    
    #TempTens := (SHR(IN := #SystemTimeByte[3], N := 4)) AND 16#0F;
    #TempOnes := #SystemTimeByte[3] AND 16#0F;
    #Hour := (#TempTens * 10) + #TempOnes;
    
END_REGION

REGION 提取分钟
    
    #TempTens := (SHR(IN := #SystemTimeByte[4], N := 4)) AND 16#0F;
    #TempOnes := #SystemTimeByte[4] AND 16#0F;
    #Minute := (#TempTens * 10) + #TempOnes;
    
END_REGION

REGION 提取秒钟
    
    #TempTens := (SHR(IN := #SystemTimeByte[5], N := 4)) AND 16#0F;
    #TempOnes := #SystemTimeByte[5] AND 16#0F;
    #Second := (#TempTens * 10) + #TempOnes;
    
END_REGION

REGION 提取星期
    
    // 星期信息存储在最后一个字节(即第 8 个字节,索引为 7)的低4位中
    // 1表示周日,2表示周一,...,7表示周六
    #Weekday := BYTE_TO_INT(#SystemTimeByte[7] AND 16#0F);
    
END_REGION

三、数据类型对比

特性 DTL Date_And_Time(DT)
适用版本 S7-1200/1500 新数据类 S7-300/400 传统类型
字节大小 12字节 8字节
时间精度 纳秒
日期范围 1-01-01 到 9999-12-31 1990-01-01 到 2089-12-31
存储方式 结构化数据 BCD编码的紧凑格式
兼容性 仅S7-1200/1500 S7-300/400/1200/1500

总的来说,DTL类型适用于:

  1. S7-1200/1500新项目;

  2. 需要高精度时间戳;

  3. 需要大范围日期(跨越世纪);

  4. 需要结构化访问日期时间各部分。
    Date_And_Time类型适用于:

  5. 兼容旧项目(S7-300/400);

  6. 与旧系统通信;

  7. 只需要秒级精度;

  8. 节省存储空间。


总结

本文主要对博途RD_LOC_T指令的使用方法进行了讲解,同时详细对比分析了DTL和Date_And_Time数据类型的优缺点。其中,Date_And_Time类型读取时间信息时涉及到的字节转换算法,需要格外注意。

相关推荐
永远都不秃头的程序员(互关)1 天前
【K-Means深度探索(二)】K值之谜:肘部法则与轮廓系数,如何选出你的最佳K?
算法·机器学习·kmeans
玄冥剑尊1 天前
回溯算法深化 II
算法·回溯算法
Tisfy1 天前
LeetCode 3453.分割正方形 I:二分查找
算法·leetcode·二分查找·题解·二分
漫随流水1 天前
leetcode算法(101.对称二叉树)
数据结构·算法·leetcode·二叉树
源代码•宸1 天前
Golang原理剖析(string面试与分析、slice、slice面试与分析)
后端·算法·面试·golang·扩容·string·slice
派森先生1 天前
排序算法-冒泡排序
算法·排序算法
静心问道1 天前
排序算法分类及实现
算法·排序算法
2301_764441331 天前
python实现罗斯勒吸引子(Rössler Attractor)
开发语言·数据结构·python·算法·信息可视化
码农三叔1 天前
(7-3)自动驾驶中的动态环境路径重规划:实战案例:探险家的行进路线
人工智能·算法·机器学习·机器人·自动驾驶
飞Link1 天前
【Water】数据增强中的数据标注、数据重构和协同标注
算法·重构·数据挖掘