首页 / 新闻资讯 / PLC浮点数字节序排查
技术分享

PLC浮点数读上来要么错值要么离谱?字节序与字交换排查实录

三菱PLC浮点数字节序与字交换解析
← 返回新闻列表

PLC上位机软件读整数都正常,一读浮点数就显示几百万、上亿,甚至直接崩掉——十有八九是字节序在作怪。一个32位Real占两个16位寄存器,不同品牌PLC和通讯网关对这两个字、四个字节的排列顺序各不相同。找准排列方式、配好字交换,离谱错值立刻恢复正常。

为什么偏偏浮点数最容易翻车?

整数读错,多数情况下数值还在可理解的范围。浮点数不行,它按IEEE754规则编码:符号位、指数位、尾数位被重新解释后,一个字节错位就能把25.6变成几百万。所以现场看到“数值大得离谱”“小数点乱飞”,先别怀疑公式,先怀疑字节序。

32位数据由两个寄存器(俗称高字、低字)组成,两个字内部各有两个字节。字的先后和字节的先后一组合,就有四种排列:

- ABCD:标准大端,字节和字都不交换;
- CDAB:只交换两个字(最常见的坑);
- BADC:字内交换字节;
- DCBA:字和字节全部翻转,即小端。

西门子S7直连通常是ABCD;大量Modbus设备、串口服务器和网关吐出来的是CDAB。具体到某台设备,手册可能写得含糊,别赌,实测最靠谱。

怎么用一个已知值,十秒钟判定字节序?

写入特征值再抓包

我惯用的办法是往寄存器里写一个特征明显的值,比如12.5。它的IEEE754编码是0x41480000,两个字节00辨识度极高。用Wireshark或串口监听工具抓一次报文,看返回的四个字节实际排列:

- 回来是41 48 00 00,ABCD直接解析;
- 回来是00 00 41 48,做一次字交换(CDAB);
- 回来是48 41 00 00,做字节交换(BADC);
- 回来是00 00 48 41,全部翻转(DCBA)。

没有写权限的表计,就找一个已知的稳定值,比如电表屏幕上显示的电压220.3,拿它的编码0x435C4CCD去报文里对,一样能反推出排列方式。

字交换逻辑应该写在哪里?

最忌讳的做法,是在业务代码里到处写BitConverter.IsLittleEndian和数组反转,换台设备就得改代码。我的习惯是把字节序策略下沉到点表层:

- 点表里每台设备、甚至每个点配置一个序型字段,取值ABCD/CDAB/BADC/DCBA;
- 驱动层拿到两个寄存器后,统一按序型重排,再交给BitConverter.ToSingle;
- 32位整数(DInt、UDInt)走同一套重排逻辑,浮点和整数的坑一次填平。

同一个车间里,西门子直连的点用ABCD、经网关的电表用CDAB,这种混搭只要点表配置对,上层代码完全无感。

类型解析还藏着哪些暗坑?

顺手把几个高频问题也记一下:

1. 有符号和无符号。寄存器到底是Int16还是UInt16要问清楚,功率因数这类量用无符号解析才不会出现负几万;
2. 定点小数。不少设备用Int16存温度、约定除以10,倍率和偏移也放点点表里;
3. Bool位序。个别协议位编号方向相反,状态量全反时往这查;
4. 非法值。通讯失败残留的字节可能拼出NaN或Infinity,解析后要做有效性判断,别让脏值进了曲线和报表。

我之前调试过一批温控表,上位机温度清一色显示几百万,按CDAB做字交换后全部正常;同一项目的电量模块却是32位整数要字交换、浮点数不用——这种“同柜不同命”的情况,只有配置化才能优雅收场。

今天找一台“数值离谱”的设备,往保持寄存器写入12.5,抓一次报文对照0x41480000的排列,四选一立刻见分晓。把结论固化进点表,这类故障以后不会再浪费你一个下午。需要支持多品牌多字节序的PLC上位机通讯框架,可以找我们拿方案:免费咨询,或致电 13761638786。

← 上一篇 WPF上位机一采集就界面卡死?跨线程刷新UI的三种写法和适用场景

有软件开发需求?

专业顾问1对1咨询,30分钟出方案,让您的想法快速落地