/// <summary> /// Запрос на запись двоичного содержания регистров подчиненого /// </summary> /// <param name="address">дрес подчиненого</param> /// <param name="regAddress">начальный адрес регистров</param> /// <param name="data">Массив новых значений регистров</param> /// <param name="numberReg">количество регистров</param> public void PresetMultipleRegisters(byte address, short regAddress, short[] data, short numberReg) { if (!_waitResponse) { _counterRepeat = 0; int i = 0; _bufferTransmit = new byte[numberReg * 2 + 9]; _addressSlave = address; _bufferTransmit[i++] = address; _bufferTransmit[i++] = 0x10; _bufferTransmit[i++] = (byte)(regAddress >> 8); _bufferTransmit[i++] = (byte)(regAddress); _bufferTransmit[i++] = (byte)(numberReg >> 8); _bufferTransmit[i++] = (byte)(numberReg); _bufferTransmit[i++] = (byte)(numberReg * 2); int index = 0; while (index != numberReg) { _bufferTransmit[i++] = (byte)(data[index] >> 8); _bufferTransmit[i++] = (byte)(data[index++]); } _bufferTransmit[i++] = (byte)CRC.GetCRC(_bufferTransmit, _bufferTransmit.Length - 2); _bufferTransmit[i] = (byte)(CRC.GetCRC(_bufferTransmit, _bufferTransmit.Length - 2) >> 8); _requestFunction = 0x10; RepeatRequest(); } else { throw new BusyException(); } }
/// <summary> /// проверяем полученные данные /// </summary> private void CheckData() { byte[] buffer = null; try { buffer = new byte[_serialPort.BytesToRead]; _serialPort.Read(buffer, 0, buffer.Length); } catch (InvalidOperationException exc) { if (CatchSerialException(exc)) { return; } } #if DEBUG Console.Write(string.Format("{0} Receive:", _serialPort.PortName)); foreach (byte b in buffer) { Console.Write("{0} ", b.ToString("X2")); } Console.WriteLine(); #endif _packetDetectedArgument.Data = buffer; _packetDetectedArgument.IsRecieved = true; OnPacketDetected(); _waitResponse = false; if (buffer.Length < 5) { ErrorCounter++; if (CheckRepeat()) { return; } _eventArgument.Status = ModBusStatus.UnknowPacket; OnExchangeEnd(); return; } var function = buffer[1] & ~0x80; var error = (buffer[1] & 0x80) == 0x80; if (_requestFunction != function) { ErrorCounter++; if (CheckRepeat()) { return; } _eventArgument.Status = ModBusStatus.InvalidFunction; OnExchangeEnd(); return; } if (!CRC.CheckCRC(buffer, 0, buffer.Length - 2, buffer, buffer.Length - 2)) { ErrorCounter++; if (CheckRepeat()) { return; } _eventArgument.Status = ModBusStatus.CRCError; OnExchangeEnd(); return; } if (buffer[0] != _addressSlave) { ErrorCounter++; if (CheckRepeat()) { return; } _eventArgument.Status = ModBusStatus.AddressSlaveError; OnExchangeEnd(); return; } if (error) { ErrorCounter++; _eventArgument.Status = ModBusStatus.FunctionError; _eventArgument.Function = buffer[1]; _eventArgument.data = new short[] { buffer[2] }; OnExchangeEnd(); return; } RecieveCounter++; _eventArgument.Function = buffer[1]; // Определяем тип функции switch (function) { // Read Holding Registers case 3: _eventArgument.data = new short[buffer[2] / 2]; _eventArgument.Status = ModBusStatus.ReadHoldingRegistersOK; int i = 0; while (i != _eventArgument.data.Length) { _eventArgument.data[i] = (short)(buffer[i * 2 + 3] << 8); _eventArgument.data[i] += buffer[i * 2 + 1 + 3]; i++; } OnExchangeEnd(); break; // Preset Multiple Registers case 0x10: _eventArgument.data = new short[0]; _eventArgument.Status = ModBusStatus.PresetMultipleRegistersOK; OnExchangeEnd(); break; default: _eventArgument.data = new short[buffer[2] / 2]; _eventArgument.Status = ModBusStatus.CustomFunctionOk; i = 0; while (i != _eventArgument.data.Length) { _eventArgument.data[i] = (short)(buffer[i * 2 + 3] << 8); _eventArgument.data[i] += buffer[i * 2 + 1 + 3]; i++; } OnExchangeEnd(); break; } }
/// <summary> /// проверяем полученные данные /// </summary> private ModBusEventArg CheckData(byte[] buffer) { if (buffer == null || buffer.Length == 0) { return(new ModBusEventArg { Status = ModBusStatus.TimeOutError }); } if (buffer.Length <= 2) { return(new ModBusEventArg { Status = ModBusStatus.UnknowPacket }); } if (buffer[0] != _addressSlave) { return(new ModBusEventArg { Status = ModBusStatus.AddressSlaveError }); } var function = buffer[1] & ~0x80; var error = (buffer[1] & 0x80) == 0x80; if (_requestFunction != function) { return(new ModBusEventArg { Status = ModBusStatus.InvalidFunction }); } if (_endingSymbolEnable && buffer[buffer.Length - 1] != EndingSymbol) { return(new ModBusEventArg { Status = ModBusStatus.NoEndingSymbol }); } if (!CRC.CheckCRC(buffer, 0, buffer.Length - (_endingSymbolEnable ? 3 : 2), buffer, buffer.Length - (_endingSymbolEnable ? 3 : 2))) { return(new ModBusEventArg { Status = ModBusStatus.CRCError }); } if (error) { return(new ModBusEventArg { Status = ModBusStatus.FunctionError, Function = buffer[1], data = new short[] { buffer[2] }, }); } // RecieveCounter++; var ea = new ModBusEventArg { Function = buffer[1] }; // Определяем тип функции switch (function) { // Read Holding Registers case 3: ea.data = new short[buffer[2] / 2]; if (ea.Data.Length == _waitRegs) { ea.Status = ModBusStatus.ReadHoldingRegistersOK; } else { ea.Status = ModBusStatus.InvalidResponse; } int i = 0; while (i != ea.data.Length) { ea.data[i] = (short)(buffer[i * 2 + 3] << 8); ea.data[i] += buffer[i * 2 + 1 + 3]; i++; } break; // Preset Multiple Registers case 0x10: ea.data = new short[0]; ea.Status = ModBusStatus.PresetMultipleRegistersOK; break; default: ea.data = new short[buffer[2] / 2]; ea.Status = ModBusStatus.CustomFunctionOk; i = 0; while (i != ea.data.Length) { ea.data[i] = (short)(buffer[i * 2 + 3] << 8); ea.data[i] += buffer[i * 2 + 1 + 3]; i++; } break; } return(ea); }