问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C#与PLC通讯时的浮点数数据处理:读取与写入的字节转换详解

创作时间:
作者:
@小白创作中心

C#与PLC通讯时的浮点数数据处理:读取与写入的字节转换详解

引用
CSDN
1.
https://blog.csdn.net/weixin_52473844/article/details/144232540

在工业自动化领域,使用C#与PLC(可编程逻辑控制器)通过ModbusTCP协议进行通讯时,浮点数数据的读取和写入是一个常见的技术问题。本文将详细介绍如何处理这一问题,并提供具体的代码实现方案。

在与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通讯的浮点数问题已经解决。如有疑问,欢迎讨论。

本文原文来自CSDN

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号