news 2026/6/13 23:40:55

(七) YModbus寄存器类型转换:int、float、double和字节序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(七) YModbus寄存器类型转换:int、float、double和字节序

GitHub 项目地址:https://github.com/lidecong133/YModbus

保持寄存器读出来是ushort[]

这很符合 Modbus 协议,但不太符合人看数据的习惯。

现场你想看的通常不是16856这种原始寄存器值,而是温度23.5、压力1.25、计数器123456。这些值在设备内部可能是整数缩放,也可能是float,还可能是 32 位或 64 位整数。

所以读寄存器只是第一步。第二步是把寄存器解释成人能看懂的值。

先确认它到底是什么类型

一个 Modbus 寄存器是 16 位,也就是 2 个字节。

类型常见占用
short/ushort1 个寄存器
int/uint2 个寄存器
float/Single2 个寄存器
long/ulong4 个寄存器
double4 个寄存器

如果手册写温度是float32,一般就要读两个寄存器。

ushort[]registers=awaitclient.ReadHoldingRegistersAsync(100,2);

如果手册写温度是UINT16,倍率 0.1,那就只读一个寄存器,然后自己除以 10。

这两种处理方式完全不同。

比例系数不是字节序

这个坑很常见。

设备显示23.5,寄存器读出来是235,这时候不要急着按float解析。

它很可能只是整数缩放:

ushortraw=(awaitclient.ReadHoldingRegistersAsync(100,1))[0];decimaltemperature=raw/10m;

字节序解决的是“几个字节怎么拼成一个类型”。

比例系数解决的是“原始数值怎么换算成工程量”。

这两个问题不要混在一起。混在一起以后,现场就会开始盲试:一会儿换字节序,一会儿换地址,一会儿换功能码,最后哪个改动生效都说不清。

再看字序和字节序

如果设备确实存的是floatint32,那就要看顺序。

一个float占 4 个字节,比如:

41 BC 00 00

放进两个寄存器时,可能是:

寄存器 0: 41 BC 寄存器 1: 00 00

也可能是:

寄存器 0: 00 00 寄存器 1: 41 BC

YModbus 把它拆成两个参数:

参数说明
ModbusWordOrder多个 16 位寄存器之间,哪个字在前
ModbusByteOrder一个寄存器内部,高字节还是低字节在前

常见组合是HighWordFirst+BigEndian,但不能假定所有设备都这样。

直接读成 typed 值

如果你只想读一个 typed 值,可以用扩展方法。

float

usingYModbus.Clients;usingYModbus.Protocol;floattemperature=awaitclient.ReadHoldingRegisterSingleAsync(startAddress:100,wordOrder:ModbusWordOrder.HighWordFirst,byteOrder:ModbusByteOrder.BigEndian);

int32

intcounter=awaitclient.ReadHoldingRegisterInt32Async(startAddress:120,wordOrder:ModbusWordOrder.LowWordFirst,byteOrder:ModbusByteOrder.BigEndian);

输入寄存器也有对应方法:

floatpressure=awaitclient.ReadInputRegisterSingleAsync(startAddress:0,wordOrder:ModbusWordOrder.HighWordFirst,byteOrder:ModbusByteOrder.BigEndian);

区别只是功能码不同。保持寄存器走03,输入寄存器走04

批量读完再转换

实际项目里,我更常用另一种方式:先读一段寄存器,再按地址表解析。

例如你一次读 100 个保持寄存器,里面有温度、压力、状态字、计数器。每个字段单独发请求,效率低,也不方便保持同一时刻的数据。

这时候用RegisterConverter

usingYModbus.Protocol;ushort[]registers=awaitclient.ReadHoldingRegistersAsync(100,20);floattemperature=RegisterConverter.ToSingle(registers.AsSpan(0,2).ToArray(),ModbusWordOrder.HighWordFirst,ModbusByteOrder.BigEndian);intcounter=RegisterConverter.ToInt32(registers.AsSpan(2,2).ToArray(),ModbusWordOrder.LowWordFirst,ModbusByteOrder.BigEndian);

写入时也可以反过来转:

ushort[]values=RegisterConverter.FromSingle(23.5F,ModbusWordOrder.HighWordFirst,ModbusByteOrder.BigEndian);awaitclient.WriteMultipleRegistersAsync(100,values);

怎么判断顺序对不对

最稳的办法是找一个已知值。

比如设备屏幕显示温度23.5,你读出来两个寄存器。然后用不同组合解析,看哪个结果接近23.5

可以临时这样试:

foreach(ModbusWordOrderwordOrderinEnum.GetValues<ModbusWordOrder>()){foreach(ModbusByteOrderbyteOrderinEnum.GetValues<ModbusByteOrder>()){floatvalue=RegisterConverter.ToSingle(registers,wordOrder,byteOrder);Console.WriteLine($"{wordOrder},{byteOrder}:{value}");}}

如果某个组合解析出来是4.17E-41这种离谱值,基本就不是它。

但这个办法只是为了确认设备格式。确认以后,最好把格式写进地址表,不要每次靠试。

地址表里要记录格式

一个可维护的地址表,至少应该记录这些东西:

字段示例
地址100
功能码03
数据类型Float32
字序HighWordFirst
字节序BigEndian
比例系数1.0
单位
名称当前温度

只记录“地址”和“名称”是不够的。等项目过几个月再维护,谁也不记得当时这个值为什么要低字在前,为什么要除以 10。

写入 typed 值要更谨慎

读错,通常只是显示不对。

写错,可能会改设备参数。

YModbus 有 typed write helper:

awaitclient.WriteHoldingRegisterSingleAsync(startAddress:100,value:23.5F,wordOrder:ModbusWordOrder.HighWordFirst,byteOrder:ModbusByteOrder.BigEndian);

int32

awaitclient.WriteHoldingRegisterInt32Async(startAddress:120,value:123456,wordOrder:ModbusWordOrder.LowWordFirst,byteOrder:ModbusByteOrder.BigEndian);

真正对设备写之前,先确认地址可写、数值范围安全、字序字节序和手册一致。最好写完以后再读回一次,确认设备里实际变成了什么。

到这里

寄存器转换不是 YModbus 特有的问题,是 Modbus 本身就这样。

YModbus 能帮你做两件事:

  • 直接用 typed helper 读写intfloatdouble
  • RegisterConverter在批量读出的寄存器上做转换

但设备到底是整数缩放、还是 IEEE754 浮点数,字序怎么排,比例系数是多少,还是要回到设备手册和现场验证。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/13 23:40:16

3PEAK思瑞浦 TPR8601-EV1R-S EMSOP8 特殊功能电路

特性 优异匹配性 TPR86xxA:在-40C至125C范围内匹配度为0.0125% TPR86xx:在-40C至125C范围内匹配度为0.025% .匹配温度漂移:0.1ppm/C工作温度范围:-40C至125C

作者头像 李华
网站建设 2026/6/13 23:37:04

揭秘AI图层分离神器:layerdivider如何让设计师告别手动抠图

揭秘AI图层分离神器&#xff1a;layerdivider如何让设计师告别手动抠图 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider layerdivider是一款基于AI的智能图…

作者头像 李华
网站建设 2026/6/13 23:36:56

Elsevier Tracker:科研工作者的审稿进度智能监控解决方案

Elsevier Tracker&#xff1a;科研工作者的审稿进度智能监控解决方案 【免费下载链接】Elsevier-Tracker 项目地址: https://gitcode.com/gh_mirrors/el/Elsevier-Tracker Elsevier Tracker是一款专为科研作者设计的Chrome浏览器插件&#xff0c;它能够实时监控Elsevie…

作者头像 李华
网站建设 2026/6/13 23:24:58

RTKLIB实时PPP定位保姆级教程:从Ntrip账号注册到RTK Monitor界面详解

RTKLIB实时PPP定位从入门到精通&#xff1a;手把手实战指南与深度解析 在卫星导航定位领域&#xff0c;实时精密单点定位&#xff08;PPP&#xff09;技术正逐渐成为高精度应用的新标准。不同于传统的RTK技术需要基准站支持&#xff0c;PPP仅需单台接收机即可实现厘米级定位&a…

作者头像 李华