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

文章目录


前言

西门子博途编程平台中,可以使用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. 对于星期数据,将#SystemTimeByte7与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类型读取时间信息时涉及到的字节转换算法,需要格外注意。

相关推荐
aaaameliaaa4 分钟前
进制练习题【找出只出现一次的数字、交换两个变量(不创建临时变量)、统计二进制中1的个数、打印整数二进制的奇数位和偶数位、求两个数二进制中不同位的个数】
c语言·数据结构·笔记·算法
QiLinkOS2 小时前
第三视觉理解徐玉生与他的商业活动(28)
大数据·c++·人工智能·算法·开源协议
wabs6662 小时前
关于动态规划【力扣1143.最长公共子序列的思考】
算法·leetcode·动态规划
剑挑星河月3 小时前
54.螺旋矩阵
java·算法·leetcode·矩阵
Robot_Nav3 小时前
MPPI 局部规划器实验设计讲解
人工智能·算法·mppi
mingo_敏3 小时前
Mean-Teacher 均值教师自训练框架详解
算法·均值算法
星空露珠4 小时前
迷你世界UGc3.0脚本Wiki[剧情动画模块管理接口 Timeline]
开发语言·数据结构·算法·游戏·lua
笨笨没好名字4 小时前
Leetcode刷题python3版第一周(下)
linux·算法·leetcode
jinyishu_4 小时前
常见排序算法详解
数据结构·算法·排序算法
手写码匠4 小时前
手写 LLM 安全护栏:从内容审核到越狱防御的完整实现
人工智能·深度学习·算法·aigc