每周一个编程小例子:16 进制到浮点数的神奇转换
引言
在工业自动化领域,PLC 工程师经常需要处理底层设备传来的原始数据。当遇到将两个 16 位寄存器合并解释为 32 位浮点数(REAL)的需求时,如何高效实现呢?本文将通过一个精妙的双字转换技术,揭秘 PLC 中 16 进制到浮点数的转换奥秘。
1 程序代码及解析
下面是完整的 PLC 程序代码(代码基于 CodeSys 平台的 ST 语言):
- FUNCTION_BLOCK FB_HexToReal
- VAR_INPUT
- HWd : WORD; // 高位字(如寄存器40001)
- LWd : WORD; // 低位字(如寄存器40002)
- END_VAR
- VAR_OUTPUT
- RealOutput : REAL; // 输出的浮点数
- END_VAR
- VAR
- hexLWd : DWORD; // 临时高位双字
- hexDw : DWORD; // 组合后的双字
- pConverter : POINTER TO REAL; // 类型转换指针
- END_VAR
- // --- 核心转换逻辑 ---
- hexLWd := HWd; // 高位字存入双字变量
- hexDw := SHL(hexLWd, 16) + LWd; // 高位左移16位后与低位拼接
- pConverter := ADR(hexDw); // 获取双字内存地址
- RealOutput := pConverter^; // 通过指针重新解释为浮点数
2 关键技术点解析
双字拼接:
SHL(hexLWd, 16) + LWd将高位字左移 16 位,再与低位字相加,形成完整的 32 位双字(DWORD)。
内存重解释:
通过POINTER TO REAL指针直接读取双字内存,将其二进制内容解释为 IEEE 754 浮点数格式。
无转换损耗:
相比传统数学运算转换,该方法直接操作内存,零精度损失且执行效率极高。
3 典型应用场景
设备通信解析
解析 Modbus/TCP 设备传来的浮点数(占用两个连续寄存器),例如温度变送器、流量计数据。
上位机数据对接
处理 SCADA 系统下发的浮点数据包,如设定值、PID 参数等。
历史数据重组
从数据库读取存储为两个 WORD 的浮点历史数据,还原为实际工程值。
案例:温度控制系统从传感器读取到HWd=16#4120和LWd=16#0000,经本程序转换后输出RealOutput=10.0(摄氏度)。
4 拓展思考
安全增强:增加范围校验防止非法值(如 NaN):
- IF hexDw <> 16#FFC00000 THEN // 排除NaN
- RealOutput := pConverter^;
- ELSE
- RealOutput := 0.0;
- END_IF
支持多数据类型:扩展功能块以兼容 LREAL(64 位浮点数):
- hexDw := SHL(HWd, 48) + SHL(MWd, 32) + SHL(LWd_H, 16) + LWd_L;
字节序问题:若设备字节序与 PLC 不一致,需调整拼接顺序:
- hexDw := SHL(LWd, 16) + HWd; // 小端模式
总结
本文展示的FB_HexToReal功能块通过内存指针重解释技术,实现了两个 16 位寄存器到浮点数的无损高效转换。该方法:
-
执行速度快:仅需 4 条关键指令
-
资源占用低:无额外数学运算
-
精度有保障:避免传统乘除法的舍入误差
在工业通信协议解析、跨系统数据交互等场景中,这种"二进制直译"思维能大幅提升开发效率。掌握内存操作技巧,将使你在 PLC 编程中如虎添翼!
思考题:如何修改此程序,使其能处理 64 位双精度浮点数?欢迎在评论区分享你的方案!
你来出题 我来答
欢迎大家在评论区提一些标准功能块的需求,如果合适,我们会在以后的文章中与大家分享。
往期回顾
每周一个编程小例子 :Bit 到 Word 转换的两种实现方案对比
2025年08月