【问题标题】:Modbus TCP Little Endian Byte SwopModbus TCP Little Endian 字节交换
【发布时间】:2022-01-28 01:25:33
【问题描述】:

我正在使用 FluentModbus,也尝试过 EasyModbus,与 Delta SE CPU 通信,只要我读/写单个寄存器,我就可以正常通信,问题是我需要转换为 Little Endian ByteSwap 才能访问 PLC Doubles 和Floats,用我不久前为 excel 购买的 ModbussPoll 对此进行了测试。

有什么办法可以解决这个问题吗?

谢谢

【问题讨论】:

  • 请用您使用的语言标记它(我猜是针对.NET)
  • 对于 EasyModbus 看一下ConvertRegistersToFloat; re FluentModbus 看起来有一些ongoing work 在这上面。不幸的是,由于 Modbus 标准没有涵盖这一点,如果上述方法没有帮助,您可能需要实施自己的解决方案(简单的 modbus 源应该为您指明正确的方向)。

标签: .net modbus-tcp


【解决方案1】:

感谢您的帮助。

这行得通

var ReadunitIdentifier = (byte)0xFF;
        var ReadstartingAddress = (ushort)40;
        var Readcount = (ushort)4;

       
        if (modbusTcpClient.IsConnected)
        {
            try
            {
                var byteData = modbusTcpClient.ReadHoldingRegisters<byte>(ReadunitIdentifier, ReadstartingAddress, Readcount);
                byte highByte0 = byteData[0];
                byte lowByte0 = byteData[1];
                byte highByte1 = byteData[2];
                byte lowByte1 = byteData[3];
                byte[] doubleBytes =
                {
                    lowByte0, highByte0,lowByte1,highByte1
                };
                SharedVariables.LoadcellScaled = BitConverter.ToInt32(doubleBytes, 0);
            }

【讨论】:

    【解决方案2】:

    v2.1.0 版本开始,您应该能够提供服务器的字节布局(小端与大端):

    var client = new ModbusTcpClient(...);
    client.Connect(..., ModbusEndianness.BigEndian);
    
    var value = client.ReadHoldingRegisters<float>(...);
    

    使用ModbusEndianness.BigEndian,您告诉客户端期待一个大端服务器,这将使客户端根据客户端的操作系统架构(主要是小端)重新排序字节。

    【讨论】:

    • 谢谢,我在 LittleEndian 设置了它,但仍然需要执行 byteswop。
    • 对不起,我不够清楚。请尝试ModbusEndianness.BigEndian 告诉小端客户端服务器在其 Modbus 消息中使用大端字节布局。这应该消除手动交换字节的必要性。
    【解决方案3】:

    注意 - 我上面读到的大部分内容都令人困惑和困惑。

    Modbus 通常使用“大/小端”来指代它传输更大 32 位(或原则上更大)值的 16 位卡盘的顺序。

    几乎所有的 Modbus 都不会在每个 16 位值内交换字节。

    所以如果你有一个十六进制值 0x33221100,字节序是关于你发送两个寄存器值 0x3322 和 0x1100 的顺序

    一些 Modbus 软件包将支持“字节交换”,因此您可以将 16 位值 0x3322 作为 16 位值 0x2233 发送。 如果您将接收到的两个寄存器放在相邻位置的 x86 内存中,这可能会有一些价值 - 然后告诉程序将其解释为 32 位整数。

    但在遇到这种可笑的做事方式之前,我们设法使用 Modbus 外围设备工作了 15 年。

    现在,如果您是一个真正的极客,并开始考虑位和字节在串行总线上上下传输的顺序,您可以认为自己进入了一个大黑洞。不用管它,考虑完整的 16 位 Modbus 寄存器值。

    【讨论】:

    • Modbus 标准为寄存器(16 位值)指定了 big-Endian 表示,因此这些不应该成为问题(库会为您解决这个问题)。但是,该标准不涵盖更大的值,因此如果您需要组合多个 16 位寄存器(例如,组合成一个 32 位整数或浮点数),那么字节序肯定很重要。由于大多数用户将轮询由其他人设计的设备,因此您必须对给定的任何内容进行解码,这是我经常遇到的问题(例如,仅处理编码为 CDAB 的 32 位浮点数)。
    • 这不是混淆字节字节序和字字节序吗?字节字节序会影响您读取单个 16 位寄存器的方式,但字字节序会影响您读取 32 位值的方式(如果我理解正确,这只是两个 16 位寄存器)
    猜你喜欢
    • 2012-10-09
    • 2018-12-09
    • 2010-10-16
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多