返回
愁死了!S7-1214C DC/DC/DC。 程序里有一个存放设定值的 DB 块(非掉电保持)。 运行中发现,这个 DB 里的实数(Real)偶尔会自己变动。比如我设定的 50.0,跑着跑着突然变成了
发布

愁死了!S7-1214C DC/DC/DC。 程序里有一个存放设定值的 DB 块(非掉电保持)。 运行中发现,这个 DB 里的实数(Real)偶尔会自己变动。比如我设定的 50.0,跑着跑着突然变成了

18阅读 1 回复 2026-04-19 12:07发布
关注Ta

156142970667普通会员楼主

电话/手机:联系客服

西门子 S7-1200:DB块数据“无故漂移 愁死了!S7-1214C DC/DC/DC。
程序里有一个存放设定值的 DB 块(非掉电保持)。
运行中发现,这个 DB 里的实数(Real)偶尔会自己变动。比如我设定的 50.0,跑着跑着突然变成了 50.00002 或者 49.99998。
重点:

全程序搜索了,除了触摸屏写入,没有任何地方写这个地址。

触摸屏上我也没动。

虽然误差很小,但导致我后面的比例运算逻辑报错。
为什么静态的 DB 块数据会自己‘抖动’?难道是 CPU 内部浮点数运算的 Bug,还是内存溢出窜位了?

以下内容回复后可见

优质评论内容

  • 明扬工控技术客服

    明扬工控技术客服2026-04-19 12:10:25

    这个现象大概率不是 CPU 坏了,也不像内存窜位。

    更像是你这个 DB 里的数据类型用了 Real,而 Real 本身就是 32 位单精度浮点数。西门子文档里写得很明确,S7 1200 的 Real 按 IEEE 754 单精度浮点方式存储,精度大约就是 6 位有效数字左右,不是所有十进制小数都能被精确表示。像 50.0 这种在显示上看起来是整整齐齐的数,参与一次运算、搬移、类型转换或者 HMI 读写后,内部都可能变成最接近它的那个浮点值,于是你就会看到 50.00002 或 49.99998 这种很小的偏差。这个现象属于浮点数特性,不是 1200 的 Bug。

    所以先说结论,你这个“自己抖动”更像是下面这种情况之一。第一,HMI 写入 50.0 后,PLC 里按浮点格式保存,显示时暴露了近似值。第二,这个变量虽然你没直接改,但后面如果参与了任何 Real 运算,再写回原地址,也会出现极小偏差。第三,如果你的逻辑里用了 Real 和别的类型互相转换,比如 Int 转 Real,或者做比例、乘除、归一化,再写回设定值地址,也会出现这种现象。

    真正需要重视的不是这个微小变化本身,而是你后面的逻辑“拿 Real 做精确相等比较”或者对这个微小误差过于敏感。浮点数不适合直接判断“是否绝对等于 50.0”。如果你后面的比例运算或判断是按精确相等来的,就很容易被这种 0.00002 级别的偏差触发异常。这个方向比怀疑内存溢出更靠谱。

    你可以这样改,现场最实用。

    第一种办法,设定值不要用 Real 存,改成整数存。比如把 50.0 放大 10 倍或 100 倍,存成 500 或 5000,运算时再换算。只要你的工艺允许,这是最稳的办法。

    第二种办法,如果必须用小数,就把类型改成 LReal。西门子文档里说明了,LReal 是 64 位双精度,精度明显高很多,能把这种微小误差再压小不少。

    第三种办法,所有判断都不要写成“等于 50.0”,而要写成“在一个容差范围内”。比如判断是否等于 50,可以改成判断这个值是否落在 49.99 到 50.01 之间。这样最符合浮点数的实际用法。

    第四种办法,HMI 写入后如果你希望程序里始终只保留固定小数位,可以在 PLC 里做一次统一取整或定标处理,再存入内部变量,不要让原始 Real 值一路直接参与后续控制。

    如果你现在看到的是 50.0 变成 50.00002 这种量级,我反而觉得说明问题基本正常。真要是内存窜位,通常不会这么“规矩”,而会跳成很离谱的值,比如几十变几千,或者直接出现 NaN、极大极小值、通信异常之类。你这个偏差非常像标准浮点误差。

    一句话总结就是,问题大概率不在 CPU,也不在 DB 自己乱改,而在 Real 这种数据类型天生就不是“精确十进制数”。你后面的逻辑需要改成适合浮点数的写法。