diff --git a/Modbus-CAPL/include/CAPL/include/ModbusClient.cin b/Modbus-CAPL/include/CAPL/include/ModbusClient.cin index 6df9024..4f614da 100644 --- a/Modbus-CAPL/include/CAPL/include/ModbusClient.cin +++ b/Modbus-CAPL/include/CAPL/include/ModbusClient.cin @@ -441,9 +441,9 @@ void ModbusWriteBits(word address, long count, byte values[]) long offset; word devStartAddr, devEndAddr; - devStartAddr = funcCode == thisDev.Addr.Write.OutputBits; // The start address of the bits - devEndAddr = devStartAddr + thisDev.MaxBitCount; // The address behind the last bit - if (address < devStartAddr) // Oh, reading at the wrong address? + devStartAddr = thisDev.Addr.Write.OutputBits; // The start address of the bits + devEndAddr = devStartAddr + thisDev.MaxBitCount; // The address behind the last bit + if (address < devStartAddr) // Oh, reading at the wrong address? { writeDbg(MbError, "ModbusWriteBits: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); OnModbusClientPanics(AddressFailure); @@ -567,23 +567,42 @@ void ModbusWriteRegisters(word address, long count, word values[]) enum ModbusFuncCode funcCode = WriteRegisters; byte buffer[maxLength]; struct ModbusReqWriteRegisters mbreq; - word curCount; + word overallLength, curCount, addressO; byte dataLength; - word overallLength; word i; long offset; + word devStartAddr, devEndAddr; + + devStartAddr = thisDev.Addr.Write.OutputRegisters; // The start address of the bits + devEndAddr = devStartAddr + thisDev.MaxRegisterCount; // The address behind the last bit + if (address >= devEndAddr) + devEndAddr = 0xFFFF; + if (address < devStartAddr) // Oh, reading at the wrong address? + { + writeDbg(MbError, "ModbusWriteRegisters: The given start address 0x%04X is smaller than the obligatory start address 0x%04X", address, devStartAddr); + OnModbusClientPanics(AddressFailure); + return; + } // FC16: Write Multiple Registers (AOs) offset = 0; - while (count > 0) + while (count > 0 && (address + offset) < devEndAddr) { + addressO = address + offset; curCount = count > gMaxRegsPerWrite ? gMaxRegsPerWrite : count; + + if (addressO + curCount > devEndAddr) // upper bound in process image + { + writeDbg(MbWarning, "ModbusWriteRegisters: Impossible to write %d bits at 0x%04X. Changed count to %d.", curCount, addressO, devEndAddr - addressO); + curCount = devEndAddr - addressO; + } + dataLength = 2 * curCount; overallLength = maxLength - 2*gMaxRegsPerWrite + dataLength; _ModbusMakeHeader(mbreq.Header, overallLength, funcCode); - mbreq.Address = address+offset; // [2] Output address + mbreq.Address = addressO; // [2] Output address mbreq.Count = curCount; // [2] Number of items; 1:max 123=0x7B mbreq.ByteCount = dataLength; // [1] Number of bytes; = 2 * count