Modbus 读写转换

1. 按ushort多字节写入

NModbus 写寄存器API:

C# 复制代码
    public void WriteSingleRegister(byte slaveAddress, ushort registerAddress, ushort value)
    {
        WriteSingleRegisterRequestResponse message = new WriteSingleRegisterRequestResponse(slaveAddress, registerAddress, value);
        base.Transport.UnicastMessage<WriteSingleRegisterRequestResponse>(message);
    }


    public void WriteMultipleRegisters(byte slaveAddress, ushort startAddress, ushort[] data)
    {
        ValidateData("data", data, 123);
        WriteMultipleRegistersRequest message = new WriteMultipleRegistersRequest(slaveAddress, startAddress, new RegisterCollection(data));
        base.Transport.UnicastMessage<WriteMultipleRegistersResponse>(message);
    }

根据不同的设备信号解析类型,大致可以分为:

C# 复制代码
   /// <summary>
   /// 浮点数解析字节序格式
   /// </summary>
   public enum ParseFormat
   {
       /// <summary>
       /// 标准32位:字节顺序 1 2 3 4 = AB CD
       /// </summary>
       ABCD,
       /// <summary>
       /// 字节反转:BA DC
       /// </summary>
       BADC,
       /// <summary>
       /// 高低字交换:CD AB
       /// </summary>
       CDAB,
       /// <summary>
       /// 完全反转:DC BA
       /// </summary>
       DCBA
   }

1.1 float 类型写入

这里主要是把一个 float 转换为对应的 ushort\[\].

C# 复制代码
        /// <summary>
        /// 将 float 按照指定字节序转换为两个 ushort
        /// </summary>
        /// <param name="value">float值</param>
        /// <param name="parseFormat">解析格式ABCD/BADC/CDAB/DCBA</param>
        /// <returns>[高16位, 低16位]</returns>
        private static ushort[] ConvertFloatToTwoUShorts(float value, ParseFormat parseFormat)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            ushort[] result = new ushort[2];

            switch (parseFormat)
            {
                case ParseFormat.ABCD:
                    // 标准:AB  CD
                    result[0] = BitConverter.ToUInt16(bytes, 2);
                    result[1] = BitConverter.ToUInt16(bytes, 0);
                    break;

                case ParseFormat.BADC:
                    // 低16位内部反转:BA  CD
                    result[0] = BitConverter.ToUInt16(bytes, 2);
                    result[1] = ReverseUShort(BitConverter.ToUInt16(bytes, 0));
                    break;

                case ParseFormat.CDAB:
                    // 高低16位互换:CD  AB
                    result[0] = BitConverter.ToUInt16(bytes, 0);
                    result[1] = BitConverter.ToUInt16(bytes, 2);
                    break;

                case ParseFormat.DCBA:
                    // 完全反转:DC  BA
                    result[0] = ReverseUShort(BitConverter.ToUInt16(bytes, 0));
                    result[1] = ReverseUShort(BitConverter.ToUInt16(bytes, 2));
                    break;
            }

            return result;
        }

        /// <summary>
        /// 反转 ushort 的高低字节(B A ↔ A B)
        /// </summary>
        private static ushort ReverseUShort(ushort value)
        {
            return (ushort)((value >> 8) | (value << 8));
        }

1.2 bool 类型写入

这里涉及一点思路转换,把ushort转换为16bits,每个bit对应一个bool状态,更改对应的bit后,得到更新后的ushort值,按照int转换为 ushort\[\]。

C# 复制代码
        private static ushort[] ConvertIntToTwoUShorts(int value)
        {
            byte[] bytes = BitConverter.GetBytes(value);
            return new ushort[]
            {
                BitConverter.ToUInt16(bytes, 0),  // 高16位
                BitConverter.ToUInt16(bytes, 2) // 低16位
            };
        }

2. 按ushort读取解析

NModbus 读寄存器API:

C# 复制代码
 ushort[] ReadHoldingRegisters(byte slaveAddress, ushort startAddress, ushort numberOfPoints);

2.1 解析float类型

一个float占用4个bytes,也就是两个ushort,所以将两个ushort转换为一个float

