1. 程式人生 > >C#MODBUS通訊

C#MODBUS通訊

public class ModbusRtu     {         /// <summary>         ///          /// </summary>         /// <param name="com">埠</param>         /// <param name="BaudRate">波特率</param>         /// <param name="stopbits">停止位</param>         /// <param name="parity">校驗方式</param>         /// <param name="databites">資料位</param>         public ModbusRtu(string com, int BaudRate, StopBits stopbits, Parity parity, int databites)         {             try             {                 _Portname = com.ToUpper();                 _BaudRate = BaudRate;                 _StopBites = stopbits;                 _Parity = parity;                 _Databites = databites;                 string[] _allcom = SerialPort.GetPortNames();                 for (int i = 0; i < _allcom.Length; i++)                 {                     _allcom[i] = _allcom[i].ToUpper();                 }                 _switch1 = ((IList)_allcom).Contains(_Portname); //判斷COM口是否存在。                 _SerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(_serportRece);                 if (!_SerialPort.IsOpen)                 {                     _SerialPort.Open();                 }             }             catch(Exception ex)             {             }         }         private void _serportRece(object sender, SerialDataReceivedEventArgs e)         {            //MessageBox.Show("Test");         }         /// <summary>         /// 埠名稱         /// </summary>         public string _Portname { get; set; }         /// <summary>         /// 波特率         /// </summary>         public int _BaudRate { get; set; }         /// <summary>         /// 停止位         /// </summary>         public StopBits _StopBites { get; set; }         /// <summary>         /// 校驗位         /// </summary>         public Parity _Parity { get; set; }         /// <summary>         /// 資料位         /// </summary>         public int _Databites { get; set; }         /// <summary>         /// 開關1判斷是否存在COM口         /// </summary>         public bool _switch1 = false;         private static SerialPort _SerialPort1=new SerialPort();         private SerialPort _SerialPort         {             get             {                 try                 {                     if (!_SerialPort1.IsOpen)//判斷埠是否開啟                     {                         _SerialPort1.DataBits = _Databites;                         _SerialPort1.BaudRate = _BaudRate;                         _SerialPort1.PortName = _Portname;                         _SerialPort1.StopBits = _StopBites;                         _SerialPort1.Parity = _Parity;                         _SerialPort1.Open();                         return _SerialPort1;                     }                     string[] _allcom = SerialPort.GetPortNames();                     for (int i = 0; i < _allcom.Length; i++)                     {                         _allcom[i] = _allcom[i].ToUpper();                     }                                      _switch1 = ((IList)_allcom).Contains(_Portname.ToUpper()); //判斷COM口是否存在。                 }                catch(Exception ex)                 {                                      }                 return _SerialPort1;             }         }         // public byte[] _sendbyte = new byte[30];         private byte[] _bytearr(int _data)         {             byte[] _s = new byte[2];          try             {                 byte[] s1 = BitConverter.GetBytes(_data);                 if (_data > 0xFF)                 {                     _s[0] = s1[s1.Length - 3];                     _s[1]= s1[s1.Length - 4];                 }                 if (_data <=0xFF)                 {                     _s[0] = 0;                     _s[1] = s1[0];                 }             }            catch (Exception ex)             {             }           //  s = BitConverter.GetBytes(_data);             return _s;         }         /// <summary>         /// CRC16校驗         /// </summary>         /// <param name="instructions">校驗的位元組陣列</param>         /// <param name="start">開始位置</param>         /// <param name="length">長度</param>         /// <returns></returns>         public byte[] _crcchecking(byte[] instructions, uint start, uint length)         {             uint i, j;             uint crc16 = 0xFFFF;//crc暫存器賦初值             try             {                 length = length + start;                 for (i = start; i < length; i++)                 {                     crc16 ^= instructions[i];                     for (j = 0; j < 8; j++)                     {                         if ((crc16 & 0x01) == 1)                         {                             crc16 = (crc16 >> 1) ^ 0xA001;                         }                         else                         {                             crc16 = crc16 >> 1;                         }                     }                 }                 //   UInt16 X = (UInt16)(crc16 *256);                 // UInt16 Y = (UInt16)(crc16/256);                 //crc16 = (UInt16)(X ^ Y);             }             catch             {             }             return BitConverter.GetBytes(crc16);         }         /// <summary>         /// 讀取無符號16位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_len">讀取長度</param>         /// <returns></returns>         public UInt16[] _ruint16(int _addr,byte _stand, int _len)         {             UInt16[] _s = new UInt16[_len];             byte[] _send = new byte[20];         try             {                 byte[] _addrbyte = BitConverter.GetBytes(_addr);                 if (_switch1)                 {                     _send[0] = _stand;                     _send[1] = 0x03;                     _send[2] = _bytearr(_addr)[0];                     _send[3] = _bytearr(_addr)[1];                     _send[4] = _bytearr(_len)[0];                     _send[5] = _bytearr(_len)[1];                     _send[6] = _crcchecking(_send, 0, 6)[0];                     _send[7] = _crcchecking(_send, 0, 6)[1];                    _SerialPort.Write(_send, 0, 8);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     byte[] _rec = new byte[_reclen];                     if (_reclen > 5)                     {                         _SerialPort.Read(_rec, 0, _reclen);                         byte reccrcL = _rec[_reclen - 1];//取接收到的報文  校驗碼低位                         byte reccrcH = _rec[_reclen - 2];//取校驗碼高位                         byte[] crc = _crcchecking(_rec, 0, (uint)_reclen-2);//重新校驗報文                         if (reccrcL == crc[1] && reccrcH == crc[0])//比對校驗碼                         {                             byte fun = _rec[1];//功能碼                             if (fun==0x03)//modbus03功能碼                             {                                 byte databyteNum = _rec[2];//接收位元組數                                 for (int i = 0; i < databyteNum; i++)                                 {                                     _s[i] = (UInt16)(_rec[i*2+3]<<8|_rec[i*2+4]);                                 }                             }                                }                     }                 }             }       catch(Exception ex)             {             }             return _s;         }         /// <summary>         /// 讀取有符號16位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_len">讀取長度</param>         /// <returns></returns>         public Int16[] _rint16(int _addr, byte _stand, int _len)         {           Int16[] _s = new Int16[_len];             byte[] _send = new byte[20];             try             {                 byte[] _addrbyte = BitConverter.GetBytes(_addr);                 if (_switch1)                 {                     _send[0] = _stand;                     _send[1] = 0x03;                     _send[2] = _bytearr(_addr)[0];                     _send[3] = _bytearr(_addr)[1];                     _send[4] = _bytearr(_len)[0];                     _send[5] = _bytearr(_len)[1];                     _send[6] = _crcchecking(_send, 0, 6)[0];                     _send[7] = _crcchecking(_send, 0, 6)[1];                     _SerialPort.Write(_send, 0, 8);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     byte[] _rec = new byte[_reclen];                     if (_reclen > 5)                     {                         _SerialPort.Read(_rec, 0, _reclen);                         byte reccrcL = _rec[_reclen - 1];//取接收到的報文  校驗碼低位                         byte reccrcH = _rec[_reclen - 2];//取校驗碼高位                         byte[] crc = _crcchecking(_rec, 0, (uint)_reclen - 2);//重新校驗報文                         if (reccrcL == crc[1] && reccrcH == crc[0])//比對校驗碼                         {                             byte fun = _rec[1];//功能碼                             if (fun == 0x03)//modbus03功能碼                             {                                 byte databyteNum = _rec[2];//接收位元組數                                 for (int i = 0; i < databyteNum; i++)                                 {                                     _s[i] = (Int16)(_rec[i * 2 + 3] << 8 | _rec[i * 2 + 4]);                                 }                             }                         }                     }                 }             }             catch (Exception ex)             {             }             return _s;         }         /// <summary>         /// 讀取無符號32位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_length">長度</param>         /// <returns></returns>         public UInt32[] _ruint32(int _addr, byte _stand, int _length)         {             int _len = _length * 2;             UInt32[] _s = new UInt32[_length];             byte[] _send = new byte[20];             try             {                 byte[] _addrbyte = BitConverter.GetBytes(_addr);                 if (_switch1)                 {                     _send[0] = _stand;                     _send[1] = 0x03;                     _send[2] = _bytearr(_addr)[0];                     _send[3] = _bytearr(_addr)[1];                     _send[4] = _bytearr(_len)[0];                     _send[5] = _bytearr(_len)[1];                     _send[6] = _crcchecking(_send, 0, 6)[0];                     _send[7] = _crcchecking(_send, 0, 6)[1];                     _SerialPort.Write(_send, 0, 8);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     byte[] _rec = new byte[_reclen];                     if (_reclen > 5)                     {                         _SerialPort.Read(_rec, 0, _reclen);                         byte reccrcL = _rec[_reclen - 1];//取接收到的報文  校驗碼低位                         byte reccrcH = _rec[_reclen - 2];//取校驗碼高位                         byte[] crc = _crcchecking(_rec, 0, (uint)_reclen - 2);//重新校驗報文                         if (reccrcL == crc[1] && reccrcH == crc[0])//比對校驗碼                         {                             byte fun = _rec[1];//功能碼                             if (fun == 0x03)//modbus03功能碼                             {                                 byte databyteNum = _rec[2];//接收位元組數                                 for (int j= 0; j < databyteNum/4; j++)                                 {                                         byte[] _nt = { _rec[4 + j * 4], _rec[3 + j * 4], _rec[6 + j * 4], _rec[5 + j * 4] };                                         _s[j] = BitConverter.ToUInt32(_nt, 0);                                 }                             }                         }                     }                 }             }             catch (Exception ex)             {             }             return _s;         }         /// <summary>         /// 讀取有符號32位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_length">讀取長度</param>         /// <returns></returns>         public Int32[] _rint32(int _addr, byte _stand, int _length)         {             int _len = _length * 2;             Int32[] _s = new Int32[_length];             byte[] _send = new byte[20];             try             {                 byte[] _addrbyte = BitConverter.GetBytes(_addr);                 if (_switch1)                 {                     _send[0] = _stand;                     _send[1] = 0x03;                     _send[2] = _bytearr(_addr)[0];                     _send[3] = _bytearr(_addr)[1];                     _send[4] = _bytearr(_len)[0];                     _send[5] = _bytearr(_len)[1];                     _send[6] = _crcchecking(_send, 0, 6)[0];                     _send[7] = _crcchecking(_send, 0, 6)[1];                     _SerialPort.Write(_send, 0, 8);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     byte[] _rec = new byte[_reclen];                     if (_reclen > 5)                     {                         _SerialPort.Read(_rec, 0, _reclen);                         byte reccrcL = _rec[_reclen - 1];//取接收到的報文  校驗碼低位                         byte reccrcH = _rec[_reclen - 2];//取校驗碼高位                         byte[] crc = _crcchecking(_rec, 0, (uint)_reclen - 2);//重新校驗報文                         if (reccrcL == crc[1] && reccrcH == crc[0])//比對校驗碼                         {                             byte fun = _rec[1];//功能碼                             if (fun == 0x03)//modbus03功能碼                             {                                 byte databyteNum = _rec[2];//接收位元組數                                 for (int j = 0; j < databyteNum / 4; j++)                                 {                                     byte[] _nt = { _rec[4 + j * 4], _rec[3 + j * 4], _rec[6 + j * 4], _rec[5 + j * 4] };                                     _s[j] = BitConverter.ToInt32(_nt, 0);                                 }                             }                         }                     }                 }             }             catch (Exception ex)             {             }             return _s;         }         /// <summary>         /// 讀取32位浮點數         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_length">讀取長度</param>         /// <returns></returns>         public  Single[] _rfloat(int _addr, byte _stand, int _length)         {             int _len = _length * 2;             Single[] _s = new Single[_length];             byte[] _send = new byte[20];             try             {                 byte[] _addrbyte = BitConverter.GetBytes(_addr);                 if (_switch1)                 {                     _send[0] = _stand;                     _send[1] = 0x03;                     _send[2] = _bytearr(_addr)[0];                     _send[3] = _bytearr(_addr)[1];                     _send[4] = _bytearr(_len)[0];                     _send[5] = _bytearr(_len)[1];                     _send[6] = _crcchecking(_send, 0, 6)[0];                     _send[7] = _crcchecking(_send, 0, 6)[1];                     _SerialPort.Write(_send, 0, 8);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     byte[] _rec = new byte[_reclen];                     if (_reclen > 5)                     {                         _SerialPort.Read(_rec, 0, _reclen);                         byte reccrcL = _rec[_reclen - 1];//取接收到的報文  校驗碼低位                         byte reccrcH = _rec[_reclen - 2];//取校驗碼高位                         byte[] crc = _crcchecking(_rec, 0, (uint)_reclen - 2);//重新校驗報文                         if (reccrcL == crc[1] && reccrcH == crc[0])//比對校驗碼                         {                             byte fun = _rec[1];//功能碼                             if (fun == 0x03)//modbus03功能碼                             {                                 byte databyteNum = _rec[2];//接收位元組數                                 for (int j = 0; j < databyteNum / 4; j++)                                 {                                     byte[] _nt = { _rec[4 + j * 4], _rec[3 + j * 4], _rec[6 + j * 4], _rec[5 + j * 4] };                                     _s[j] = BitConverter.ToSingle(_nt, 0);                                 }                             }                         }                     }                 }             }             catch (Exception ex)             {             }             return _s;         }         /// <summary>         /// 讀取位狀態         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_length">讀取長度</param>         /// <returns></returns>         public bool[] _rbite(int _addr, byte _stand, int _length)         {             int _len = _length * 1;             bool[] _s = new bool[1000];             byte[] _send = new byte[20];             try             {                 byte[] _addrbyte = BitConverter.GetBytes(_addr);                 if (_switch1)                 {                     _send[0] = _stand;                     _send[1] = 0x01;                     _send[2] = _bytearr(_addr)[0];                     _send[3] = _bytearr(_addr)[1];                     _send[4] = _bytearr(_len)[0];                     _send[5] = _bytearr(_len)[1];                     _send[6] = _crcchecking(_send, 0, 6)[0];                     _send[7] = _crcchecking(_send, 0, 6)[1];                     _SerialPort.Write(_send, 0, 8);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     byte[] _rec = new byte[_reclen];                     if (_reclen > 5)                     {                         _SerialPort.Read(_rec, 0, _reclen);                         byte reccrcL = _rec[_reclen - 1];//取接收到的報文  校驗碼低位                         byte reccrcH = _rec[_reclen - 2];//取校驗碼高位                         byte[] crc = _crcchecking(_rec, 0, (uint)_reclen - 2);//重新校驗報文                         if (reccrcL == crc[1] && reccrcH == crc[0])//比對校驗碼                         {                             byte databyteNum = _rec[2];//接收位元組數                             byte fun = _rec[1];//功能碼                             if (fun == 0x01)//modbus03功能碼                             {                                                           for (int j = 0; j < databyteNum ; j++)                                 {                                     for (int i = 0; i < 8; i++)                                     {                                         _s[j*8+i] = (_rec[3 + j] & Convert.ToInt16(Math.Pow(2, i))) == Convert.ToInt16(Math.Pow(2, i));                                     }                                 }                             }                         }                     }                 }             }             catch (Exception ex)             {             }             return _s;         }         /// <summary>         /// 寫單個位狀態         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_bool">BOOL值</param>         /// <returns></returns>         public bool _wbite(int _addr, byte _stand, bool  _bool)         {             bool s = false;             byte bools = 0;             byte[] _send = new byte[20];             if (_switch1)             {                 byte[] _addrbyte = BitConverter.GetBytes(_addr);                 byte _addrH = 0;                 byte _addrL = 1;                 byte[] sedbyte = new byte[20];                 try                 {                     if (_addr > 0xFF)                     {                         _addrL = _addrbyte[_addrbyte.Length - 3];                         _addrH = _addrbyte[_addrbyte.Length - 4];                     }                     if (_addr <= 0xFF)                     {                         _addrL = 0;                         _addrH = _addrbyte[0];                     }                     if (_bool)                     {                         bools = 1;                     }                     _send[0] = _stand;                     _send[1] = 0x05;                     _send[2] = _addrL;                     _send[3] = _addrH;                     _send[4] = bools;                     _send[5] = _crcchecking(_send, 0, 5)[0];                     _send[6] = _crcchecking(_send, 0, 5)[1];                     _SerialPort.Write(_send, 0, 7);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     byte[] _rec = new byte[_reclen];                     if (_reclen > 5)                     {                         _SerialPort.Read(_rec, 0, _reclen);                         byte reccrcL = _rec[_reclen - 3];//取接收到的報文  校驗碼低位                         byte reccrcH = _rec[_reclen - 2];//取校驗碼高位                         byte[] crc = _crcchecking(_rec, 0, (uint)_reclen - 3);//重新校驗報文                         if (reccrcL == crc[0] && reccrcH == crc[1])//比對校驗碼                         {                             byte databyteNum = _rec[2];//接收位元組數                             byte fun = _rec[1];//功能碼                             if (fun == 0x05)//modbus03功能碼                             {                                 s = true;                             }                         }                     }                 }                 catch (Exception ex)                 {                     //throw;                 }             }             return s;         }         /// <summary>         /// 寫單個16位有符號資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_data">16位有符號資料</param>         /// <returns></returns>         public bool _wint16(int _addr, byte _stand, Int16 _data)         {             bool _successful = false;             try             {                 if (_switch1)                 {                     byte[] _recebyte = new byte[1000];                     byte _addrH = 0;                     byte _addrL = 1;                     byte[] sedbyte = new byte[20];                     byte[] _addrbyte = BitConverter.GetBytes(_addr);                     if (_data < 32767 || _data > -32767)                     {                         if (_addr > 0xFF)                         {                             _addrL = _addrbyte[_addrbyte.Length - 3];                             _addrH = _addrbyte[_addrbyte.Length - 4];                         }                         if (_addr <= 0xFF)                         {                             _addrL = 0;                             _addrH = _addrbyte[0];                         }                         Int16 _y = Convert.ToInt16(_data);                         byte[] intBuff = BitConverter.GetBytes(_y);                         sedbyte[0] = _stand;                         sedbyte[1] = 0x06;                         sedbyte[2] = _addrL;//MODBUS地址低位                         sedbyte[3] = _addrH;//modbus地址高位                         sedbyte[4] = intBuff[1];                         sedbyte[5] = intBuff[0];                         sedbyte[6] = _crcchecking(sedbyte, 0, 6)[0];                         sedbyte[7] = _crcchecking(sedbyte, 0, 6)[1];                         _SerialPort.Write(sedbyte, 0, 8);//傳送報文                         int _reclen = _SerialPort.BytesToRead;                          _SerialPort.Read(_recebyte, 0,_reclen);                         if (_reclen>5)                         {                             byte reccrcL = _recebyte[_reclen - 2];//取接收到的報文  校驗碼低位                             byte reccrcH = _recebyte[_reclen - 1];//取校驗碼高位                             byte[] crc = _crcchecking(_recebyte, 0, (uint)_reclen - 2);//重新校驗報文                             if (reccrcL == crc[0] && reccrcH == crc[1])//比對校驗碼                             {                                 byte fun = _recebyte[1];//功能碼                                 if (fun == 0x06)//modbus03功能碼                                 {                                     _successful = true;                                 }                             }                             _successful = true;                         }                     }                 }             }             catch             {             }             return _successful;         }         /// <summary>         /// 寫單個無符號16位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_data">16位無符號資料</param>         /// <returns></returns>         public bool _wuint16(int _addr, byte _stand, UInt16 _data)         {             bool _successful = false;             try             {                 if (_switch1)                 {                     byte[] _recebyte = new byte[1000];                     byte _addrH = 0;                     byte _addrL = 1;                     byte[] sedbyte = new byte[20];                     byte[] _addrbyte = BitConverter.GetBytes(_addr);                         if (_addr > 0xFF)                         {                             _addrL = _addrbyte[_addrbyte.Length - 3];                             _addrH = _addrbyte[_addrbyte.Length - 4];                         }                         if (_addr <= 0xFF)                         {                             _addrL = 0;                             _addrH = _addrbyte[0];                         }                         UInt16 _y = Convert.ToUInt16(_data);                         byte[] intBuff = BitConverter.GetBytes(_y);                         sedbyte[0] = _stand;                         sedbyte[1] = 0x06;                         sedbyte[2] = _addrL;//MODBUS地址低位                         sedbyte[3] = _addrH;//modbus地址高位                         sedbyte[4] = intBuff[1];                         sedbyte[5] = intBuff[0];                         sedbyte[6] = _crcchecking(sedbyte, 0, 6)[0];                         sedbyte[7] = _crcchecking(sedbyte, 0, 6)[1];                         _SerialPort.Write(sedbyte, 0, 8);//傳送報文                         int _reclen = _SerialPort.BytesToRead;                         _SerialPort.Read(_recebyte, 0, _reclen);                         if (_reclen > 5)                         {                             byte reccrcL = _recebyte[_reclen - 2];//取接收到的報文  校驗碼低位                             byte reccrcH = _recebyte[_reclen - 1];//取校驗碼高位                             byte[] crc = _crcchecking(_recebyte, 0, (uint)_reclen - 2);//重新校驗報文                             if (reccrcL == crc[0] && reccrcH == crc[1])//比對校驗碼                             {                                 byte fun = _recebyte[1];//功能碼                                 if (fun == 0x06)//modbus03功能碼                                 {                                     _successful = true;                                 }                             }                                                     }                     }                 }                        catch             {             }             return _successful;         }         /// <summary>         /// 寫入單個有符號32位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_data">32位有符號資料</param>         /// <returns></returns>         public bool _wint32(int _addr, byte _stand, Int32 _data)         {             bool _successful = false;             try             {                 if (_switch1)                 {                     byte[] _recebyte = new byte[1000];                     byte _addrH = 0;                     byte _addrL = 1;                     byte[] sedbyte = new byte[20];                     byte[] _addrbyte = BitConverter.GetBytes(_addr);                     if (_addr > 0xFF)                     {                         _addrL = _addrbyte[_addrbyte.Length - 3];                         _addrH = _addrbyte[_addrbyte.Length - 4];                     }                     if (_addr <= 0xFF)                     {                         _addrL = 0;                         _addrH = _addrbyte[0];                     }                     byte[] intBuff = BitConverter.GetBytes(_data);                     sedbyte[0] = _stand;                     sedbyte[1] = 0x10;                     sedbyte[2] = _addrL;//MODBUS地址低位                     sedbyte[3] = _addrH;//modbus地址高位                     sedbyte[4] = 0x00;                     sedbyte[5] = 0x02;                     sedbyte[6] = 0x04;                     sedbyte[7] = intBuff[1];                     sedbyte[8] = intBuff[0];                     sedbyte[9] = intBuff[3];                     sedbyte[10] = intBuff[2];                     sedbyte[11] = _crcchecking(sedbyte, 0, 11)[0];                     sedbyte[12] = _crcchecking(sedbyte, 0, 11)[1];                     _SerialPort.Write(sedbyte, 0, 13);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     _SerialPort.Read(_recebyte, 0, _reclen);                     if (_reclen > 5)                     {                         byte reccrcL = _recebyte[_reclen - 2];//取接收到的報文  校驗碼低位                         byte reccrcH = _recebyte[_reclen - 1];//取校驗碼高位                         byte[] crc = _crcchecking(_recebyte, 0, (uint)_reclen - 2);//重新校驗報文                         if (reccrcL == crc[0] && reccrcH == crc[1])//比對校驗碼                         {                             byte fun = _recebyte[1];//功能碼                             if (fun == 0x10)//modbus03功能碼                             {                                 _successful = true;                             }                         }                                            }                 }             }             catch             {             }             return _successful;         }         /// <summary>         /// 寫入單個無符號32位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_data">無符號32位資料</param>         /// <returns></returns>         public bool _wuint32(int _addr, byte _stand, UInt32 _data)         {             bool _successful = false;             try             {                 if (_switch1)                 {                     byte[] _recebyte = new byte[1000];                     byte _addrH = 0;                     byte _addrL = 1;                     byte[] sedbyte = new byte[20];                     byte[] _addrbyte = BitConverter.GetBytes(_addr);                     if (_addr > 0xFF)                     {                         _addrL = _addrbyte[_addrbyte.Length - 3];                         _addrH = _addrbyte[_addrbyte.Length - 4];                     }                     if (_addr <= 0xFF)                     {                         _addrL = 0;                         _addrH = _addrbyte[0];                     }                     byte[] intBuff = BitConverter.GetBytes(_data);                     sedbyte[0] = _stand;                     sedbyte[1] = 0x10;                     sedbyte[2] = _addrL;//MODBUS地址低位                     sedbyte[3] = _addrH;//modbus地址高位                     sedbyte[4] = 0x00;                     sedbyte[5] = 0x02;                     sedbyte[6] = 0x04;                     sedbyte[7] = intBuff[1];                     sedbyte[8] = intBuff[0];                     sedbyte[9] = intBuff[3];                     sedbyte[10] = intBuff[2];                     sedbyte[11] = _crcchecking(sedbyte, 0, 11)[0];                     sedbyte[12] = _crcchecking(sedbyte, 0, 11)[1];                     _SerialPort.Write(sedbyte, 0, 13);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     _SerialPort.Read(_recebyte, 0, _reclen);                     if (_reclen > 5)                     {                         byte reccrcL = _recebyte[_reclen - 2];//取接收到的報文  校驗碼低位                         byte reccrcH = _recebyte[_reclen - 1];//取校驗碼高位                         byte[] crc = _crcchecking(_recebyte, 0, (uint)_reclen - 2);//重新校驗報文                         if (reccrcL == crc[0] && reccrcH == crc[1])//比對校驗碼                         {                             byte fun = _recebyte[1];//功能碼                             if (fun == 0x10)//modbus03功能碼                             {                                 _successful = true;                             }                         }                     }                 }             }             catch             {             }             return _successful;         }         /// <summary>         /// 寫入單個單精度浮點數         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_stand">站號</param>         /// <param name="_data">單精度浮點數</param>         /// <returns></returns>         public bool _wfloat(int _addr, byte _stand, Single _data)         {             bool _successful = false;             try             {                 if (_switch1)                 {                     byte[] _recebyte = new byte[1000];                     byte _addrH = 0;                     byte _addrL = 1;                     byte[] sedbyte = new byte[20];                     byte[] _addrbyte = BitConverter.GetBytes(_addr);                     if (_addr > 0xFF)                     {                         _addrL = _addrbyte[_addrbyte.Length - 3];                         _addrH = _addrbyte[_addrbyte.Length - 4];                     }                     if (_addr <= 0xFF)                     {                         _addrL = 0;                         _addrH = _addrbyte[0];                     }                     byte[] intBuff = BitConverter.GetBytes(_data);                     sedbyte[0] = _stand;                     sedbyte[1] = 0x10;                     sedbyte[2] = _addrL;//MODBUS地址低位                     sedbyte[3] = _addrH;//modbus地址高位                     sedbyte[4] = 0x00;                     sedbyte[5] = 0x02;                     sedbyte[6] = 0x04;                     sedbyte[7] = intBuff[1];                     sedbyte[8] = intBuff[0];                     sedbyte[9] = intBuff[3];                     sedbyte[10] = intBuff[2];                     sedbyte[11] = _crcchecking(sedbyte, 0, 11)[0];                     sedbyte[12] = _crcchecking(sedbyte, 0, 11)[1];                     _SerialPort.Write(sedbyte, 0, 13);//傳送報文                     int _reclen = _SerialPort.BytesToRead;                     _SerialPort.Read(_recebyte, 0, _reclen);                     if (_reclen > 5)                     {                         byte reccrcL = _recebyte[_reclen - 2];//取接收到的報文  校驗碼低位                         byte reccrcH = _recebyte[_reclen - 1];//取校驗碼高位                         byte[] crc = _crcchecking(_recebyte, 0, (uint)_reclen - 2);//重新校驗報文                         if (reccrcL == crc[0] && reccrcH == crc[1])//比對校驗碼                         {                             byte fun = _recebyte[1];//功能碼                             if (fun == 0x10)//modbus03功能碼                             {                                 _successful = true;                             }                         }                     }                 }             }             catch(Exception ex)             {             }             return _successful;         }     }     public class ModbusTcp : IDisposable     {         public ModbusTcp(int _Port, string _Ip)         {             _ip = _Ip;             _port = _Port;             _online = false;             Ping ping = new Ping();             try             {                 PingReply pingReply = ping.Send(_Ip);                 if (pingReply.Status == IPStatus.Success)                 {                     _online = true;                     // Console.WriteLine("當前線上,已ping通!");                 }                 else                 {                     _online = false;                 }             }             catch             {             }         }         public ModbusTcp()         {         }         public string _ip { get; set; }         public int _port { get; set; }         public bool _online { get; set; }         /// <summary>         /// 獲取伺服器是否線上         /// </summary>         public bool _conn { get; }         private static Socket _SocketClient;         // private Socket clientSocket;         private Socket _socket         {             get             {                 if (_SocketClient == null)                 {                     int port = _port;                     string host = _ip;//伺服器端ip地址                     IPAddress ip = IPAddress.Parse(host);                     IPEndPoint ipe = new IPEndPoint(ip, port);                     _SocketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                     _SocketClient.Connect(ipe);                     return _SocketClient;                 }                 //掉線重連                 if (!_SocketClient.Connected)                 {                     _SocketClient.Close();                     int port = _port;                     string host = _ip;//伺服器端ip地址                     IPAddress ip = IPAddress.Parse(host);                     IPEndPoint ipe = new IPEndPoint(ip, port);                     _SocketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                     _SocketClient.Connect(ipe);                     return _SocketClient;                 }                 return _SocketClient;             }         }         /// <summary>         /// 讀取位狀態         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_len">讀取長度</param>         /// <returns></returns>         public bool[] _bite(int _addr, int _len)         {             #region             /*——————————————————————————————————————————————————————————              * MODBUS_TCP---01功能碼說明              * 讀取多個位狀態              * 傳送報文:              * 00 00 00 00 00 06(此位元組之後共有多少位元組) 01(站號)01(功能碼)61(地址高位)80(地址低位) 00(讀取數量高位) 0A (讀取數量低位)               * 返回報文:              * 00 00 00 00 00 05 01 01 02(讀取結果有多少個位元組) 33(0---7的位寄存) 03(8---15的位寄存)               * 讀取的結果以位元組儲存,8位一個位元組,讀取10個位則需要兩個位元組儲存狀態。將位元組拆分,即為單個位狀態              * 關於返回值:              *    返回 bool 陣列,陣列的0號值為連續讀取位  的首地址位狀態,陣列1號值為讀取的第二個地址的位狀態              * ——————————————————————————————————————————————————             */             #endregion             bool[] _bites = new bool[1000];             if (_online)             {                 if (_len >= 1)                 {                     int _LEN = _len * 1;                     byte[] _recebyte = new byte[1000];                     byte _lenH = 0;                     byte _lenL = 1;                     byte _addrH = 0;                     byte _addrL = 1;                     byte[] sedbyte = new byte[20];                     byte[] _lengbyte = BitConverter.GetBytes(_LEN);                     byte[] _addrbyte = BitConverter.GetBytes(_addr);                     if (_LEN > 0xFF)                     {                         _lenL = _lengbyte[_lengbyte.Length - 3];                         _lenH = _lengbyte[_lengbyte.Length - 4];                     }                     if (_LEN <= 0xFF)                     {                         _lenL = 0;                         _lenH = _lengbyte[0];                     }                     if (_addr > 0xFF)                     {                         _addrL = _addrbyte[_addrbyte.Length - 3];                         _addrH = _addrbyte[_addrbyte.Length - 4];                     }                     if (_addr <= 0xFF)                     {                         _addrL = 0;                         _addrH = _addrbyte[0];                     }                     sedbyte[0] = 0x00;                     sedbyte[1] = 0x00;                     sedbyte[2] = 0x00;                     sedbyte[3] = 0x00;                     sedbyte[4] = 0x00;                     sedbyte[5] = 0x06;                     sedbyte[6] = 0x01;                     sedbyte[7] = 0x01;                     sedbyte[8] = _addrL;//MODBUS地址低位                     sedbyte[9] = _addrH;//modbus地址高位                     sedbyte[10] = _lenL;//讀取長度低位                     sedbyte[11] = _lenH;//讀取長度高位                     try                     {                         _socket.Send(sedbyte, 0, 12, SocketFlags.None);//傳送報文                         int _recelen = _socket.Receive(_recebyte, 0);                         int _recl1 = _recebyte[5] + 6;                         if (_recelen == _recl1)                         {                             for (int i = 0; i < _recebyte[8]; i++)                             {                                 for (int j = 0; j < 8; j++)                                 {                                     _bites[i * 8 + j] = (_recebyte[9 + i] & Convert.ToInt16(Math.Pow(2, j))) == Convert.ToInt16(Math.Pow(2, j));                                 }                             }                         }                     }                     catch                     {                     }                 }             }             return _bites;         }         /// <summary>         /// 讀取單精度浮點數         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_len">讀取長度</param>         /// <returns></returns>         public float[] _float(int _addr, int _len)         {             float[] _float = new float[100];             try             {                 if (_online)                 {                     if (_len >= 1)                     {                         int _LEN = _len * 2;                         byte[] _recebyte = new byte[1000];                         byte _lenH = 0;                         byte _lenL = 1;                         byte _addrH = 0;                         byte _addrL = 1;                         byte[] sedbyte = new byte[20];                         byte[] _lengbyte = BitConverter.GetBytes(_LEN);                         byte[] _addrbyte = BitConverter.GetBytes(_addr);                         if (_LEN > 0xFF)                         {                             _lenL = _lengbyte[_lengbyte.Length - 3];                             _lenH = _lengbyte[_lengbyte.Length - 4];                         }                         if (_LEN <= 0xFF)                         {                             _lenL = 0;                             _lenH = _lengbyte[0];                         }                         if (_addr > 0xFF)                         {                             _addrL = _addrbyte[_addrbyte.Length - 3];                             _addrH = _addrbyte[_addrbyte.Length - 4];                         }                         if (_addr <= 0xFF)                         {                             _addrL = 0;                             _addrH = _addrbyte[0];                         }                         sedbyte[0] = 0x00;                         sedbyte[1] = 0x00;                         sedbyte[2] = 0x00;                         sedbyte[3] = 0x00;                         sedbyte[4] = 0x00;                         sedbyte[5] = 0x06;                         sedbyte[6] = 0x01;                         sedbyte[7] = 0x03;                         sedbyte[8] = _addrL;//MODBUS地址低位                         sedbyte[9] = _addrH;//modbus地址高位                         sedbyte[10] = _lenL;//讀取長度低位                         sedbyte[11] = _lenH;//讀取長度高位                         _socket.Send(sedbyte, 0, 12, SocketFlags.None);//傳送報文                         int _recelen = _socket.Receive(_recebyte, 0);                         int _s1 = _len * 4 + 9;                         if (_recelen == _s1)//校驗返回的資料                         {                             byte[] _bs = new byte[4];                             //   rec = rec + 1;                             for (int i = 0; i < _len; i++)                             {                                 _bs[0] = _recebyte[10 + i * 4];                                 _bs[1] = _recebyte[9 + i * 4];                                 _bs[2] = _recebyte[12 + i * 4];                                 _bs[3] = _recebyte[11 + i * 4];                                 _float[i] = BitConverter.ToSingle(_bs, 0);                             }                             //  MessageBox.Show("ok!");                         }                     }                 }             }             catch             {             }             return _float;         }         /// <summary>         /// 讀取有符號32位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_len">讀取長度</param>         /// <returns></returns>         public Int32[] _int32(int _addr, int _len)         {             Int32[] _int32 = new Int32[100];             try             {                 if (_online)                 {                     if (_len >= 1)                     {                         int _LEN = _len * 2;                         byte[] _recebyte = new byte[1000];                         byte _lenH = 0;                         byte _lenL = 1;                         byte _addrH = 0;                         byte _addrL = 1;                         byte[] sedbyte = new byte[20];                         byte[] _lengbyte = BitConverter.GetBytes(_LEN);                         byte[] _addrbyte = BitConverter.GetBytes(_addr);                         if (_LEN > 0xFF)                         {                             _lenL = _lengbyte[_lengbyte.Length - 3];                             _lenH = _lengbyte[_lengbyte.Length - 4];                         }                         if (_LEN <= 0xFF)                         {                             _lenL = 0;                             _lenH = _lengbyte[0];                         }                         if (_addr > 0xFF)                         {                             _addrL = _addrbyte[_addrbyte.Length - 3];                             _addrH = _addrbyte[_addrbyte.Length - 4];                         }                         if (_addr <= 0xFF)                         {                             _addrL = 0;                             _addrH = _addrbyte[0];                         }                         sedbyte[0] = 0x00;                         sedbyte[1] = 0x00;                         sedbyte[2] = 0x00;                         sedbyte[3] = 0x00;                         sedbyte[4] = 0x00;                         sedbyte[5] = 0x06;                         sedbyte[6] = 0x01;                         sedbyte[7] = 0x03;                         sedbyte[8] = _addrL;//MODBUS地址低位                         sedbyte[9] = _addrH;//modbus地址高位                         sedbyte[10] = _lenL;//讀取長度低位                         sedbyte[11] = _lenH;//讀取長度高位                         _socket.Send(sedbyte, 0, 12, SocketFlags.None);//傳送報文                         int _recelen = _socket.Receive(_recebyte, 0);                         int _s1 = _len * 4 + 9;                         if (_recelen == _s1)//校驗返回的資料                         {                             byte[] _bs = new byte[4];                             //   rec = rec + 1;                             for (int i = 0; i < _len; i++)                             {                                 _bs[0] = _recebyte[10 + i * 4];                                 _bs[1] = _recebyte[9 + i * 4];                                 _bs[2] = _recebyte[12 + i * 4];                                 _bs[3] = _recebyte[11 + i * 4];                                 _int32[i] = BitConverter.ToInt32(_bs, 0);                             }                             //  MessageBox.Show("ok!");                         }                     }                 }             }             catch             {             }             return _int32;         }         /// <summary>         /// 讀取無符號32位資料         /// </summary>         /// <param name="_addr">MODBUS地址</param>         /// <param name="_len">讀取長度</param>         /// <returns></returns>         public uint[] _uint32(int _addr, int _len)         {             uint[] _uint = new uint[100];             try             {                 if (_online)                 {                     if (_len >= 1)                     {                         int _LEN = _len * 2;                         byte[] _recebyte = new byte[1000];                         byte _lenH = 0;                         byte _lenL = 1;                         byte _addrH = 0;                         byte _addrL = 1;                         byte[] sedbyte = new byte[20];                         byte[] _lengbyte = BitConverter.GetBytes(_LEN);                         byte[] _addrbyte = BitConverter.GetBytes(_addr);                         if (_LEN > 0xFF)                         {                             _lenL = _lengbyte[_lengbyte.Length - 3];                             _lenH = _lengbyte[_lengbyte.Length - 4];                         }                         if (_LEN <= 0xFF)                         {                             _lenL = 0;                             _lenH = _lengbyte[0];                         }                         if (_addr > 0xFF)                         {                             _addrL = _addrbyte[_addrbyte.Length - 3];                             _addrH = _addrbyte[_addrbyte.Length - 4];                         }                         if (_addr <= 0xFF)                         {                             _addrL = 0;                             _addrH = _addrbyte[0];                         }                         sedbyte[0] = 0x00;                         sedbyte[1] = 0x00;                         sedbyte[2] = 0x00;                         sedbyte[3] = 0x00;