Gabriel Rivas / ModbusSlaveRTU

Dependents:   Nucleo_modbus_protocol_test

Committer:
gabrielrivas
Date:
Mon Jan 19 08:12:28 2015 +0000
Revision:
3:71ae7fd3f2fa
Parent:
2:f028bdcd4814
Child:
4:9751b0a81ded
Documentation added.;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gabrielrivas 2:f028bdcd4814 1 /** Modbus Slave RTU
gabrielrivas 1:5efaa10b9a3f 2 * Copyright (c) 2015 Gabriel Rivas
gabrielrivas 1:5efaa10b9a3f 3 *
gabrielrivas 1:5efaa10b9a3f 4 * Licensed under the Apache License, Version 2.0 (the "License");
gabrielrivas 1:5efaa10b9a3f 5 * you may not use this file except in compliance with the License.
gabrielrivas 1:5efaa10b9a3f 6 * You may obtain a copy of the License at
gabrielrivas 1:5efaa10b9a3f 7 *
gabrielrivas 1:5efaa10b9a3f 8 * http://www.apache.org/licenses/LICENSE-2.0
gabrielrivas 1:5efaa10b9a3f 9 *
gabrielrivas 1:5efaa10b9a3f 10 * Unless required by applicable law or agreed to in writing, software
gabrielrivas 1:5efaa10b9a3f 11 * distributed under the License is distributed on an "AS IS" BASIS,
gabrielrivas 1:5efaa10b9a3f 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
gabrielrivas 1:5efaa10b9a3f 13 * See the License for the specific language governing permissions and
gabrielrivas 1:5efaa10b9a3f 14 * limitations under the License.
gabrielrivas 1:5efaa10b9a3f 15 */
gabrielrivas 1:5efaa10b9a3f 16
gabrielrivas 0:81fee41d95f1 17 #ifndef _MODBUS_SLAVE_RTU_H_
gabrielrivas 0:81fee41d95f1 18 #define _MODBUS_SLAVE_RTU_H_
gabrielrivas 0:81fee41d95f1 19
gabrielrivas 0:81fee41d95f1 20 #include "mbed.h"
gabrielrivas 0:81fee41d95f1 21 #include "rtos.h"
gabrielrivas 0:81fee41d95f1 22 #include "MessageQueue.h"
gabrielrivas 0:81fee41d95f1 23
gabrielrivas 0:81fee41d95f1 24 #define MODBUS_MAX_LEN (256)
gabrielrivas 0:81fee41d95f1 25
gabrielrivas 0:81fee41d95f1 26 struct ThreadSafeArray_t {
gabrielrivas 0:81fee41d95f1 27 Mutex mutex;
gabrielrivas 0:81fee41d95f1 28 uint8_t *data;
gabrielrivas 0:81fee41d95f1 29 uint32_t length;
gabrielrivas 0:81fee41d95f1 30 };
gabrielrivas 0:81fee41d95f1 31
gabrielrivas 3:71ae7fd3f2fa 32 /**
gabrielrivas 3:71ae7fd3f2fa 33 * Modbus RTU class for slave devices. It shares data with other software components via a Message queue object,
gabrielrivas 3:71ae7fd3f2fa 34 * and can exist more than one Modbus Slave RTU instances in a application program.
gabrielrivas 3:71ae7fd3f2fa 35 */
gabrielrivas 0:81fee41d95f1 36 class ModbusSlaveRTU
gabrielrivas 0:81fee41d95f1 37 {
gabrielrivas 0:81fee41d95f1 38 public:
gabrielrivas 0:81fee41d95f1 39 /*! Modbus response message bytes indexes. */
gabrielrivas 1:5efaa10b9a3f 40 enum MbByteIndex_t {
gabrielrivas 1:5efaa10b9a3f 41 ADDRESS = 0, /**< Modbus address position.*/
gabrielrivas 1:5efaa10b9a3f 42 FUNCTION = 1, /**< Modbus function position.*/
gabrielrivas 1:5efaa10b9a3f 43 BYTE_COUNT = 2, /**< Byte count high byte position.*/
gabrielrivas 1:5efaa10b9a3f 44 DATA_START = 3, /**< Returned data start position.*/
gabrielrivas 1:5efaa10b9a3f 45 BYTE_OFFSET = 2, /**< Starting register in bytes, high byte position.*/
gabrielrivas 1:5efaa10b9a3f 46 REGISTER_COUNT = 4 /**< Number of registers to be read, high byte position.*/
gabrielrivas 0:81fee41d95f1 47 };
gabrielrivas 0:81fee41d95f1 48
gabrielrivas 0:81fee41d95f1 49 /*! Modbus errors reported during message processing. */
gabrielrivas 0:81fee41d95f1 50 enum MbReceivedMessageErrors_t {
gabrielrivas 1:5efaa10b9a3f 51 NO_ERROR = 0x10, /**< No error.*/
gabrielrivas 1:5efaa10b9a3f 52 ADDRESS_ERROR = 0x11, /**< Wrong slave address.*/
gabrielrivas 1:5efaa10b9a3f 53 CRC_ERROR = 0x12, /**< CRC from received message doesn't match with locally calculated CRC.*/
gabrielrivas 1:5efaa10b9a3f 54 OFFSET_ERROR = 0x13, /**< Offset is out of range.*/
gabrielrivas 1:5efaa10b9a3f 55 BYTE_COUNT_ERROR = 0x14 /**< Byte count requested is out of range.*/
gabrielrivas 0:81fee41d95f1 56 };
gabrielrivas 0:81fee41d95f1 57
gabrielrivas 1:5efaa10b9a3f 58 /*! Status of the internal modbus FSM. */
gabrielrivas 0:81fee41d95f1 59 enum MbStatusTypes_t {
gabrielrivas 1:5efaa10b9a3f 60 LISTENING = 0x20, /**< Listening for incomming requests.*/
gabrielrivas 1:5efaa10b9a3f 61 PROCESSING = 0x21, /**< Processing received request.*/
gabrielrivas 1:5efaa10b9a3f 62 SENDING = 0x23 /**< Sending generated response.*/
gabrielrivas 0:81fee41d95f1 63 };
gabrielrivas 0:81fee41d95f1 64
gabrielrivas 1:5efaa10b9a3f 65 /*! Internal modbus FSM states. */
gabrielrivas 0:81fee41d95f1 66 enum MbSlaveRTUStates_t {
gabrielrivas 1:5efaa10b9a3f 67 WAIT_REQUEST_MESSAGE = 0x00, /**< Idle while bytes are being received.*/
gabrielrivas 1:5efaa10b9a3f 68 GET_RECEIVED_BYTES = 0x01, /**< Copy received bytes into the internal buffer.*/
gabrielrivas 1:5efaa10b9a3f 69 BUILD_RESPONSE_MESSAGE = 0x02, /**< Building response message.*/
gabrielrivas 1:5efaa10b9a3f 70 TRANSMIT_RESPONSE_MESSAGE = 0x03 /**< Transmitting response message.*/
gabrielrivas 0:81fee41d95f1 71 };
gabrielrivas 0:81fee41d95f1 72
gabrielrivas 0:81fee41d95f1 73 /*! Modbus function codes. */
gabrielrivas 0:81fee41d95f1 74 enum MbFunctionCodes_t {
gabrielrivas 0:81fee41d95f1 75 READ_COIL_STATUS = 0x01, /**< Function to read a single coil status.*/
gabrielrivas 0:81fee41d95f1 76 READ_INPUT_STATUS = 0x02, /**< Function to read input register.*/
gabrielrivas 0:81fee41d95f1 77 READ_HOLDING_REGISTERS = 0x03, /**< Function to read one or more internal holding resgisters.*/
gabrielrivas 0:81fee41d95f1 78 READ_INPUT_REGISTERS = 0x04, /**< Function to read one or more input resgisters.*/
gabrielrivas 0:81fee41d95f1 79 FORCE_SINGLE_COIL = 0x05, /**< Function to write a value into a single discrete output.*/
gabrielrivas 0:81fee41d95f1 80 PRESET_SINGLE_REGISTER = 0x06, /**< Function to write a value into a single holding register.*/
gabrielrivas 0:81fee41d95f1 81 READ_EXCEPTION_STATUS = 0x07, /**< Function to request the value of the status byte.*/
gabrielrivas 0:81fee41d95f1 82 LOOPBACK_TEST = 0x08, /**< Function to test the communications interface. Returns the same message.*/
gabrielrivas 0:81fee41d95f1 83 FORCE_MULTIPLE_COILS = 0x0F /**< Function to set more than one coil to a given value*/
gabrielrivas 0:81fee41d95f1 84 };
gabrielrivas 0:81fee41d95f1 85
gabrielrivas 0:81fee41d95f1 86 /*! Modbus frame structure elements. */
gabrielrivas 0:81fee41d95f1 87 struct MbSlaveRTUFrame_t {
gabrielrivas 0:81fee41d95f1 88 uint8_t mAddress; /**< Slave device address.*/
gabrielrivas 0:81fee41d95f1 89 MbFunctionCodes_t mFunction; /**< Requested function of type MbFunctionCodes_t.*/
gabrielrivas 0:81fee41d95f1 90 uint16_t mOffset; /**< Offset in bytes from the starting address.*/
gabrielrivas 1:5efaa10b9a3f 91 uint16_t mByteCount; /**< Number of bytes to respond.*/
gabrielrivas 1:5efaa10b9a3f 92 uint8_t mCRCH; /**< CRC high byte.*/
gabrielrivas 1:5efaa10b9a3f 93 uint8_t mCRCL; /**< CRC low byte.*/
gabrielrivas 1:5efaa10b9a3f 94 uint16_t mSize; /**< Size of the frame in bytes.*/
gabrielrivas 0:81fee41d95f1 95 };
gabrielrivas 0:81fee41d95f1 96
gabrielrivas 1:5efaa10b9a3f 97 /*! Memory map structure. */
gabrielrivas 0:81fee41d95f1 98 struct MemoryMap_t {
gabrielrivas 1:5efaa10b9a3f 99 ThreadSafeArray_t *coilRegisters; /**< Pointer to the coil registers array.*/
gabrielrivas 1:5efaa10b9a3f 100 ThreadSafeArray_t *holdingRegisters; /**< Pointer to the holding registers array.*/
gabrielrivas 1:5efaa10b9a3f 101 ThreadSafeArray_t *inputRegisters; /**< Pointer to the input registers array.*/
gabrielrivas 0:81fee41d95f1 102 };
gabrielrivas 0:81fee41d95f1 103
gabrielrivas 0:81fee41d95f1 104 public:
gabrielrivas 0:81fee41d95f1 105 /**
gabrielrivas 1:5efaa10b9a3f 106 * Creates a Modbus Slave RTU object.
gabrielrivas 1:5efaa10b9a3f 107 * @param id Mosbus address.
gabrielrivas 1:5efaa10b9a3f 108 * @param txQueue Message queue to write modbus responses into.
gabrielrivas 1:5efaa10b9a3f 109 * @param rxQueue Message queue to read modbus requests from.
gabrielrivas 0:81fee41d95f1 110 * @param *coilRegisters Pointer to the memory space reserved for the coil registers.
gabrielrivas 0:81fee41d95f1 111 * @param *inputRegisters Pointer to the memory space reserved for the input registers.
gabrielrivas 0:81fee41d95f1 112 * @param *inputRegisters Pointer to the memory space reserved for the holding registers.
gabrielrivas 0:81fee41d95f1 113 * @return void
gabrielrivas 0:81fee41d95f1 114 */
gabrielrivas 0:81fee41d95f1 115 ModbusSlaveRTU( uint8_t id,
gabrielrivas 0:81fee41d95f1 116 MessageQueue<uint8_t>* txQueue,
gabrielrivas 0:81fee41d95f1 117 MessageQueue<uint8_t>* rxQueue,
gabrielrivas 0:81fee41d95f1 118 ThreadSafeArray_t *coilRegisters,
gabrielrivas 0:81fee41d95f1 119 ThreadSafeArray_t *inputRegisters,
gabrielrivas 0:81fee41d95f1 120 ThreadSafeArray_t *holdingRegisters);
gabrielrivas 0:81fee41d95f1 121
gabrielrivas 0:81fee41d95f1 122 public:
gabrielrivas 0:81fee41d95f1 123 /**
gabrielrivas 1:5efaa10b9a3f 124 * Function to start the Modbus RTU Slave engine.
gabrielrivas 0:81fee41d95f1 125 */
gabrielrivas 0:81fee41d95f1 126 void trigger(void);
gabrielrivas 0:81fee41d95f1 127
gabrielrivas 0:81fee41d95f1 128 /**
gabrielrivas 1:5efaa10b9a3f 129 * Gets the status of the internal FSM.
gabrielrivas 1:5efaa10b9a3f 130 * @return Status value as defined in MbStatusTypes_t.
gabrielrivas 0:81fee41d95f1 131 */
gabrielrivas 0:81fee41d95f1 132 MbStatusTypes_t getStatus(void);
gabrielrivas 1:5efaa10b9a3f 133
gabrielrivas 1:5efaa10b9a3f 134 /**
gabrielrivas 1:5efaa10b9a3f 135 * Internal FSM process.
gabrielrivas 1:5efaa10b9a3f 136 */
gabrielrivas 0:81fee41d95f1 137 void FSM(void);
gabrielrivas 0:81fee41d95f1 138
gabrielrivas 0:81fee41d95f1 139 private:
gabrielrivas 1:5efaa10b9a3f 140 /**
gabrielrivas 1:5efaa10b9a3f 141 * Handler for read holding registers function request.
gabrielrivas 1:5efaa10b9a3f 142 * @return Error or success code as defined in MbReceivedMessageErrors_t.
gabrielrivas 1:5efaa10b9a3f 143 */
gabrielrivas 1:5efaa10b9a3f 144 MbReceivedMessageErrors_t readHoldingRegistersHandler(void);
gabrielrivas 1:5efaa10b9a3f 145
gabrielrivas 1:5efaa10b9a3f 146 /**
gabrielrivas 1:5efaa10b9a3f 147 * Handler for read coil registers function request.
gabrielrivas 1:5efaa10b9a3f 148 * @return Error or success code as defined in MbReceivedMessageErrors_t.
gabrielrivas 1:5efaa10b9a3f 149 */
gabrielrivas 1:5efaa10b9a3f 150 MbReceivedMessageErrors_t readCoilRegistersHandler(void);
gabrielrivas 1:5efaa10b9a3f 151
gabrielrivas 1:5efaa10b9a3f 152 /**
gabrielrivas 1:5efaa10b9a3f 153 * Builds response message.
gabrielrivas 1:5efaa10b9a3f 154 * @return Error or success code as defined in MbReceivedMessageErrors_t.
gabrielrivas 1:5efaa10b9a3f 155 */
gabrielrivas 1:5efaa10b9a3f 156 MbReceivedMessageErrors_t buildResponse(void);
gabrielrivas 0:81fee41d95f1 157
gabrielrivas 0:81fee41d95f1 158 /**
gabrielrivas 1:5efaa10b9a3f 159 * Function that computes the CRC of a Modbus message.
gabrielrivas 0:81fee41d95f1 160 * @param *data Pointer to the message data.
gabrielrivas 0:81fee41d95f1 161 * @param uint8_t Length of the message.
gabrielrivas 0:81fee41d95f1 162 * @return The CRC Code.
gabrielrivas 0:81fee41d95f1 163 */
gabrielrivas 0:81fee41d95f1 164 uint16_t getCRC(uint8_t * data,uint8_t len);
gabrielrivas 0:81fee41d95f1 165
gabrielrivas 0:81fee41d95f1 166 /**
gabrielrivas 1:5efaa10b9a3f 167 * Verifies the CRC value of a message to determine it has been received correctly.
gabrielrivas 0:81fee41d95f1 168 * @param *data Pointer to the message data.
gabrielrivas 0:81fee41d95f1 169 * @return Returns 1 if the message has been well received, 0 otherwise.
gabrielrivas 0:81fee41d95f1 170 */
gabrielrivas 0:81fee41d95f1 171 uint8_t checkMessageCRC(uint8_t * data);
gabrielrivas 0:81fee41d95f1 172
gabrielrivas 0:81fee41d95f1 173 /**
gabrielrivas 1:5efaa10b9a3f 174 * Function that appends the header and tail bytes for a response message.
gabrielrivas 0:81fee41d95f1 175 * @return void.
gabrielrivas 0:81fee41d95f1 176 */
gabrielrivas 0:81fee41d95f1 177 void appendHeaderAndTailToMessage(void);
gabrielrivas 0:81fee41d95f1 178
gabrielrivas 0:81fee41d95f1 179 /**
gabrielrivas 1:5efaa10b9a3f 180 * Function that checks for error in the received message.
gabrielrivas 0:81fee41d95f1 181 * @param *array Safe array being processed depending on the modbus function.
gabrielrivas 1:5efaa10b9a3f 182 * @return The error or success code as defined in MbReceivedMessageErrors_t.
gabrielrivas 0:81fee41d95f1 183 */
gabrielrivas 1:5efaa10b9a3f 184 MbReceivedMessageErrors_t checkReceivedMessageErrors(ThreadSafeArray_t *array);
gabrielrivas 0:81fee41d95f1 185
gabrielrivas 0:81fee41d95f1 186 private:
gabrielrivas 1:5efaa10b9a3f 187 /** Internal state of the modbus FSM.
gabrielrivas 1:5efaa10b9a3f 188 */
gabrielrivas 0:81fee41d95f1 189 MbSlaveRTUStates_t m_state;
gabrielrivas 1:5efaa10b9a3f 190
gabrielrivas 1:5efaa10b9a3f 191 /** Response frame.
gabrielrivas 1:5efaa10b9a3f 192 */
gabrielrivas 0:81fee41d95f1 193 MbSlaveRTUFrame_t m_frame;
gabrielrivas 1:5efaa10b9a3f 194
gabrielrivas 1:5efaa10b9a3f 195 /** Modbus address.
gabrielrivas 1:5efaa10b9a3f 196 */
gabrielrivas 1:5efaa10b9a3f 197 uint8_t m_address;
gabrielrivas 1:5efaa10b9a3f 198
gabrielrivas 1:5efaa10b9a3f 199 /** Modbus process status.
gabrielrivas 1:5efaa10b9a3f 200 */
gabrielrivas 1:5efaa10b9a3f 201 MbStatusTypes_t m_status;
gabrielrivas 1:5efaa10b9a3f 202
gabrielrivas 1:5efaa10b9a3f 203 /** Memory map for registers.
gabrielrivas 1:5efaa10b9a3f 204 */
gabrielrivas 0:81fee41d95f1 205 MemoryMap_t m_memoryMap;
gabrielrivas 1:5efaa10b9a3f 206
gabrielrivas 1:5efaa10b9a3f 207 /** Queue to write response data.
gabrielrivas 1:5efaa10b9a3f 208 */
gabrielrivas 0:81fee41d95f1 209 MessageQueue<uint8_t>* m_bTxQueue;
gabrielrivas 1:5efaa10b9a3f 210
gabrielrivas 1:5efaa10b9a3f 211 /** Queue to read incomming requests from.
gabrielrivas 1:5efaa10b9a3f 212 */
gabrielrivas 0:81fee41d95f1 213 MessageQueue<uint8_t>* m_bRxQueue;
gabrielrivas 1:5efaa10b9a3f 214
gabrielrivas 1:5efaa10b9a3f 215 /** Internal byte array to copy incomming requests.
gabrielrivas 1:5efaa10b9a3f 216 */
gabrielrivas 0:81fee41d95f1 217 uint8_t m_receivedMessage[MODBUS_MAX_LEN];
gabrielrivas 1:5efaa10b9a3f 218
gabrielrivas 1:5efaa10b9a3f 219 /** Internal byte array to generate responses.
gabrielrivas 1:5efaa10b9a3f 220 */
gabrielrivas 0:81fee41d95f1 221 uint8_t m_responseMessage[MODBUS_MAX_LEN];
gabrielrivas 0:81fee41d95f1 222 };
gabrielrivas 0:81fee41d95f1 223 #endif