modubs常用8命令协议基础封装

一、区别:tcp比rtu多了事务,协议,长度(前面多6个字节)

ascii和rtu的区别(参考地址:https://blog.csdn.net/b07lxh/article/details/131613977)

/// <summary>
        /// byte[]转换为等效的十六进制字符串,例如byte example = 32,转换字符串为"20"
        /// </summary>
        /// <param name="source">byte[]原数组</param>
        /// <param name="formatStr">转换的格式,默认为十六进制</param>
        private string BytesToHexString(byte[] source)
        {
            StringBuilder pwd = new StringBuilder();
            foreach (byte btStr in source) { pwd.AppendFormat("{0:X2}", btStr); }
            return pwd.ToString();
        }


        //转换为16进制字符串后,组装成ModbusASCII命令格式,首字符为":",末尾字符为回车换行
        string cmdString = ":" + BytesToHexString(command) + "\r\n";
        //把ModbusASCII指令格式转换为等效的byte[]
        byte[] AsciiCmd = Encoding.ASCII.GetBytes(cmdString);

 二、ascii的结果处理:

0x3A是ASCII码的冒号(:);最后两个字符0x0D 0x0A是回车换行符;剩下的是需要处理的数据,和rtu一样

三、tcp常用modbus协议封装发送

 public class ModbusHelp
    {
        #region 功能码
        /// <summary>
        /// 读线圈寄存器
        /// </summary>
        public const byte MB_READ_COILS = 0x01;
        /// <summary>
        /// 读离散输入寄存器
        /// </summary>
        public const byte MB_READ_DISCRETE = 0x02;

        /// <summary>
        /// 读保持寄存器
        /// </summary>
        public const byte MB_READ_HOLD_REG = 0x03;
        /// <summary>
        /// 读输入寄存器
        /// </summary>
        public const byte MB_READ_INPUT_REG = 0x04;

        /// <summary>
        /// 写单个线圈
        /// </summary>
        public const byte MB_WRITE_SINGLE_COIL = 0x05;
        /// <summary>
        /// 写单寄存器
        /// </summary>
        public const byte MB_WRITE_SINGLE_REG = 0x06;

        /// <summary>
        /// 写多线圈
        /// </summary>
        public const byte MB_WRITE_MULTIPLE_COILS = 0x0f;
        /// <summary>
        /// 写多寄存器
        /// </summary>
        public const byte MB_WRITE_MULTIPLE_REGS = 0x10;
        #endregion


        #region 协议
        /// <summary>
        /// 事物处理标识符
        /// </summary>
        public byte[] MB_Thing = new byte[] { 0x00, 0x0B };
        /// <summary>
        /// 协议标识符
        /// </summary>
        public byte[] MB_Agreement = new byte[] { 0x00, 0x00 };
        /// <summary>
        /// 单元标识符
        /// </summary>
        public byte MB_Cell = 0x07;
        #endregion

        #region 请求参数封装
        /// <summary>
        /// 计算数据长度
        /// </summary>
        /// <param name="byteData"></param>
        /// <returns></returns>
        public byte[] GetDataLength(byte[] byteData)
        {
            int leng = byteData.Length;
            return IntToByte(leng);
        }

        /// <summary>
        /// int类型转字节
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public byte[] IntToByte(int data)
        {
            var register = Convert.ToInt16(data);
            //return BitConverter.GetBytes((ushort)IPAddress.HostToNetworkOrder(register));
            return BitConverter.GetBytes(register).Reverse().ToArray();
        }


        /// <summary>
        /// 读线圈寄存器
        /// </summary>
        /// <param name="state">读取位置</param>
        /// <param name="places">读取多少位</param>
        /// <returns></returns>
        public List<byte> ReadModbusCoils(int state, int places)
        {
            return ReadModbusSingleData(state, places, MB_READ_COILS);
        }

        /// <summary>
        /// 读离散输入寄存器
        /// </summary>
        /// <param name="state">读取位置</param>
        /// <param name="places">读取多少位</param>
        /// <returns></returns>
        public List<byte> ReadModbusDiscrete(int state, int places)
        {

            return ReadModbusSingleData(state, places, MB_READ_DISCRETE);
        }

        /// <summary>
        /// 读保持寄存器
        /// </summary>
        /// <param name="state">读取位置</param>
        /// <param name="places">读取多少位</param>
        /// <returns></returns>
        public List<byte> ReadModbusHoldReg(int state, int places)
        {
            return ReadModbusSingleData(state, places, MB_READ_HOLD_REG);
        }

        /// <summary>
        /// 读输入寄存器
        /// </summary>
        /// <param name="state">读取位置</param>
        /// <param name="places">读取多少位</param>
        /// <returns></returns>
        public List<byte> ReadModbusInputReg(int state, int places)
        {
            return ReadModbusSingleData(state, places, MB_READ_INPUT_REG);
        }

        /// <summary>
        /// 1,2,3,4 请求是一样的
        /// </summary>
        /// <param name="state"></param>
        /// <param name="places"></param>
        /// <param name="fcode"></param>
        /// <returns></returns>
        public List<byte> ReadModbusSingleData(int state, int places, byte fcode)
        {
            List<byte> SendCommand = new List<byte>();
            //事物处理标识符
            SendCommand.AddRange(MB_Thing);
            //协议标识符
            SendCommand.AddRange(MB_Agreement);
            //长度
            SendCommand.AddRange(new byte[] { 0x00, 0x06 });
            //单元标识符
            SendCommand.Add(MB_Cell);
            //功能码
            SendCommand.Add(fcode);
            //起始地址
            SendCommand.AddRange(IntToByte(state));
            //结束地址-长度
            SendCommand.AddRange(IntToByte(places));
            return SendCommand;
        }

        /// <summary>
        /// 写单个线圈
        /// </summary>
        /// <param name="state">读取位置</param>
        /// <param name="places">读取多少位</param>
        /// <returns></returns>
        public List<byte> WriteModbusCoil(int index, int value)
        {
            List<byte> SendCommand = new List<byte>();
            //事物处理标识符
            SendCommand.AddRange(MB_Thing);
            //协议标识符
            SendCommand.AddRange(MB_Agreement);
            //长度
            SendCommand.AddRange(new byte[] { 0x00, 0x06 });
            //单元标识符
            SendCommand.Add(MB_Cell);
            //功能码
            SendCommand.Add(MB_WRITE_SINGLE_COIL);
            //起始地址
            SendCommand.AddRange(IntToByte(index));
            //写入数据
            SendCommand.AddRange(value == 1 ? new byte[] { 0xff, 0x00 } : new byte[] { 0x00, 0x00 });
            return SendCommand;
        }

        /// <summary>
        /// 写单寄存器
        /// </summary>
        /// <param name="state">读取位置</param>
        /// <param name="places">读取多少位</param>
        /// <returns></returns>
        public List<byte> WriteModbusSingleReg(int index, int value)
        {
            List<byte> SendCommand = new List<byte>();
            //事物处理标识符
            SendCommand.AddRange(MB_Thing);
            //协议标识符
            SendCommand.AddRange(MB_Agreement);
            //长度
            SendCommand.AddRange(new byte[] { 0x00, 0x06 });
            //单元标识符
            SendCommand.Add(MB_Cell);
            //功能码
            SendCommand.Add(MB_WRITE_SINGLE_REG);
            //起始地址
            SendCommand.AddRange(IntToByte(index));
            //写入数据
            SendCommand.AddRange(IntToByte(value));
            return SendCommand;
        }

        /// <summary>
        /// 写入多个线圈器
        /// </summary>
        /// <param name="index">位置</param>
        /// <param name="values"></param>
        /// <returns></returns>
        public List<byte> WriteModbusMultipleCoils(int index, List<int> values)
        {
            //写入的值
            List<byte> SendCommand = new List<byte>();
            //事物处理标识符
            SendCommand.AddRange(MB_Thing);
            //协议标识符
            SendCommand.AddRange(MB_Agreement);
            //长度
            SendCommand.AddRange(new byte[] { 0x00, 0x08 });
            //单元标识符
            SendCommand.Add(MB_Cell);
            //功能码
            SendCommand.Add(MB_WRITE_MULTIPLE_COILS);
            //起始地址
            SendCommand.AddRange(IntToByte(index));
            //写入的数量
            SendCommand.AddRange(IntToByte(values.Count()));
            //写入数据字节
            SendCommand.Add(0x01);
            string str = "";//数据要反转
            for (int i = values.Count - 1; i >= 0; i--)
            {
                if (values[i] == 1)
                    str += "1";
                else
                    str += "0";
            }
            SendCommand.Add(Convert.ToByte(str, 2));
            return SendCommand;
        }

        /// <summary>
        /// 写入多个寄存器
        /// </summary>
        /// <param name = "index" > 位置 </ param >
        /// < param name="values"></param>
        /// <returns></returns>
        public List<byte> WriteModbusMultipleRegs(int index, List<int> values)
        {
            //写入的值
            List<byte> valueByte = new List<byte>();
            foreach (var it in values)
            {
                valueByte.AddRange(IntToByte(it));
            }
            byte[] valueLeng = BitConverter.GetBytes(Convert.ToInt16(valueByte.Count()));
            valueByte.Insert(0, valueLeng.FirstOrDefault());

            List<byte> SendCommand = new List<byte>();
            //事物处理标识符
            SendCommand.AddRange(MB_Thing);
            //协议标识符
            SendCommand.AddRange(MB_Agreement);

            //长度
            SendCommand.AddRange(IntToByte(valueByte.Count() + 6));

            //单元标识符  1
            SendCommand.Add(MB_Cell);
            //功能码  1
            SendCommand.Add(MB_WRITE_MULTIPLE_REGS);
            //写入位置 2
            SendCommand.AddRange(IntToByte(index));
            //写入寄存器数量
            SendCommand.AddRange(IntToByte(values.Count()));
            //写入的值
            SendCommand.AddRange(valueByte);
            return SendCommand;
        }
        #endregion

        /// <summary>
        /// 处理返回的值
        /// </summary>
        /// <param name="buffer"></param>
        public void HandelByte(byte[] buffer, int length = 0)
        {
            int count = buffer.Count();
            if (buffer[7] == 0x01 || buffer[7] == 0x02)//读取多个  读取的个数  
            {
                string binaryString = Convert.ToString(buffer[9], 2);
                var values = binaryString.ToCharArray().ToList();//这个判断有问题
                int vl = values.Count;
                if (vl != length)
                {
                    for (int i = 0; i < length - vl; i++)
                        values.Insert(0, '0');
                }
                values.Reverse();
                string str = string.Join(",", values);
                Console.WriteLine(str);//线圈的状态
            }
            else if ( buffer[7] == 0x03 || buffer[7] == 0x04)//读取多个
            {
                var data = BitConverter.ToUInt16(buffer, 0);
                int l = buffer[8] / 2;
                ShowData(buffer, l);
            }
            else if (buffer[7] == 0x05 || buffer[7] == 0x06)//写入单个寄存器
            {
                //解析
                ushort[] data = new ushort[1];
                data[0] = BitConverter.ToUInt16(new byte[] { buffer[11], buffer[10] }, 0);
                Console.WriteLine(data);//写入的值
            }
            else if (buffer[7] == 0x0f || buffer[7] == 0x10)//写入多个寄存器
            {
                //解析
                ushort[] data = new ushort[1];
                data[0] = BitConverter.ToUInt16(new byte[] { buffer[11], buffer[10] }, 0);
                Console.WriteLine(data);//写入的个数
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="length"></param>
        /// <param name="j"></param>
        private void ShowData(byte[] buffer, int length)
        {
            //解析
            ushort[] data = new ushort[length];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = BitConverter.ToUInt16(new byte[] { buffer[9 + 2 * i + 1], buffer[9 + 2 * i] }, 0);
            }
            Console.WriteLine(data);
        }
    }

 

posted @ 2024-07-30 18:02  世人皆萌  阅读(61)  评论(0编辑  收藏  举报