C# 复制代码
        /// <summary>
        /// 【反向】将两个 ushort 根据指定格式 还原为 float
        /// </summary>
        /// <param name="values">两个ushort:[高16位, 低16位]</param>
        /// <param name="parseFormat">解析格式 ABCD/BADC/CDAB/DCBA</param>
        /// <returns>还原后的float</returns>
        private static float ConvertTwoUShortsToFloat(ushort[] values, ParseFormat parseFormat)
        {
            if (values == null || values.Length != 2)
                throw new ArgumentException("必须传入长度为2的ushort数组");

            ushort high = values[0];
            ushort low = values[1];
            byte[] bytes = new byte[4];

            switch (parseFormat)
            {
                case ParseFormat.ABCD:
                    // AB  CD → 字节顺序 [CD][AB]
                    Buffer.BlockCopy(BitConverter.GetBytes(low), 0, bytes, 0, 2);
                    Buffer.BlockCopy(BitConverter.GetBytes(high), 0, bytes, 2, 2);
                    break;

                case ParseFormat.BADC:
                    // BA  CD → 低字反转,高字不变
                    Buffer.BlockCopy(BitConverter.GetBytes(ReverseUShort(low)), 0, bytes, 0, 2);
                    Buffer.BlockCopy(BitConverter.GetBytes(high), 0, bytes, 2, 2);
                    break;

                case ParseFormat.CDAB:
                    // CD  AB → 高低字互换
                    Buffer.BlockCopy(BitConverter.GetBytes(high), 0, bytes, 0, 2);
                    Buffer.BlockCopy(BitConverter.GetBytes(low), 0, bytes, 2, 2);
                    break;

                case ParseFormat.DCBA:
                    // DC  BA → 高低字都反转
                    Buffer.BlockCopy(BitConverter.GetBytes(ReverseUShort(low)), 0, bytes, 0, 2);
                    Buffer.BlockCopy(BitConverter.GetBytes(ReverseUShort(high)), 0, bytes, 2, 2);
                    break;

                default:
                    throw new NotSupportedException("不支持的解析格式");
            }

            return BitConverter.ToSingle(bytes, 0);
        }

2.2 解析bool类型

这里拿到的依然是一个ushort,然后看该bool量对应的bit在第几位。下面仅列出ushort对应到int的逆向转换。

C# 复制代码
        private static int ConvertTwoUShortsToInt(ushort[] values)
        {
            if (values == null || values.Length != 2)
                throw new ArgumentException("必须传入长度为2的ushort数组");

            byte[] bytes = new byte[4];

            Buffer.BlockCopy(BitConverter.GetBytes(values[0]), 0, bytes, 0, 2);
            Buffer.BlockCopy(BitConverter.GetBytes(values[1]), 0, bytes, 2, 2);

            return BitConverter.ToInt32(bytes, 0);
        }
相关推荐
楠楠子呀2 小时前
独立站聊天转化全链路:从二维码引流到数据复盘
java·javascript·数据仓库·python·c#·自动化·etl
csdn_aspnet2 小时前
C# 第k个最小元素(K’th Smallest Element)
算法·c#·排序算法
影寂ldy3 小时前
Modbus-ASCII 协议 + LRC校验
笔记·网络协议·c#
自己的九又四分之三站台3 小时前
C# 接入 RasterLite2:从原生 DLL 加载到 Coverage、Section、Tile 验证
开发语言·c#·地理信息
好名字都被猪取了-4 小时前
# C# 全栈开发资源包(.NET8/.NET10)
c#
淡海水5 小时前
03-05-线性-Array-List-LinkedList与Span-所有权与成本模型选型
c#·list·编译·array·clr·机器码
瓜皮弟子头很铁5 小时前
使用c#程序打开windows软件
c#
一个帅气昵称啊5 小时前
.Net C# AI智能体开发-AI智能体
人工智能·c#·.net
李高钢1 天前
C# WinForms 架构与项目实战:多窗体通信、三层架构、数据库、日志与配置
架构·c#·winforms
OPEN-F1 天前
Python进阶教程:自动化办公实战
python·c#·自动化