Gabriel Rivas / ModbusSlaveRTU

Dependents:   Nucleo_modbus_protocol_test

Committer:
gabrielrivas
Date:
Mon Jan 19 03:29:36 2015 +0000
Revision:
0:81fee41d95f1
Child:
1:5efaa10b9a3f
First version of ModbusSlaveRTU for C++.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gabrielrivas 0:81fee41d95f1 1 #ifndef _MODBUS_SLAVE_RTU_H_
gabrielrivas 0:81fee41d95f1 2 #define _MODBUS_SLAVE_RTU_H_
gabrielrivas 0:81fee41d95f1 3
gabrielrivas 0:81fee41d95f1 4 #include "mbed.h"
gabrielrivas 0:81fee41d95f1 5 #include "rtos.h"
gabrielrivas 0:81fee41d95f1 6 #include "MessageQueue.h"
gabrielrivas 0:81fee41d95f1 7
gabrielrivas 0:81fee41d95f1 8 #define MODBUS_MAX_LEN (256)
gabrielrivas 0:81fee41d95f1 9
gabrielrivas 0:81fee41d95f1 10 struct ThreadSafeArray_t {
gabrielrivas 0:81fee41d95f1 11 Mutex mutex;
gabrielrivas 0:81fee41d95f1 12 uint8_t *data;
gabrielrivas 0:81fee41d95f1 13 uint32_t length;
gabrielrivas 0:81fee41d95f1 14 };
gabrielrivas 0:81fee41d95f1 15
gabrielrivas 0:81fee41d95f1 16 class ModbusSlaveRTU
gabrielrivas 0:81fee41d95f1 17 {
gabrielrivas 0:81fee41d95f1 18 public:
gabrielrivas 0:81fee41d95f1 19 /*! Modbus response message bytes indexes. */
gabrielrivas 0:81fee41d95f1 20 enum MbResponseByteIndex_t {
gabrielrivas 0:81fee41d95f1 21 ADDRESS = 0,
gabrielrivas 0:81fee41d95f1 22 FUNCTION = 1,
gabrielrivas 0:81fee41d95f1 23 BYTE_COUNT = 2,
gabrielrivas 0:81fee41d95f1 24 DATA_START = 3
gabrielrivas 0:81fee41d95f1 25 };
gabrielrivas 0:81fee41d95f1 26
gabrielrivas 0:81fee41d95f1 27 /*! Modbus errors reported during message processing. */
gabrielrivas 0:81fee41d95f1 28 enum MbReceivedMessageErrors_t {
gabrielrivas 0:81fee41d95f1 29 ADDRESS_ERROR = 0x10,
gabrielrivas 0:81fee41d95f1 30 CRC_ERROR = 0x11,
gabrielrivas 0:81fee41d95f1 31 OFFSET_ERROR = 0x12,
gabrielrivas 0:81fee41d95f1 32 BYTE_COUNT_ERROR = 0x13
gabrielrivas 0:81fee41d95f1 33 };
gabrielrivas 0:81fee41d95f1 34
gabrielrivas 0:81fee41d95f1 35 enum MbStatusTypes_t {
gabrielrivas 0:81fee41d95f1 36 MESSAGE_LISTENING = 0x20,
gabrielrivas 0:81fee41d95f1 37 MESSAGE_PROCESSING = 0x21,
gabrielrivas 0:81fee41d95f1 38 MESSAGE_SENDING = 0x23
gabrielrivas 0:81fee41d95f1 39 };
gabrielrivas 0:81fee41d95f1 40
gabrielrivas 0:81fee41d95f1 41 enum MbSlaveRTUStates_t {
gabrielrivas 0:81fee41d95f1 42 WAIT_REQUEST_MESSAGE = 0x00,
gabrielrivas 0:81fee41d95f1 43 GET_RECEIVED_BYTES = 0x01,
gabrielrivas 0:81fee41d95f1 44 BUILD_RESPONSE_MESSAGE = 0x02,
gabrielrivas 0:81fee41d95f1 45 TRANSMIT_RESPONSE_MESSAGE = 0x03
gabrielrivas 0:81fee41d95f1 46 };
gabrielrivas 0:81fee41d95f1 47
gabrielrivas 0:81fee41d95f1 48 /*! Modbus function codes. */
gabrielrivas 0:81fee41d95f1 49 enum MbFunctionCodes_t {
gabrielrivas 0:81fee41d95f1 50 READ_COIL_STATUS = 0x01, /**< Function to read a single coil status.*/
gabrielrivas 0:81fee41d95f1 51 READ_INPUT_STATUS = 0x02, /**< Function to read input register.*/
gabrielrivas 0:81fee41d95f1 52 READ_HOLDING_REGISTERS = 0x03, /**< Function to read one or more internal holding resgisters.*/
gabrielrivas 0:81fee41d95f1 53 READ_INPUT_REGISTERS = 0x04, /**< Function to read one or more input resgisters.*/
gabrielrivas 0:81fee41d95f1 54 FORCE_SINGLE_COIL = 0x05, /**< Function to write a value into a single discrete output.*/
gabrielrivas 0:81fee41d95f1 55 PRESET_SINGLE_REGISTER = 0x06, /**< Function to write a value into a single holding register.*/
gabrielrivas 0:81fee41d95f1 56 READ_EXCEPTION_STATUS = 0x07, /**< Function to request the value of the status byte.*/
gabrielrivas 0:81fee41d95f1 57 LOOPBACK_TEST = 0x08, /**< Function to test the communications interface. Returns the same message.*/
gabrielrivas 0:81fee41d95f1 58 FORCE_MULTIPLE_COILS = 0x0F /**< Function to set more than one coil to a given value*/
gabrielrivas 0:81fee41d95f1 59 };
gabrielrivas 0:81fee41d95f1 60
gabrielrivas 0:81fee41d95f1 61 /*! Modbus frame structure elements. */
gabrielrivas 0:81fee41d95f1 62 struct MbSlaveRTUFrame_t {
gabrielrivas 0:81fee41d95f1 63 uint8_t mAddress; /**< Slave device address.*/
gabrielrivas 0:81fee41d95f1 64 MbFunctionCodes_t mFunction; /**< Requested function of type MbFunctionCodes_t.*/
gabrielrivas 0:81fee41d95f1 65 uint16_t mOffset; /**< Offset in bytes from the starting address.*/
gabrielrivas 0:81fee41d95f1 66 uint16_t mByteCount;
gabrielrivas 0:81fee41d95f1 67 uint8_t mCRCH;
gabrielrivas 0:81fee41d95f1 68 uint8_t mCRCL;
gabrielrivas 0:81fee41d95f1 69 uint16_t mSize;
gabrielrivas 0:81fee41d95f1 70 };
gabrielrivas 0:81fee41d95f1 71
gabrielrivas 0:81fee41d95f1 72 struct MemoryMap_t {
gabrielrivas 0:81fee41d95f1 73 ThreadSafeArray_t *coilRegisters;
gabrielrivas 0:81fee41d95f1 74 ThreadSafeArray_t *holdingRegisters;
gabrielrivas 0:81fee41d95f1 75 ThreadSafeArray_t *inputRegisters;
gabrielrivas 0:81fee41d95f1 76 };
gabrielrivas 0:81fee41d95f1 77
gabrielrivas 0:81fee41d95f1 78 typedef struct MbSlaveRTUControl {
gabrielrivas 0:81fee41d95f1 79 uint8_t MbAddress;
gabrielrivas 0:81fee41d95f1 80 uint8_t rxByte;
gabrielrivas 0:81fee41d95f1 81 uint32_t receiveIndex;
gabrielrivas 0:81fee41d95f1 82 MbStatusTypes_t status;
gabrielrivas 0:81fee41d95f1 83 } MbSlaveRTUControl_t;
gabrielrivas 0:81fee41d95f1 84
gabrielrivas 0:81fee41d95f1 85
gabrielrivas 0:81fee41d95f1 86 public:
gabrielrivas 0:81fee41d95f1 87 /**
gabrielrivas 0:81fee41d95f1 88 * @brief Initialization function for the Modbus RTU Slave.
gabrielrivas 0:81fee41d95f1 89 * @param id.
gabrielrivas 0:81fee41d95f1 90 * @param *coilRegisters Pointer to the memory space reserved for the coil registers.
gabrielrivas 0:81fee41d95f1 91 * @param *inputRegisters Pointer to the memory space reserved for the input registers.
gabrielrivas 0:81fee41d95f1 92 * @param *inputRegisters Pointer to the memory space reserved for the holding registers.
gabrielrivas 0:81fee41d95f1 93 * @return void
gabrielrivas 0:81fee41d95f1 94 */
gabrielrivas 0:81fee41d95f1 95 ModbusSlaveRTU( uint8_t id,
gabrielrivas 0:81fee41d95f1 96 MessageQueue<uint8_t>* txQueue,
gabrielrivas 0:81fee41d95f1 97 MessageQueue<uint8_t>* rxQueue,
gabrielrivas 0:81fee41d95f1 98 ThreadSafeArray_t *coilRegisters,
gabrielrivas 0:81fee41d95f1 99 ThreadSafeArray_t *inputRegisters,
gabrielrivas 0:81fee41d95f1 100 ThreadSafeArray_t *holdingRegisters);
gabrielrivas 0:81fee41d95f1 101
gabrielrivas 0:81fee41d95f1 102 public:
gabrielrivas 0:81fee41d95f1 103 /**
gabrielrivas 0:81fee41d95f1 104 * @brief Function to start the Modbus RTU Slave engine.
gabrielrivas 0:81fee41d95f1 105 * @return void
gabrielrivas 0:81fee41d95f1 106 */
gabrielrivas 0:81fee41d95f1 107 void trigger(void);
gabrielrivas 0:81fee41d95f1 108
gabrielrivas 0:81fee41d95f1 109 /**
gabrielrivas 0:81fee41d95f1 110 * @brief Function to start the Modbus RTU Slave engine.
gabrielrivas 0:81fee41d95f1 111 * @return MbStatusTypes_t
gabrielrivas 0:81fee41d95f1 112 */
gabrielrivas 0:81fee41d95f1 113 MbStatusTypes_t getStatus(void);
gabrielrivas 0:81fee41d95f1 114 void FSM(void);
gabrielrivas 0:81fee41d95f1 115
gabrielrivas 0:81fee41d95f1 116 private:
gabrielrivas 0:81fee41d95f1 117 uint8_t readHoldingRegistersHandler(void);
gabrielrivas 0:81fee41d95f1 118 uint8_t readCoilRegistersHandler(void);
gabrielrivas 0:81fee41d95f1 119 uint8_t buildResponse(void);
gabrielrivas 0:81fee41d95f1 120
gabrielrivas 0:81fee41d95f1 121 /**
gabrielrivas 0:81fee41d95f1 122 * @brief Function that computes the CRC of a Modbus message.
gabrielrivas 0:81fee41d95f1 123 * @param *data Pointer to the message data.
gabrielrivas 0:81fee41d95f1 124 * @param uint8_t Length of the message.
gabrielrivas 0:81fee41d95f1 125 * @return The CRC Code.
gabrielrivas 0:81fee41d95f1 126 */
gabrielrivas 0:81fee41d95f1 127 uint16_t getCRC(uint8_t * data,uint8_t len);
gabrielrivas 0:81fee41d95f1 128
gabrielrivas 0:81fee41d95f1 129 /**
gabrielrivas 0:81fee41d95f1 130 * @brief Verifies the CRC value of a message to determine it has been received correctly.
gabrielrivas 0:81fee41d95f1 131 * @param *data Pointer to the message data.
gabrielrivas 0:81fee41d95f1 132 * @return Returns 1 if the message has been well received, 0 otherwise.
gabrielrivas 0:81fee41d95f1 133 */
gabrielrivas 0:81fee41d95f1 134 uint8_t checkMessageCRC(uint8_t * data);
gabrielrivas 0:81fee41d95f1 135
gabrielrivas 0:81fee41d95f1 136 /**
gabrielrivas 0:81fee41d95f1 137 * @brief Function that appends the header and tail bytes for a response message.
gabrielrivas 0:81fee41d95f1 138 * @return void.
gabrielrivas 0:81fee41d95f1 139 */
gabrielrivas 0:81fee41d95f1 140 void appendHeaderAndTailToMessage(void);
gabrielrivas 0:81fee41d95f1 141
gabrielrivas 0:81fee41d95f1 142 /**
gabrielrivas 0:81fee41d95f1 143 * @brief Function that checks for error in the received message.
gabrielrivas 0:81fee41d95f1 144 * @param *array Safe array being processed depending on the modbus function.
gabrielrivas 0:81fee41d95f1 145 * @return uint8_t the error or success code.
gabrielrivas 0:81fee41d95f1 146 */
gabrielrivas 0:81fee41d95f1 147 uint8_t checkReceivedMessageErrors(ThreadSafeArray_t *array);
gabrielrivas 0:81fee41d95f1 148
gabrielrivas 0:81fee41d95f1 149 private:
gabrielrivas 0:81fee41d95f1 150 MbSlaveRTUStates_t m_state;
gabrielrivas 0:81fee41d95f1 151 MbSlaveRTUFrame_t m_frame;
gabrielrivas 0:81fee41d95f1 152 MbSlaveRTUControl_t m_control;
gabrielrivas 0:81fee41d95f1 153 MemoryMap_t m_memoryMap;
gabrielrivas 0:81fee41d95f1 154 MessageQueue<uint8_t>* m_bTxQueue;
gabrielrivas 0:81fee41d95f1 155 MessageQueue<uint8_t>* m_bRxQueue;
gabrielrivas 0:81fee41d95f1 156 uint8_t m_receivedMessage[MODBUS_MAX_LEN];
gabrielrivas 0:81fee41d95f1 157 uint8_t m_responseMessage[MODBUS_MAX_LEN];
gabrielrivas 0:81fee41d95f1 158 };
gabrielrivas 0:81fee41d95f1 159 #endif