BeckHoff(倍福)PLC 获取系统时间---GetCpuCounter

一、在倍福PLC里,获取系统时间,首先要添加库 Tc2_system,因为需要用到GETCPUCOUNTER功能块

二、实例化功能块

FUNCTION F_TIME_V1_0_0 : TIME

VAR

	fbSystemTick			:FW_GetCpuCounter;(* Instance of function block for time measuring *)
	udiTemp_TimeLow			:UDINT;(* Low DW of Timestamp *)
	udiTemp_TimeHigh		:UDINT;(* High DW of Timestamp*)

	dwTemp_TimeHighDW		:DWORD;(* temp variable for reset of 19 Bit of High DWORD *)
	udiTemp_TimeHighCalc	:UDINT;(* temp variable for the value of Bits in ms*)
	udiTemp_TimeSum			:UDINT;(* temp variable for added systemticks in ms *)

	udiTemp_Calc			:UDINT;(* temp variable for computing sytemticks in ms *)

END_VAR
(*All VAR_IN_OUT variables have been moved to the end of the declaration due to compatibility reasons*)
VAR_IN_OUT
END_VAR

三、以下代码实现了将系统高精度时钟转换为可读的时间格式(毫秒级),解决因数据类型限制导致的时间溢出问题。

(* Call of function block *)
fbSystemTick(	dwCpuCntLo => udiTemp_TimeLow,
				dwCpuCntHi => udiTemp_TimeHigh);

(* Overflow of LowWord  each 7 Minutes! Therefor take for used time both DW *)

(* Change first Bits of HighDW von 100ns to 1ms *)
udiTemp_Calc := 4294967295 / 10000;


(* Length of UDINT Variable is not lage enough. Therefore delete first 19 Bit of High DW *)
dwTemp_TimeHighDW := UDINT_TO_DWORD(udiTemp_TimeHigh);

dwTemp_TimeHighDW := SHL(dwTemp_TimeHighDW, 19);
dwTemp_TimeHighDW := SHR(dwTemp_TimeHighDW, 19);

udiTemp_TimeHighCalc := DWORD_TO_UDINT(dwTemp_TimeHighDW);

(* Whole Ticks is sum of LowDW and High DW*)
udiTemp_TimeSum := (udiTemp_TimeLow/10000)+(udiTemp_TimeHighCalc * udiTemp_Calc);

(* Output of Timestamp as TIME in ms *)
F_TIME_V1_0_0 := UDINT_TO_TIME(udiTemp_TimeSum);

3.1、代码分析

3.1.1 系统时钟读取
fbSystemTick(	dwCpuCntLo => udiTemp_TimeLow,
				dwCpuCntHi => udiTemp_TimeHigh);
  • 功能:调用系统功能块fbSystemTick获取高精度时钟计数。
  • 输出参数
    • udiTemp_TimeLow(低 32 位):存储时钟计数的低字部分(单位:100ns)。
    • udiTemp_TimeHigh(高 32 位):存储时钟计数的高字部分(单位:100ns)。
  • 问题:低字部分每约 7 分钟(2^32 × 100ns ≈ 429 秒)溢出一次,需结合高字计算完整时间。
3.1.2. 高字数据预处理
udiTemp_Calc := 4294967295 / 10000;  // 常量:429,496.7295

dwTemp_TimeHighDW := UDINT_TO_DWORD(udiTemp_TimeHigh);
dwTemp_TimeHighDW := SHL(dwTemp_TimeHighDW, 19);  // 左移19位
dwTemp_TimeHighDW := SHR(dwTemp_TimeHighDW, 19);  // 右移19位(清除低19位)
udiTemp_TimeHighCalc := DWORD_TO_UDINT(dwTemp_TimeHighDW);
  • 目的:处理高字数据,消除低精度位的干扰。
  • 关键操作
    1. 位运算:通过SHLSHR清除高字数据的低 19 位(保留高 13 位有效信息)。
    2. 精度转换:将高字部分从 100ns 精度转换为 1ms 精度(通过udiTemp_Calc常量缩放)。
3. 1.3 组合高低字并转换单位
udiTemp_TimeSum := (udiTemp_TimeLow/10000)+(udiTemp_TimeHighCalc * udiTemp_Calc);
F_TIME_V1_0_0 := UDINT_TO_TIME(udiTemp_TimeSum);
  • 时间计算逻辑
    1. 低字部分udiTemp_TimeLow/10000 将 100ns 转换为 ms(1ms = 10,000 × 100ns)。
    2. 高字部分udiTemp_TimeHighCalc * udiTemp_Calc 将高字缩放为 ms 单位。
    3. 合并结果:两部分相加得到总毫秒数。
  • 输出:通过UDINT_TO_TIME转换为标准TIME类型变量F_TIME_V1_0_0

3.2 关键技术点

  1. 溢出处理
    • 利用高字数据扩展时间范围,避免每 7 分钟溢出。
    • 实际有效时间范围:约 2^45 × 100ns ≈ 35.7 年(高 13 位 + 低 32 位)。
  2. 精度与性能平衡

    • 清除高字低 19 位:减少计算量,同时保留足够精度(误差 < 0.5ms)。
    • 常量udiTemp_Calc预计算:优化运行时性能。
  3. 数据类型适配

    • 使用DWORD中间变量处理位运算(SHL/SHR仅支持DWORD)。
    • TIME类型最大值为 24 天 20 小时 31 分钟 23.647 秒,适用于大多数工业场景。

3.3 应用场景

  • 高精度计时:测量设备响应时间、循环周期。
  • 长时间监控:记录设备累计运行时间(避免频繁重置计数器)。
  • 事件追溯:生成精确到毫秒级的时间戳,用于故障诊断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三阶码叟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值