C#与PLC通讯时,数据读取和写入浮点数,字节转换问题(ModbusTCP)

发布于:2024-12-05 ⋅ 阅读:(79) ⋅ 点赞:(0)

在与PLC进行通讯时,会发现一个问题,浮点数1.2接收过来后,居然变成了两个16位的整数。
在这里插入图片描述
经过一系列的分析,这是因为在PLC存储浮点数时32位,我们接收过来的数据会变成两个16位的高低字节,而且我们进行下发数据时,也需要进行转换,否则PLC那边的数据会乱码。
我这边使用的资源包是NModbus来实现ModbusTCP通讯的,可以根据自己的需求进行下载程序包。如果是其他的通讯方式遇到字节转换问题,可也以直接用核心代码。
在这里插入图片描述
现在开始上核心代码

读取数据浮点数处理

在这里插入图片描述
从104的点位开始读取了11位的数据,01、23 、45则是读取的浮点数转换为的高低字节,这时候我们需要封装一个方法 ConvertRegistersToDecimal 进行数据处理。
这里大家需要注意一下,浮点数float是32位,double是64位,decimal是128位,因为我这边的浮点数是decimal,所以进行了强制转换,如果没有强制转换的话则是32位float。

 private decimal ConvertRegistersToDecimal(ushort highPart,ushort lowPart)
  {
      decimal result = (decimal)BitConverter.ToSingle(new byte[]
          {
      (byte)(highPart & 0xFF),
      (byte)((highPart >> 8) & 0xFF),
      (byte)(lowPart & 0xFF),
      (byte)((lowPart >> 8) & 0xFF)
      }, 0);
      return result;// Incorrect, just for illustration
  }

还有一点需要注意,字节的顺序不要写错,比如[0]和[1]。

写入浮点数数据处理

这里和读取的概念一样,有一点需要再次强调一下,浮点数float是32位,double是64位,decimal是128位,因为我这边的浮点数是decimal,所以进行了强制转换,如果没有强制转换的话则是32位float。
我们这里进行转换时,记得把浮点数转变为32位float类型。我这里用的时decimal,转成了float。
在这里插入图片描述
我们在写入数据时需要进行一下数据处理,封装一个ConvertDecimalToRegisters方法,我这里用的时decimal,转成了float。

 private ushort[] ConvertDecimalToRegisters(decimal value)
 {
     float floatValue = (float)value; // 示例值
     

     // 将浮点数转换为字节数组(注意:这里假设PLC期望的是IEEE 754标准的32位浮点数)
     byte[] floatBytes = BitConverter.GetBytes(floatValue);
     // 发送浮点数到PLC(注意:这里假设NModbus库支持直接发送浮点数,如果不支持,则需要手动拆分字节并发送到两个16位寄存器中)
     // 但是,请注意,NModbus实际上并不直接支持写入浮点数到单个寄存器地址。
     // 你需要将其拆分为两个16位值或使用支持浮点数的库扩展。
     // 正确的做法应该是:
     ushort[] registerValues = new ushort[2];
     if (BitConverter.IsLittleEndian)
     {
         registerValues[0] = (ushort)((floatBytes[2] << 8) | floatBytes[3]); // 高16位(对于小端字节序)
         registerValues[1] = (ushort)((floatBytes[0] << 8) | floatBytes[1]); // 低16位(对于小端字节序)
     }
     else
     {
         registerValues[0] = (ushort)((floatBytes[0] << 8) | floatBytes[1]); // 高16位(对于大端字节序,但不常见)
         registerValues[1] = (ushort)((floatBytes[2] << 8) | floatBytes[3]); // 低16位(对于大端字节序,但不常见)
     }
     ushort[] a = { BitConverter.ToUInt16(floatBytes, 0), BitConverter.ToUInt16(floatBytes, 2) };
     return a;

 }

到此我们的与PLC通讯的浮点数问题已经解决,如有疑问,欢迎大家商讨。
小白路漫漫,让我们一起加油!!!


网站公告

今日签到

点亮在社区的每一天
去签到