Modbus RTU class for slave devices. It shares data with other software components via a Message queue object, and can exist more than one Modbus Slave RTU instances in a application program.
Dependents: Nucleo_modbus_protocol_test
ModbusSlaveRTU.cpp@6:0143a57e0c8e, 2015-01-21 (annotated)
- Committer:
- gabrielrivas
- Date:
- Wed Jan 21 02:59:27 2015 +0000
- Revision:
- 6:0143a57e0c8e
- Parent:
- 1:5efaa10b9a3f
Added timer based synchronization to the serial port receiving part.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
gabrielrivas | 0:81fee41d95f1 | 1 | /* Modbus RTU Slave Library |
gabrielrivas | 1:5efaa10b9a3f | 2 | * Copyright (c) 2015 Gabriel Rivas |
gabrielrivas | 0:81fee41d95f1 | 3 | * |
gabrielrivas | 0:81fee41d95f1 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
gabrielrivas | 0:81fee41d95f1 | 5 | * you may not use this file except in compliance with the License. |
gabrielrivas | 0:81fee41d95f1 | 6 | * You may obtain a copy of the License at |
gabrielrivas | 0:81fee41d95f1 | 7 | * |
gabrielrivas | 0:81fee41d95f1 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
gabrielrivas | 0:81fee41d95f1 | 9 | * |
gabrielrivas | 0:81fee41d95f1 | 10 | * Unless required by applicable law or agreed to in writing, software |
gabrielrivas | 0:81fee41d95f1 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
gabrielrivas | 0:81fee41d95f1 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
gabrielrivas | 0:81fee41d95f1 | 13 | * See the License for the specific language governing permissions and |
gabrielrivas | 0:81fee41d95f1 | 14 | * limitations under the License. |
gabrielrivas | 0:81fee41d95f1 | 15 | */ |
gabrielrivas | 0:81fee41d95f1 | 16 | |
gabrielrivas | 0:81fee41d95f1 | 17 | #include "ModbusSlaveRTU.h" |
gabrielrivas | 0:81fee41d95f1 | 18 | #include "MessageQueue.h" |
gabrielrivas | 0:81fee41d95f1 | 19 | |
gabrielrivas | 0:81fee41d95f1 | 20 | #define MODBUS_FRAME_OVERHEAD_BYTES (5) |
gabrielrivas | 0:81fee41d95f1 | 21 | #define MODBUS_ID_FUNCTION_SIZE (3) |
gabrielrivas | 0:81fee41d95f1 | 22 | #define CRC_POSITION1 (m_frame.mByteCount + MODBUS_ID_FUNCTION_SIZE) |
gabrielrivas | 0:81fee41d95f1 | 23 | #define CRC_POSITION2 (m_frame.mByteCount + MODBUS_ID_FUNCTION_SIZE + 1) |
gabrielrivas | 0:81fee41d95f1 | 24 | |
gabrielrivas | 0:81fee41d95f1 | 25 | ModbusSlaveRTU::ModbusSlaveRTU( uint8_t id, |
gabrielrivas | 0:81fee41d95f1 | 26 | MessageQueue<uint8_t>* txQueue, |
gabrielrivas | 0:81fee41d95f1 | 27 | MessageQueue<uint8_t>* rxQueue, |
gabrielrivas | 0:81fee41d95f1 | 28 | ThreadSafeArray_t *coilRegisters, |
gabrielrivas | 0:81fee41d95f1 | 29 | ThreadSafeArray_t *inputRegisters, |
gabrielrivas | 0:81fee41d95f1 | 30 | ThreadSafeArray_t *holdingRegisters) |
gabrielrivas | 0:81fee41d95f1 | 31 | { |
gabrielrivas | 0:81fee41d95f1 | 32 | // assert(txQueue != NULL); |
gabrielrivas | 0:81fee41d95f1 | 33 | m_bTxQueue = txQueue; |
gabrielrivas | 0:81fee41d95f1 | 34 | |
gabrielrivas | 0:81fee41d95f1 | 35 | // assert(rxQueue != NULL); |
gabrielrivas | 0:81fee41d95f1 | 36 | m_bRxQueue = rxQueue; |
gabrielrivas | 0:81fee41d95f1 | 37 | |
gabrielrivas | 0:81fee41d95f1 | 38 | m_state = WAIT_REQUEST_MESSAGE; |
gabrielrivas | 0:81fee41d95f1 | 39 | |
gabrielrivas | 1:5efaa10b9a3f | 40 | m_address = id; |
gabrielrivas | 1:5efaa10b9a3f | 41 | m_status = LISTENING; |
gabrielrivas | 0:81fee41d95f1 | 42 | |
gabrielrivas | 0:81fee41d95f1 | 43 | // assert(coilRegisters != NULL); |
gabrielrivas | 0:81fee41d95f1 | 44 | m_memoryMap.coilRegisters = coilRegisters; |
gabrielrivas | 0:81fee41d95f1 | 45 | |
gabrielrivas | 0:81fee41d95f1 | 46 | // assert(inputRegisters != NULL); |
gabrielrivas | 0:81fee41d95f1 | 47 | m_memoryMap.inputRegisters = inputRegisters; |
gabrielrivas | 0:81fee41d95f1 | 48 | |
gabrielrivas | 0:81fee41d95f1 | 49 | // assert(holdingRegisters != NULL); |
gabrielrivas | 0:81fee41d95f1 | 50 | m_memoryMap.holdingRegisters = holdingRegisters; |
gabrielrivas | 0:81fee41d95f1 | 51 | } |
gabrielrivas | 0:81fee41d95f1 | 52 | |
gabrielrivas | 0:81fee41d95f1 | 53 | void ModbusSlaveRTU::trigger(void) |
gabrielrivas | 0:81fee41d95f1 | 54 | { |
gabrielrivas | 0:81fee41d95f1 | 55 | m_state = GET_RECEIVED_BYTES; |
gabrielrivas | 0:81fee41d95f1 | 56 | } |
gabrielrivas | 0:81fee41d95f1 | 57 | |
gabrielrivas | 0:81fee41d95f1 | 58 | ModbusSlaveRTU::MbStatusTypes_t ModbusSlaveRTU::getStatus(void) |
gabrielrivas | 0:81fee41d95f1 | 59 | { |
gabrielrivas | 1:5efaa10b9a3f | 60 | return m_status; |
gabrielrivas | 0:81fee41d95f1 | 61 | } |
gabrielrivas | 0:81fee41d95f1 | 62 | |
gabrielrivas | 0:81fee41d95f1 | 63 | void ModbusSlaveRTU::FSM(void) |
gabrielrivas | 0:81fee41d95f1 | 64 | { |
gabrielrivas | 0:81fee41d95f1 | 65 | uint32_t count; |
gabrielrivas | 0:81fee41d95f1 | 66 | |
gabrielrivas | 0:81fee41d95f1 | 67 | switch(m_state) { |
gabrielrivas | 0:81fee41d95f1 | 68 | case WAIT_REQUEST_MESSAGE: |
gabrielrivas | 1:5efaa10b9a3f | 69 | m_status = LISTENING; |
gabrielrivas | 0:81fee41d95f1 | 70 | |
gabrielrivas | 0:81fee41d95f1 | 71 | break; |
gabrielrivas | 0:81fee41d95f1 | 72 | case GET_RECEIVED_BYTES: |
gabrielrivas | 0:81fee41d95f1 | 73 | count = m_bRxQueue->getWriteIndex(); |
gabrielrivas | 1:5efaa10b9a3f | 74 | m_status = PROCESSING; |
gabrielrivas | 0:81fee41d95f1 | 75 | if ((count > 0) && (count < MODBUS_MAX_LEN)) { |
gabrielrivas | 0:81fee41d95f1 | 76 | for (uint32_t i = 0; i < count; i++) { |
gabrielrivas | 0:81fee41d95f1 | 77 | uint8_t data = m_bRxQueue->read(); |
gabrielrivas | 0:81fee41d95f1 | 78 | m_receivedMessage[i] = data; |
gabrielrivas | 0:81fee41d95f1 | 79 | } |
gabrielrivas | 0:81fee41d95f1 | 80 | m_state = BUILD_RESPONSE_MESSAGE; |
gabrielrivas | 0:81fee41d95f1 | 81 | m_bRxQueue->reset(); |
gabrielrivas | 0:81fee41d95f1 | 82 | } else { |
gabrielrivas | 0:81fee41d95f1 | 83 | m_state = WAIT_REQUEST_MESSAGE; |
gabrielrivas | 0:81fee41d95f1 | 84 | } |
gabrielrivas | 0:81fee41d95f1 | 85 | break; |
gabrielrivas | 0:81fee41d95f1 | 86 | case BUILD_RESPONSE_MESSAGE: |
gabrielrivas | 1:5efaa10b9a3f | 87 | if (buildResponse() == NO_ERROR) { |
gabrielrivas | 1:5efaa10b9a3f | 88 | m_status = SENDING; |
gabrielrivas | 0:81fee41d95f1 | 89 | m_state = TRANSMIT_RESPONSE_MESSAGE; |
gabrielrivas | 0:81fee41d95f1 | 90 | } else { |
gabrielrivas | 1:5efaa10b9a3f | 91 | m_status = LISTENING; |
gabrielrivas | 0:81fee41d95f1 | 92 | m_state = WAIT_REQUEST_MESSAGE; |
gabrielrivas | 0:81fee41d95f1 | 93 | } |
gabrielrivas | 0:81fee41d95f1 | 94 | break; |
gabrielrivas | 0:81fee41d95f1 | 95 | case TRANSMIT_RESPONSE_MESSAGE: |
gabrielrivas | 0:81fee41d95f1 | 96 | for (uint32_t i = 0; i < m_frame.mSize; i++) { |
gabrielrivas | 0:81fee41d95f1 | 97 | m_bTxQueue->write(m_responseMessage[i]); |
gabrielrivas | 0:81fee41d95f1 | 98 | } |
gabrielrivas | 0:81fee41d95f1 | 99 | |
gabrielrivas | 1:5efaa10b9a3f | 100 | m_status = LISTENING; |
gabrielrivas | 0:81fee41d95f1 | 101 | m_state = WAIT_REQUEST_MESSAGE; |
gabrielrivas | 0:81fee41d95f1 | 102 | break; |
gabrielrivas | 0:81fee41d95f1 | 103 | default: |
gabrielrivas | 0:81fee41d95f1 | 104 | break; |
gabrielrivas | 0:81fee41d95f1 | 105 | } |
gabrielrivas | 0:81fee41d95f1 | 106 | |
gabrielrivas | 0:81fee41d95f1 | 107 | } |
gabrielrivas | 0:81fee41d95f1 | 108 | |
gabrielrivas | 1:5efaa10b9a3f | 109 | ModbusSlaveRTU::MbReceivedMessageErrors_t ModbusSlaveRTU::buildResponse(void) |
gabrielrivas | 0:81fee41d95f1 | 110 | { |
gabrielrivas | 1:5efaa10b9a3f | 111 | MbReceivedMessageErrors_t result = NO_ERROR; |
gabrielrivas | 0:81fee41d95f1 | 112 | |
gabrielrivas | 0:81fee41d95f1 | 113 | switch(m_receivedMessage[FUNCTION]) { |
gabrielrivas | 0:81fee41d95f1 | 114 | case READ_COIL_STATUS: |
gabrielrivas | 0:81fee41d95f1 | 115 | result = readCoilRegistersHandler(); |
gabrielrivas | 0:81fee41d95f1 | 116 | break; |
gabrielrivas | 0:81fee41d95f1 | 117 | case READ_HOLDING_REGISTERS: |
gabrielrivas | 0:81fee41d95f1 | 118 | result = readHoldingRegistersHandler(); |
gabrielrivas | 0:81fee41d95f1 | 119 | break; |
gabrielrivas | 0:81fee41d95f1 | 120 | case FORCE_SINGLE_COIL: |
gabrielrivas | 0:81fee41d95f1 | 121 | break; |
gabrielrivas | 0:81fee41d95f1 | 122 | default: |
gabrielrivas | 0:81fee41d95f1 | 123 | break; |
gabrielrivas | 0:81fee41d95f1 | 124 | } |
gabrielrivas | 0:81fee41d95f1 | 125 | |
gabrielrivas | 0:81fee41d95f1 | 126 | return result; |
gabrielrivas | 0:81fee41d95f1 | 127 | } |
gabrielrivas | 0:81fee41d95f1 | 128 | |
gabrielrivas | 0:81fee41d95f1 | 129 | uint8_t ModbusSlaveRTU::checkMessageCRC(uint8_t * data) |
gabrielrivas | 0:81fee41d95f1 | 130 | { |
gabrielrivas | 0:81fee41d95f1 | 131 | uint8_t function = data[FUNCTION]; |
gabrielrivas | 0:81fee41d95f1 | 132 | uint8_t byteCount; |
gabrielrivas | 0:81fee41d95f1 | 133 | uint16_t crcVal; |
gabrielrivas | 0:81fee41d95f1 | 134 | uint16_t crcCalc; |
gabrielrivas | 0:81fee41d95f1 | 135 | uint8_t result; |
gabrielrivas | 0:81fee41d95f1 | 136 | |
gabrielrivas | 0:81fee41d95f1 | 137 | if (function != READ_EXCEPTION_STATUS) { |
gabrielrivas | 0:81fee41d95f1 | 138 | byteCount = 8; |
gabrielrivas | 0:81fee41d95f1 | 139 | crcVal = data[byteCount-1]; |
gabrielrivas | 0:81fee41d95f1 | 140 | crcVal = (crcVal << 8) | data[byteCount - 2]; |
gabrielrivas | 0:81fee41d95f1 | 141 | crcCalc = getCRC(data, byteCount - 2); |
gabrielrivas | 0:81fee41d95f1 | 142 | |
gabrielrivas | 0:81fee41d95f1 | 143 | if (crcVal == crcCalc) { |
gabrielrivas | 0:81fee41d95f1 | 144 | result = 1; |
gabrielrivas | 0:81fee41d95f1 | 145 | } else { |
gabrielrivas | 0:81fee41d95f1 | 146 | result = 0; |
gabrielrivas | 0:81fee41d95f1 | 147 | } |
gabrielrivas | 0:81fee41d95f1 | 148 | } else { |
gabrielrivas | 0:81fee41d95f1 | 149 | result = 0; |
gabrielrivas | 0:81fee41d95f1 | 150 | } |
gabrielrivas | 0:81fee41d95f1 | 151 | |
gabrielrivas | 0:81fee41d95f1 | 152 | return result; |
gabrielrivas | 0:81fee41d95f1 | 153 | } |
gabrielrivas | 0:81fee41d95f1 | 154 | |
gabrielrivas | 0:81fee41d95f1 | 155 | uint16_t ModbusSlaveRTU::getCRC(uint8_t * data,uint8_t len) |
gabrielrivas | 0:81fee41d95f1 | 156 | { |
gabrielrivas | 0:81fee41d95f1 | 157 | uint16_t crc = 0xFFFF; |
gabrielrivas | 0:81fee41d95f1 | 158 | uint8_t i; |
gabrielrivas | 0:81fee41d95f1 | 159 | |
gabrielrivas | 0:81fee41d95f1 | 160 | while (len--) { |
gabrielrivas | 0:81fee41d95f1 | 161 | i = *data++; |
gabrielrivas | 0:81fee41d95f1 | 162 | *(uint8_t *)&crc ^= i; |
gabrielrivas | 0:81fee41d95f1 | 163 | |
gabrielrivas | 0:81fee41d95f1 | 164 | for (i = 0; i != 8; i++) { |
gabrielrivas | 0:81fee41d95f1 | 165 | if (crc & 0x0001) { |
gabrielrivas | 0:81fee41d95f1 | 166 | crc = (crc >> 1); |
gabrielrivas | 0:81fee41d95f1 | 167 | crc ^= 0xA001; |
gabrielrivas | 0:81fee41d95f1 | 168 | } else { |
gabrielrivas | 0:81fee41d95f1 | 169 | crc = (crc >> 1); |
gabrielrivas | 0:81fee41d95f1 | 170 | } |
gabrielrivas | 0:81fee41d95f1 | 171 | } |
gabrielrivas | 0:81fee41d95f1 | 172 | } |
gabrielrivas | 0:81fee41d95f1 | 173 | return crc; |
gabrielrivas | 0:81fee41d95f1 | 174 | } |
gabrielrivas | 0:81fee41d95f1 | 175 | |
gabrielrivas | 1:5efaa10b9a3f | 176 | ModbusSlaveRTU::MbReceivedMessageErrors_t ModbusSlaveRTU::readHoldingRegistersHandler(void) |
gabrielrivas | 0:81fee41d95f1 | 177 | { |
gabrielrivas | 0:81fee41d95f1 | 178 | uint8_t i; |
gabrielrivas | 1:5efaa10b9a3f | 179 | MbReceivedMessageErrors_t result = NO_ERROR; |
gabrielrivas | 0:81fee41d95f1 | 180 | |
gabrielrivas | 0:81fee41d95f1 | 181 | m_frame.mAddress = m_receivedMessage[ADDRESS]; |
gabrielrivas | 0:81fee41d95f1 | 182 | m_frame.mFunction = static_cast<MbFunctionCodes_t>(m_receivedMessage[FUNCTION]); |
gabrielrivas | 0:81fee41d95f1 | 183 | |
gabrielrivas | 0:81fee41d95f1 | 184 | result = checkReceivedMessageErrors(m_memoryMap.holdingRegisters); |
gabrielrivas | 0:81fee41d95f1 | 185 | |
gabrielrivas | 0:81fee41d95f1 | 186 | if (result < ADDRESS_ERROR) { |
gabrielrivas | 1:5efaa10b9a3f | 187 | m_frame.mByteCount = ((m_receivedMessage[REGISTER_COUNT] << 8) | (m_receivedMessage[REGISTER_COUNT + 1] & 0xFF)); |
gabrielrivas | 0:81fee41d95f1 | 188 | m_frame.mByteCount <<= 1; |
gabrielrivas | 0:81fee41d95f1 | 189 | |
gabrielrivas | 0:81fee41d95f1 | 190 | |
gabrielrivas | 0:81fee41d95f1 | 191 | if ((m_frame.mByteCount + m_frame.mOffset) > m_memoryMap.holdingRegisters->length) |
gabrielrivas | 0:81fee41d95f1 | 192 | m_frame.mByteCount = m_memoryMap.holdingRegisters->length - m_frame.mOffset; |
gabrielrivas | 0:81fee41d95f1 | 193 | |
gabrielrivas | 0:81fee41d95f1 | 194 | (m_memoryMap.holdingRegisters)->mutex.lock(); |
gabrielrivas | 0:81fee41d95f1 | 195 | |
gabrielrivas | 0:81fee41d95f1 | 196 | m_frame.mSize = m_frame.mByteCount + MODBUS_FRAME_OVERHEAD_BYTES; |
gabrielrivas | 0:81fee41d95f1 | 197 | |
gabrielrivas | 0:81fee41d95f1 | 198 | for(i = 0; i < m_frame.mByteCount; i++) { |
gabrielrivas | 0:81fee41d95f1 | 199 | m_responseMessage[i + DATA_START] = *((m_memoryMap.holdingRegisters)->data + i + m_frame.mOffset); |
gabrielrivas | 0:81fee41d95f1 | 200 | } |
gabrielrivas | 0:81fee41d95f1 | 201 | |
gabrielrivas | 0:81fee41d95f1 | 202 | appendHeaderAndTailToMessage(); |
gabrielrivas | 0:81fee41d95f1 | 203 | |
gabrielrivas | 0:81fee41d95f1 | 204 | (m_memoryMap.holdingRegisters)->mutex.unlock(); |
gabrielrivas | 0:81fee41d95f1 | 205 | } |
gabrielrivas | 0:81fee41d95f1 | 206 | |
gabrielrivas | 0:81fee41d95f1 | 207 | return result; |
gabrielrivas | 0:81fee41d95f1 | 208 | } |
gabrielrivas | 0:81fee41d95f1 | 209 | |
gabrielrivas | 1:5efaa10b9a3f | 210 | ModbusSlaveRTU::MbReceivedMessageErrors_t ModbusSlaveRTU::readCoilRegistersHandler(void) |
gabrielrivas | 0:81fee41d95f1 | 211 | { |
gabrielrivas | 1:5efaa10b9a3f | 212 | MbReceivedMessageErrors_t result = NO_ERROR; |
gabrielrivas | 0:81fee41d95f1 | 213 | uint16_t initRegister; |
gabrielrivas | 0:81fee41d95f1 | 214 | uint16_t initCoil; |
gabrielrivas | 0:81fee41d95f1 | 215 | uint16_t endRegister; |
gabrielrivas | 0:81fee41d95f1 | 216 | uint16_t i = 0; |
gabrielrivas | 0:81fee41d95f1 | 217 | uint16_t j = 0; |
gabrielrivas | 0:81fee41d95f1 | 218 | uint8_t mask; |
gabrielrivas | 0:81fee41d95f1 | 219 | uint8_t residual_bits; |
gabrielrivas | 0:81fee41d95f1 | 220 | |
gabrielrivas | 0:81fee41d95f1 | 221 | m_frame.mAddress = m_receivedMessage[ADDRESS]; |
gabrielrivas | 0:81fee41d95f1 | 222 | m_frame.mFunction = static_cast<MbFunctionCodes_t>(m_receivedMessage[FUNCTION]); |
gabrielrivas | 0:81fee41d95f1 | 223 | |
gabrielrivas | 0:81fee41d95f1 | 224 | result = checkReceivedMessageErrors(m_memoryMap.coilRegisters); |
gabrielrivas | 0:81fee41d95f1 | 225 | |
gabrielrivas | 0:81fee41d95f1 | 226 | if (result < ADDRESS_ERROR) { |
gabrielrivas | 1:5efaa10b9a3f | 227 | m_frame.mByteCount = ((m_receivedMessage[REGISTER_COUNT] << 8) | (m_receivedMessage[REGISTER_COUNT + 1] & 0xFF)); |
gabrielrivas | 0:81fee41d95f1 | 228 | |
gabrielrivas | 0:81fee41d95f1 | 229 | residual_bits = (m_frame.mByteCount) % 8; |
gabrielrivas | 0:81fee41d95f1 | 230 | m_frame.mByteCount >>= 3; |
gabrielrivas | 0:81fee41d95f1 | 231 | |
gabrielrivas | 0:81fee41d95f1 | 232 | if (residual_bits > 0) |
gabrielrivas | 0:81fee41d95f1 | 233 | m_frame.mByteCount += 1; |
gabrielrivas | 0:81fee41d95f1 | 234 | |
gabrielrivas | 0:81fee41d95f1 | 235 | initRegister = m_frame.mOffset >> 3; |
gabrielrivas | 0:81fee41d95f1 | 236 | initCoil = m_frame.mOffset % 8; |
gabrielrivas | 0:81fee41d95f1 | 237 | endRegister = initRegister + (m_frame.mByteCount); |
gabrielrivas | 0:81fee41d95f1 | 238 | |
gabrielrivas | 0:81fee41d95f1 | 239 | if (m_frame.mByteCount == 0) |
gabrielrivas | 0:81fee41d95f1 | 240 | endRegister -= 1; |
gabrielrivas | 0:81fee41d95f1 | 241 | |
gabrielrivas | 0:81fee41d95f1 | 242 | mask = (1 << residual_bits) - 1; |
gabrielrivas | 0:81fee41d95f1 | 243 | |
gabrielrivas | 0:81fee41d95f1 | 244 | if ((m_frame.mByteCount + m_frame.mOffset) > m_memoryMap.holdingRegisters->length) |
gabrielrivas | 0:81fee41d95f1 | 245 | m_frame.mByteCount = m_memoryMap.holdingRegisters->length - m_frame.mOffset; |
gabrielrivas | 0:81fee41d95f1 | 246 | |
gabrielrivas | 0:81fee41d95f1 | 247 | m_frame.mSize = m_frame.mByteCount + MODBUS_FRAME_OVERHEAD_BYTES; |
gabrielrivas | 0:81fee41d95f1 | 248 | |
gabrielrivas | 0:81fee41d95f1 | 249 | m_memoryMap.coilRegisters->mutex.lock(); |
gabrielrivas | 0:81fee41d95f1 | 250 | |
gabrielrivas | 0:81fee41d95f1 | 251 | //Process coil data to generate the response message. |
gabrielrivas | 0:81fee41d95f1 | 252 | for (i = initRegister; i < endRegister; i++) { |
gabrielrivas | 0:81fee41d95f1 | 253 | m_responseMessage[j++ + DATA_START] = (m_memoryMap.coilRegisters->data[i] >> initCoil) | |
gabrielrivas | 0:81fee41d95f1 | 254 | (m_memoryMap.coilRegisters->data[i+1] << (8 - initCoil)); |
gabrielrivas | 0:81fee41d95f1 | 255 | } |
gabrielrivas | 0:81fee41d95f1 | 256 | |
gabrielrivas | 0:81fee41d95f1 | 257 | m_responseMessage[j + DATA_START] = (m_memoryMap.coilRegisters->data[i] >> initCoil) | |
gabrielrivas | 0:81fee41d95f1 | 258 | (m_memoryMap.coilRegisters->data[i+1] << (8 - initCoil)); |
gabrielrivas | 0:81fee41d95f1 | 259 | m_responseMessage[j + DATA_START] &= mask; |
gabrielrivas | 0:81fee41d95f1 | 260 | |
gabrielrivas | 0:81fee41d95f1 | 261 | appendHeaderAndTailToMessage(); |
gabrielrivas | 0:81fee41d95f1 | 262 | |
gabrielrivas | 0:81fee41d95f1 | 263 | m_memoryMap.coilRegisters->mutex.unlock(); |
gabrielrivas | 0:81fee41d95f1 | 264 | } |
gabrielrivas | 0:81fee41d95f1 | 265 | |
gabrielrivas | 0:81fee41d95f1 | 266 | return result; |
gabrielrivas | 0:81fee41d95f1 | 267 | } |
gabrielrivas | 0:81fee41d95f1 | 268 | |
gabrielrivas | 0:81fee41d95f1 | 269 | void ModbusSlaveRTU::appendHeaderAndTailToMessage(void) |
gabrielrivas | 0:81fee41d95f1 | 270 | { |
gabrielrivas | 0:81fee41d95f1 | 271 | uint16_t mCRC; |
gabrielrivas | 0:81fee41d95f1 | 272 | |
gabrielrivas | 0:81fee41d95f1 | 273 | m_responseMessage[ADDRESS] = m_frame.mAddress; |
gabrielrivas | 0:81fee41d95f1 | 274 | m_responseMessage[FUNCTION] = m_frame.mFunction; |
gabrielrivas | 0:81fee41d95f1 | 275 | m_responseMessage[BYTE_COUNT] = m_frame.mByteCount; |
gabrielrivas | 0:81fee41d95f1 | 276 | |
gabrielrivas | 0:81fee41d95f1 | 277 | mCRC = getCRC(m_responseMessage,m_frame.mByteCount + DATA_START); |
gabrielrivas | 0:81fee41d95f1 | 278 | |
gabrielrivas | 0:81fee41d95f1 | 279 | m_responseMessage[CRC_POSITION1] = (uint8_t) mCRC & 0xFF; |
gabrielrivas | 0:81fee41d95f1 | 280 | m_responseMessage[CRC_POSITION2] = (uint8_t) (mCRC >> 8) & 0xFF; |
gabrielrivas | 0:81fee41d95f1 | 281 | } |
gabrielrivas | 0:81fee41d95f1 | 282 | |
gabrielrivas | 1:5efaa10b9a3f | 283 | ModbusSlaveRTU::MbReceivedMessageErrors_t ModbusSlaveRTU::checkReceivedMessageErrors(ThreadSafeArray_t *array) |
gabrielrivas | 0:81fee41d95f1 | 284 | { |
gabrielrivas | 1:5efaa10b9a3f | 285 | MbReceivedMessageErrors_t result = NO_ERROR; |
gabrielrivas | 0:81fee41d95f1 | 286 | |
gabrielrivas | 0:81fee41d95f1 | 287 | //Check if Modbus Address is correct |
gabrielrivas | 1:5efaa10b9a3f | 288 | if (m_frame.mAddress != m_address) { |
gabrielrivas | 0:81fee41d95f1 | 289 | result = ADDRESS_ERROR; |
gabrielrivas | 0:81fee41d95f1 | 290 | } |
gabrielrivas | 0:81fee41d95f1 | 291 | |
gabrielrivas | 0:81fee41d95f1 | 292 | //Verify message errors |
gabrielrivas | 0:81fee41d95f1 | 293 | if (checkMessageCRC(m_receivedMessage) == 0) { |
gabrielrivas | 0:81fee41d95f1 | 294 | result = CRC_ERROR; |
gabrielrivas | 0:81fee41d95f1 | 295 | } |
gabrielrivas | 0:81fee41d95f1 | 296 | |
gabrielrivas | 0:81fee41d95f1 | 297 | //Verify offset |
gabrielrivas | 1:5efaa10b9a3f | 298 | m_frame.mOffset = ((m_receivedMessage[BYTE_OFFSET] << 8) | (m_receivedMessage[BYTE_OFFSET + 1] & 0xFF)); |
gabrielrivas | 0:81fee41d95f1 | 299 | if ((m_frame.mOffset > array->length - 1) || |
gabrielrivas | 0:81fee41d95f1 | 300 | (m_frame.mOffset > MODBUS_MAX_LEN-1)) { |
gabrielrivas | 0:81fee41d95f1 | 301 | result = OFFSET_ERROR; |
gabrielrivas | 0:81fee41d95f1 | 302 | } |
gabrielrivas | 0:81fee41d95f1 | 303 | |
gabrielrivas | 0:81fee41d95f1 | 304 | return result; |
gabrielrivas | 0:81fee41d95f1 | 305 | } |