每周一个编程小例子:16 进制到浮点数的神奇转换

引言

在工业自动化领域,PLC 工程师经常需要处理底层设备传来的原始数据。当遇到将两个 16 位寄存器合并解释为 32 位浮点数(REAL)的需求时,如何高效实现呢?本文将通过一个精妙的双字转换技术,揭秘 PLC 中 16 进制到浮点数的转换奥秘。

程序代码及解析

下面是完整的 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^;    // 通过指针重新解释为浮点数

关键技术点解析

双字拼接
SHL(hexLWd, 16) + LWd将高位字左移 16 位,再与低位字相加,形成完整的 32 位双字(DWORD)。

内存重解释
通过POINTER TO REAL指针直接读取双字内存,将其二进制内容解释为 IEEE 754 浮点数格式。

无转换损耗
相比传统数学运算转换,该方法直接操作内存,零精度损失且执行效率极高。

典型应用场景

设备通信解析
解析 Modbus/TCP 设备传来的浮点数(占用两个连续寄存器),例如温度变送器、流量计数据。

上位机数据对接
处理 SCADA 系统下发的浮点数据包,如设定值、PID 参数等。

历史数据重组
从数据库读取存储为两个 WORD 的浮点历史数据,还原为实际工程值。

案例:温度控制系统从传感器读取到HWd=16#4120和LWd=16#0000,经本程序转换后输出RealOutput=10.0(摄氏度)。

拓展思考

安全增强:增加范围校验防止非法值(如 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 转换的两种实现方案对比

每周一个编程小例子:记录设备运行时间

每周一个编程小例子:基于长按检测的启动控制系统

每周一个编程小例子:探秘 PLC 数据记录功能块

每周一个编程小例子:心跳检测与 PLC 应用

每周一个编程小例子:斜坡发生器

每周一个编程小例子:旋转速度计算

每周一个编程小例子:计算 PLC 循环周期|例程需求征集!

每周一个编程小例子:如何优雅的分割字符串

每周一个编程小例子:带反馈的阀门控制程序

每周一个编程小例子:西门子 LGF 库中的脉冲继电器功能块

每周一个编程小例子:曲线加减速的控制应用

每周一个编程小例子:轻松去除字符串前导字符

每周一个编程小例子:根据阈值更新输入

每周一个编程小例子:官方模拟量输入处理模块

每周一个编程小例子:主从电机的时序控制

每周一个编程小例子:基于一阶滞后滤波的优化方案

图片

2025年08月

Tags: