使用C#实现ModbusTCP通信

公共方法

 public class Common
  {
      /// <summary>
      /// 生成CRC校验码
      /// </summary>
      /// <param name="data"></param>
      /// <returns>返回CRC校验码</returns>
      public static byte[] CRC16(List<byte> data)
      {
          //CRC校验的基本步骤如下:

          //1.预置:CRC寄存器预置为0xFFFF。
          //2.数据输入:报文中除了CRC校验码以外的所有字节(包括设备地址、功能码和数据)按照顺序进行处理。
          //4.计算:对每一个字节,从最高位到最低位,将其与CRC寄存器当前的值进行异或运算。如果结果的最高位为1,则将寄存器的值左移一位并与0x8005进行异或运算;如果最高位为0,则只需左移一位。重复此过程,直至8位都处理完毕。然后继续处理下一个字节,直到所有字节都计算完毕。
          //4.结果:最后CRC寄存器中的值就是CRC校验码,通常在传输前转换为低字节在前(Little - Endian)的形式,并附加到报文的末尾。

          //当接收方收到报文时,会对整个报文(包括CRC校验码)使用相同的CRC计算流程。如果报文未被篡改,计算结果应为0x0000(考虑到了CRC码的加入和计算规则)。如果结果不是0x0000,则表明报文在传输过程中可能遭到了篡改或出现了错误。

          //运算
          ushort crc = 0xFFFF;
          for (int i = 0; i < data.Count; i++)
          {
              crc = (ushort)(crc ^ (data[i]));
              for (int j = 0; j < 8; j++)
              {
                  crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
              }
          }
          byte hi = (byte)((crc & 0xFF00) >> 8);  //
          byte lo = (byte)(crc & 0x00FF);         //

          return [lo, hi];
      }

      /// <summary>
      /// 错误码
      /// </summary>
      public static Dictionary<byte, string> ErrorCodes = new Dictionary<byte, string>
      {
          { 0x01, "非法的功能码"},
          { 0x02, "非法的数据地址"},
          { 0x03, "非法的数据值"},
          { 0x04, "从设备/服务器故障"},
          { 0x05, "确认,从设备/服务器需要一个耗时操作"},
          { 0x06, "从设备/服务器繁忙"},
          { 0x0A, "网关故障"},
          { 0x0B, "网关目标设备未能响应"},
      };
  }

枚举

    /// <summary>
    /// 大小端模式
    /// </summary>
    public enum Endian
    { 
        /// <summary>
        /// 大端
        /// </summary>
        BigEndian,

        /// <summary>
        /// 小端
        /// </summary>
        LittleEndian

    }

    /// <summary>
    /// 功能码
    /// </summary>
    public enum FuncCode
    {
        ReadCoils=0x01,
        ReadDiscreteInputs = 0x02,
        ReadHoldingRegisters = 0x03,
        ReadInputRegisters = 0x04,
        WriteSingleCoil= 0x05,
        WriteSingleRegister = 0x06,
        WriteMultipleCoil = 0x0F,
        WriteMultipleRegisters = 0x10,
    }

 

 

ModbusTCP协议封装

    /// <summary>
    /// ModbusTCP协议封装
    /// </summary>
    public class ModbusTCP
    {
        private Socket _socket;
        private static readonly object lockObj = new object();

        public ModbusTCP(Socket socket)
        {
            _socket = socket;
        }

        #region 功能码0x01 0x02
        /// <summary>
        /// 功能码0x01 0x02
        /// </summary>
        /// <param name="funcCode">功能码。只支持01、02</param>
        /// <param name="startAddress">起始地址</param>
        /// <param name="count">读取数量</param>
        /// <returns>bool数组</returns>
        public bool[] ReadBools(FuncCode funcCode, short startAddress, short count)
        {
            if (funcCode != FuncCode.ReadCoils && funcCode != FuncCode.ReadDiscreteInputs)
            {
                throw new Exception("该方法只支持功能码01、02");
            }

            //1.发送请求(send)
            //2.获取响应数据(receive)
            //3.分析返回结果。返回bool[]
            //3.1 校验
            //3.2 如果通过,取出数据并bool[]

            lock (lockObj)
            {
                #region 1.发送请求
                //发送的bytes
                List<byte> sendBytes = GetReadBytes(funcCode, startAddress, count);

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                int readCount = (int)Math.Ceiling(count * 1.0 / 8) + 9;//读取字节个数
                List<byte> receiveBytes = GetReceiveBytes(readCount);

                #endregion

                #region 3.分析返回结果。返回bool[]
                //3.1 校验
                ExceptionCheck(sendBytes, receiveBytes);

                //3.2 如果通过,取出数据并bool[]
                List<byte> dataBytes = receiveBytes.GetRange(9, readCount - 9);
                bool[] tempBool = new bool[dataBytes.Count * 8];//临时变量

                for (int i = 0; i < dataBytes.Count; i++)
                {
                    for (int j = 0; j < 8; j++)
                    {
                        //判断第j位是否为1
                        tempBool[i * 8 + j] = (dataBytes[i] & (1 << j)) != 0;
                    }
                }

                bool[] result = new bool[count];//最终结果
                Array.Copy(tempBool, result, count);
                return result;
                #endregion
            }
        }
        #endregion

        #region 写单线圈 功能码0x05
        /// <summary>
        /// 写单线圈 功能码0x05
        /// </summary>
        /// <param name="startAddress">起始地址</param>
        /// <param name="value">写的值</param>
        public void WriteSingleCoil(short startAddress, bool value)
        {
            lock (lockObj)
            {
                //1.发送请求
                //2.获取响应数据
                //3.校验
                #region 1.发送请求

                byte[] writeValueBytes = value ? [0xFF, 0x00] : [0x00, 0x00];//写入的值bytes

                List<byte> sendBytes = GetSingleWriteBytes(FuncCode.WriteSingleCoil, startAddress, writeValueBytes);

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                List<byte> receiveBytes = GetReceiveBytes(12);
                #endregion

                #region 3.校验
                ExceptionCheck(sendBytes, receiveBytes);
                #endregion
            }
        }
        #endregion

        #region 写多线圈 功能码0x0F
        /// <summary>
        /// 写多线圈 功能码0x0F
        /// </summary>
        /// <param name="startAddress">起始地址</param>
        /// <param name="values">写的多个值</param>
        public void WriteMultipleCoil(short startAddress, bool[] values)
        {
            //1.发送请求
            //2.获取响应数据
            //3.校验
            lock (lockObj)
            {
                #region 1.发送请求
                byte[] valueCountBytes = BitConverter.GetBytes(values.Length);//值的个数bytes
                int bytesCount = (int)Math.Ceiling(values.Length * 1.0 / 8);//写入的字节个数
                                                                            //发送的bytes
                                                                            //将bool[]转成byte[]
                BitArray bitArray = new BitArray(values);
                byte[] writeBytes = new byte[bytesCount];
                bitArray.CopyTo(writeBytes, 0);

                List<byte> sendBytes = GetMultipleWriteBytes(FuncCode.WriteMultipleCoil, startAddress, valueCountBytes, (byte)bytesCount, writeBytes);

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                List<byte> receiveBytes = GetReceiveBytes(12); //读取字节个数12
                #endregion

                #region 3.校验
                ExceptionCheck(sendBytes, receiveBytes);
                #endregion
            }
        }
        #endregion

        #region 读保持寄存器(16位)  功能码0x03 0x04
        /// <summary>
        /// 读保持寄存器(16位)  功能码0x03 0x04
        /// </summary>
        /// <param name="funcCode">功能码。只支持03、04</param>
        /// <param name="startAddress">开始地址</param>
        /// <param name="count">要读的数字个数</param>
        /// <returns>数字数组</returns>
        /// <exception cref="Exception"></exception>
        public short[] ReadReg16(FuncCode funcCode, short startAddress, short count)
        {
            if (funcCode != FuncCode.ReadHoldingRegisters && funcCode != FuncCode.ReadInputRegisters)
            {
                throw new Exception("该方法只支持功能码03、04");
            }

            //1.发送请求
            //2.获取响应数据
            //3.分析返回结果。返回short[]
            //3.1 校验
            //3.2 如果通过,取出数据并short[]

            lock (lockObj)
            {
                #region 1.发送请求

                //发送的bytes
                List<byte> sendBytes = GetReadBytes(funcCode, startAddress, count);

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                int readCount = count * 2 + 9;//读取字节个数

                List<byte> receiveBytes = GetReceiveBytes(readCount);

                #endregion

                #region 3.分析返回结果。返回short[]
                //3.1 校验
                ExceptionCheck(sendBytes, receiveBytes);

                //3.2 如果通过,取出数据并short[]
                List<byte> dataBytes = receiveBytes.GetRange(9, readCount - 9);

                short[] result = new short[count];
                for (int i = 0; i < count; i++)
                {
                    //BitConverter 只支持小端
                    List<byte> curBytes = dataBytes.GetRange(i * 2, 2);
                    curBytes.Reverse();
                    result[i] = BitConverter.ToInt16(curBytes.ToArray());
                }

                return result;
                #endregion
            }
        }
        #endregion

        #region 读保持寄存器(32位 int)  功能码0x03 0x04
        /// <summary>
        /// 读保持寄存器(32位)  功能码0x03 0x04
        /// </summary>
        /// <param name="startAddress">开始地址</param>
        /// <param name="count">要读的数字个数</param>
        /// <param name="endian">大小端模式。默认大端</param>
        /// <returns>数字数组</returns>
        /// <exception cref="Exception"></exception>
        public int[] ReadReg32Int(FuncCode funcCode, short startAddress, short count, Endian endian = Endian.BigEndian)
        {
            if (funcCode != FuncCode.ReadHoldingRegisters && funcCode != FuncCode.ReadInputRegisters)
            {
                throw new Exception("该方法只支持功能码03、04");
            }
            //1.发送请求
            //2.获取响应数据
            //3.分析返回结果。返回int[]
            //3.1 校验
            //3.2 如果通过,取出数据并int[]

            lock (lockObj)
            {
                #region 1.发送请求
                //发送的bytes
                List<byte> sendBytes = GetReadBytes(funcCode, startAddress, (short)(count * 2));

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                int readCount = count * 4 + 9;//读取字节个数

                List<byte> receiveBytes = GetReceiveBytes(readCount);

                #endregion

                #region 3.分析返回结果。返回int[]
                ExceptionCheck(sendBytes, receiveBytes);

                //3.2 如果通过,取出数据并int[]
                List<byte> dataBytes = receiveBytes.GetRange(9, readCount - 9);

                int[] result = new int[count];
                for (int i = 0; i < count; i++)
                {
                    //BitConverter 只支持小端
                    List<byte> curBytes = dataBytes.GetRange(i * 4, 4);
                    if (endian == Endian.BigEndian)
                    {
                        curBytes.Reverse();
                    }
                    result[i] = BitConverter.ToInt32(curBytes.ToArray());
                }

                return result;
                #endregion
            }
        }
        #endregion

        #region 读保持寄存器(32位 float)  功能码0x03 0x04
        /// <summary>
        /// 读保持寄存器(32位 float)  功能码0x03 0x04
        /// </summary>
        /// <param name="startAddress">开始地址</param>
        /// <param name="count">要读的数字个数</param>
        /// <param name="endian">大小端模式。默认大端</param>
        /// <returns>数字数组</returns>
        /// <exception cref="Exception"></exception>
        public float[] ReadReg32Float(FuncCode funcCode, short startAddress, short count, Endian endian = Endian.BigEndian)
        {
            //1.发送请求
            //2.获取响应数据
            //3.分析返回结果。返回int[]
            //3.1 校验
            //3.2 如果通过,取出数据并int[]
            lock (lockObj)
            {
                #region 1.发送请求

                //发送的bytes
                List<byte> sendBytes = GetReadBytes(funcCode, startAddress, (short)(count * 2));

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                int readCount = count * 4 + 9;//读取字节个数

                List<byte> receiveBytes = GetReceiveBytes(readCount);

                #endregion

                #region 3.分析返回结果。返回short[]
                //3.1 校验
                ExceptionCheck(sendBytes, receiveBytes);

                //3.2 如果通过,取出数据并int[]
                List<byte> dataBytes = receiveBytes.GetRange(9, readCount - 9);

                float[] result = new float[count];
                for (int i = 0; i < count; i++)
                {
                    //BitConverter 只支持小端
                    List<byte> curBytes = dataBytes.GetRange(i * 4, 4);
                    if (endian == Endian.BigEndian)
                    {
                        curBytes.Reverse();
                    }
                    result[i] = BitConverter.ToSingle(curBytes.ToArray());
                }

                return result;
                #endregion
            }
        }
        #endregion

        #region 写单个寄存器 功能码0x06
        /// <summary>
        /// 写单个寄存器 功能码0x06
        /// </summary>
        /// <param name="startAddress">起始地址</param>
        /// <param name="value">写的多个值</param>
        public void WriteSingleReg(short startAddress, short value)
        {
            //1.发送请求
            //2.获取响应数据
            //3.校验
            lock (lockObj)
            {
                #region 1.发送请求

                byte[] valueBytes = BitConverter.GetBytes(value).Reverse().ToArray();//小端

                List<byte> sendBytes = GetSingleWriteBytes(FuncCode.WriteSingleRegister, startAddress, valueBytes);

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                List<byte> receiveBytes = GetReceiveBytes(12); //读取字节个数
                #endregion

                #region 3.校验
                ExceptionCheck(sendBytes, receiveBytes);
                #endregion
            }
        }
        #endregion

        #region 写多个寄存器(32位int) 功能码0x10
        /// <summary>
        /// 写多个寄存器(32位int) 功能码0x10
        /// </summary>
        /// <param name="startAddress">起始地址</param>
        /// <param name="values">写的多个值</param>
        /// <param name="endian">大小端</param>
        public void WriteMultipleReg32Int(short startAddress, int[] values, Endian endian = Endian.BigEndian)
        {
            //1.发送请求
            //2.获取响应数据
            //3.校验
            lock (lockObj)
            {
                #region 1.发送请求

                byte[] regCountbytes = BitConverter.GetBytes(values.Length * 2);

                //发送的bytes
                List<byte> valuesBytes = new List<byte>();//值的byte集合
                foreach (int i in values)
                {
                    byte[] curBytes = BitConverter.GetBytes(i);//小端
                    if (endian == Endian.BigEndian)//如果是大端
                    {
                        curBytes = curBytes.Reverse().ToArray();
                    }

                    valuesBytes.AddRange(curBytes);
                }

                List<byte> sendBytes = GetMultipleWriteBytes(FuncCode.WriteMultipleRegisters, startAddress, regCountbytes, (byte)(values.Length * 4), valuesBytes.ToArray());

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                List<byte> receiveBytes = GetReceiveBytes(12); //读取字节个数
                #endregion

                #region 3.校验
                ExceptionCheck(sendBytes, receiveBytes);
                #endregion
            }
        }
        #endregion

        #region 写多个寄存器(32位float) 功能码0x10
        /// <summary>
        /// 写多个寄存器(32位float) 功能码0x10
        /// </summary>
        /// <param name="startAddress">起始地址</param>
        /// <param name="values">写的多个值</param>
        /// <param name="endian">大小端</param>
        public void WriteMultipleReg32Float(short startAddress, float[] values, Endian endian = Endian.BigEndian)
        {
            lock (lockObj)
            {
                //1.发送请求
                //2.获取响应数据
                //3.校验
                #region 1.发送请求
                byte[] startBytes = BitConverter.GetBytes(startAddress);

                byte[] regCountbytes = BitConverter.GetBytes(values.Length * 2);

                //发送的bytes
                List<byte> valuesBytes = new List<byte>();
                foreach (float i in values)
                {
                    byte[] curBytes = BitConverter.GetBytes(i);//小端
                    if (endian == Endian.BigEndian)//如果是大端
                    {
                        curBytes = curBytes.Reverse().ToArray();
                    }

                    valuesBytes.AddRange(curBytes);
                }

                List<byte> sendBytes = GetMultipleWriteBytes(FuncCode.WriteMultipleRegisters, startAddress, regCountbytes, (byte)(values.Length * 4), valuesBytes.ToArray());

                _socket.Send(sendBytes.ToArray());
                #endregion

                #region 2.获取响应数据
                List<byte> receiveBytes = GetReceiveBytes(12); //读取字节个数
                #endregion

                #region 3.校验
                ExceptionCheck(sendBytes, receiveBytes);
                #endregion
            }
        }
        #endregion

        #region 私有方法
        private ushort TransId = 0;//事务标识符

        /// <summary>
        /// 设置事务标识符
        /// </summary>
        private void SetTransId()
        {
            if (TransId == ushort.MaxValue)
            {
                TransId = 0;
            }
            else
            {
                TransId++;
            }
        }

        #region 请求读操作字节封装(适用于功能码01、02、03、04)
        /// <summary>
        /// 请求读操作字节封装(适用于功能码01、02、03、04)
        /// </summary>
        /// <param name="funcCode"></param>
        /// <param name="startAddress"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        private List<byte> GetReadBytes(FuncCode funcCode, short startAddress, short count)
        {
            byte[] startBytes = BitConverter.GetBytes(startAddress);
            byte[] countBytes = BitConverter.GetBytes(count);

            SetTransId();//设置事务标识符
            byte[] transBytes = BitConverter.GetBytes(TransId);
            //发送的bytes
            return [
                transBytes[0],//事务标识符
                transBytes[1],

                0x00,0x00,//协议标识符

                0x00,0x06,//长度

                0x01,//单元标识符

                (byte)funcCode,//功能码

                startBytes[1],//起始地址H
                startBytes[0],

                countBytes[1],//读取长度H
                countBytes[0],
            ];
        }
        #endregion

        #region 获取读写操作响应字节封装
        /// <summary>
        /// 获取读写操作响应字节封装
        /// </summary>
        /// <param name="receiveCount">需要读取的字节数</param>
        /// <returns></returns>
        private List<byte> GetReceiveBytes(int receiveCount)
        {
            byte[] receiveBytes = new byte[receiveCount];
            try
            {
                _socket.Receive(receiveBytes);
            }
            catch (Exception)
            {
                //异常处理,比如超时异常等
            }

            return receiveBytes.ToList();
        }
        #endregion

        #region 异常码校验
        /// <summary>
        /// 校验响应的结果
        /// </summary>
        /// <param name="sendBytes">响应的结果</param>
        /// <param name="receiveBytes">响应的结果</param>
        /// <exception cref="Exception"></exception>
        private void ExceptionCheck(List<byte> sendBytes, List<byte> receiveBytes)
        {
            if (receiveBytes[7] > 0x80)//出异常了
            {
                throw new Exception($"出异常了,异常信息:{Common.ErrorCodes[receiveBytes[8]]}");
            }

            //是否是同一次事务
            if (!sendBytes.GetRange(0, 2).SequenceEqual(receiveBytes.GetRange(0, 2)))
            {
                throw new Exception("发送和接收不是同一次事务");
            }
        }
        #endregion

        #region 单个写请求的报文 (适用于功能码05、06)
        private List<byte> GetSingleWriteBytes(FuncCode funcCode, short startAddress, byte[] valusBytes)
        {
            SetTransId();//设置事务标识符
            byte[] transBytes = BitConverter.GetBytes(TransId);

            byte[] startBytes = BitConverter.GetBytes(startAddress);
            List<byte> sendBytes = [
                 transBytes[0],//事务标识符
                transBytes[1],

                0x00,0x00,//协议标识符

                0x00,0x06,//长度

                0x01,//单元标识符

                (byte)funcCode,//功能码

                startBytes[1],//起始地址H
                startBytes[0],
            ];

            sendBytes.AddRange(valusBytes);

            return sendBytes;
        }
        #endregion

        #region 多个写请求的报文 (适用于功能码06、10)
        /// <summary>
        /// 
        /// </summary>
        /// <param name="funcCode"></param>
        /// <param name="startAddress"></param>
        /// <param name="valueCountBytes">写数量</param>
        /// <param name="bytesCount"></param>
        /// <param name="valuesBytes"></param>
        /// <returns></returns>
        private List<byte> GetMultipleWriteBytes(FuncCode funcCode, short startAddress, byte[] valueCountBytes, byte bytesCount, byte[] valuesBytes)
        {
            byte[] startBytes = BitConverter.GetBytes(startAddress);
            SetTransId();//设置事务标识符
            byte[] transBytes = BitConverter.GetBytes(TransId);

            short len = (short)(7 + valuesBytes.Length);//长度
            byte[] lenBytes = BitConverter.GetBytes(len);
            List<byte> sendBytes = [
               transBytes[0],//事务ID
               transBytes[1],

                0x00,0x00,//协议标识符

                lenBytes[1],lenBytes[0],//长度

                0x01,//单元标识符

                (byte)funcCode,//功能码
                startBytes[1],//起始地址H
                startBytes[0],

                 valueCountBytes[1],//值的个数bytes
                valueCountBytes[0],

                bytesCount//写入的字节个数
           ];

            sendBytes.AddRange(valuesBytes);//值 字节数组
            return sendBytes;
        }
        #endregion

        #endregion
    }

 

调用

    public partial class TCPCaseBySelf : Window, INotifyPropertyChanged
    {
        private Socket socket;
        private ModbusTCP modbusTCP;

        public TCPCaseBySelf()
        {
            InitializeComponent();

            DataContext = this;//上下文

            Connect();//连接

            #region 读取三个状态输出
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadOutputStatus();//读取三个状态输出
                    });
                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 数字量输入
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadInputStatus();
                    });
                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 模拟量输出
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadOutputNum();
                    });
                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 模拟量输入
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadIutputNum();
                    });
                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 读float
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadFloat();
                    });
                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 读int
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadInt();
                    });
                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 读short
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadShort();
                    });
                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 测试代码
            // if (modbusTCP == null)
            // {
            //     modbusTCP = new ModbusTCP(socket);
            // }
            //int[] rst= modbusTCP.ReadReg32Int(FuncCode.ReadHoldingRegisters,10,1);
            #endregion
        }

        #region 属性值改变通知
        public event PropertyChangedEventHandler? PropertyChanged;

        /// <summary>
        /// 属性值改变通知
        /// </summary>
        /// <param name="propName"></param>
        private void PropChanged(string propName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }
        #endregion

        #region 连接
        /// <summary>
        /// 连接
        /// </summary>
        private void Connect()
        {
            socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
            socket.Connect("127.0.0.1", 502);
        }
        #endregion

        #region 三个输出状态操作
        private bool outputStatus0;

        public bool OutputStatus0
        {
            get { return outputStatus0; }
            set
            {
                outputStatus0 = value;
                PropChanged("OutputStatus0");
            }
        }

        private bool outputStatus1;

        public bool OutputStatus1
        {
            get { return outputStatus1; }
            set
            {
                outputStatus1 = value;
                PropChanged("OutputStatus1");
            }
        }

        private bool outputStatus2;

        public bool OutputStatus2
        {
            get { return outputStatus2; }
            set
            {
                outputStatus2 = value;
                PropChanged("OutputStatus2");
            }
        }

        /// <summary>
        /// 读取三个状态输出
        /// </summary>
        private void ReadOutputStatus()
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }
                bool[] result = modbusTCP.ReadBools(FuncCode.ReadCoils, 0, 3);
                OutputStatus0 = result[0];
                OutputStatus1 = result[1];
                OutputStatus2 = result[2];
            }
        }

        private void cb0_Click(object sender, RoutedEventArgs e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }
                modbusTCP.WriteSingleCoil(0, OutputStatus0);
            }
        }

        private void cb1_Click(object sender, RoutedEventArgs e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }
                modbusTCP.WriteSingleCoil(1, OutputStatus1);
            }
        }

        private void cb2_Click(object sender, RoutedEventArgs e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }
                modbusTCP.WriteSingleCoil(2, OutputStatus2);
            }
        }
        #endregion

        #region 数字量输入
        private void ReadInputStatus()
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }
                bool[] result = modbusTCP.ReadBools(FuncCode.ReadDiscreteInputs, 0, 3);

                if (result[0])
                {
                    BorderLight0.Background = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    BorderLight0.Background = new SolidColorBrush(Colors.LightGray);
                }

                if (result[1])
                {
                    BorderLight1.Background = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    BorderLight1.Background = new SolidColorBrush(Colors.LightGray);
                }

                if (result[2])
                {
                    BorderLight2.Background = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    BorderLight2.Background = new SolidColorBrush(Colors.LightGray);
                }
            }
        }
        #endregion

        #region 模拟量输出 操作
        private void ReadOutputNum()
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                short[] result = modbusTCP.ReadReg16(FuncCode.ReadHoldingRegisters, 0, 4);
                sVar0.Value = result[0];
                sVar1.Value = result[1];
                sVar2.Value = result[2];
                sVar3.Value = result[3];
            }
        }

        private void sVar0_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                modbusTCP.WriteSingleReg(0, (short)sVar0.Value);
            }
        }

        private void sVar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                modbusTCP.WriteSingleReg(1, (short)sVar1.Value);
            }
        }

        private void sVar2_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                modbusTCP.WriteSingleReg(2, (short)sVar2.Value);
            }
        }

        private void sVar3_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                modbusTCP.WriteSingleReg(3, (short)sVar3.Value);
            }
        }
        #endregion

        #region 模拟量输入
        private void ReadIutputNum()
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                short[] result = modbusTCP.ReadReg16(FuncCode.ReadInputRegisters, 0, 4);
                txtInputReg0.Text = result[0].ToString();
                txtInputReg1.Text = result[1].ToString();
                txtInputReg2.Text = result[2].ToString();
                txtInputReg3.Text = result[3].ToString();
            }
        }
        #endregion

        #region int 操作
        private void ReadInt()
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                int[] result = modbusTCP.ReadReg32Int(FuncCode.ReadHoldingRegisters, 10, 1);
                txtInt.Text = result[0].ToString();
            }
        }

        private void txtInt_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                modbusTCP.WriteMultipleReg32Int(10, [int.Parse(txtInt.Text)]);
            }
        }
        #endregion

        #region float 操作
        private void ReadFloat()
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                float[] result = modbusTCP.ReadReg32Float(FuncCode.ReadHoldingRegisters, 8, 1);
                txtFloat.Text = result[0].ToString();
            }
        }

        private void txtFloat_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                modbusTCP.WriteMultipleReg32Float(8, [float.Parse(txtFloat.Text)]);
            }
        }
        #endregion

        #region short 操作
        private void ReadShort()
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                short[] result = modbusTCP.ReadReg16(FuncCode.ReadHoldingRegisters, 12, 1);
                txtShort.Text = result[0].ToString();
            }
        }
        private void txtShort_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (socket != null && socket.Connected)
            {
                if (modbusTCP == null)
                {
                    modbusTCP = new ModbusTCP(socket);
                }

                modbusTCP.WriteSingleReg(12, short.Parse(txtShort.Text));
            }
        }
        #endregion

        private void Window_Closed(object sender, EventArgs e)
        {
            if (socket != null && socket.Connected)
            {
                socket.Close();
            }
        }
    }

 

posted @ 2026-03-27 12:20  野码  阅读(12)  评论(0)    收藏  举报