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.h
- Committer:
- gabrielrivas
- Date:
- 2015-01-21
- Revision:
- 6:0143a57e0c8e
- Parent:
- 5:7cec6597adee
File content as of revision 6:0143a57e0c8e:
/** Modbus Slave RTU * Copyright (c) 2015 Gabriel Rivas * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _MODBUS_SLAVE_RTU_H_ #define _MODBUS_SLAVE_RTU_H_ #include "mbed.h" #include "rtos.h" #include "MessageQueue.h" #define MODBUS_MAX_LEN (256) struct ThreadSafeArray_t { Mutex mutex; uint8_t *data; uint32_t length; }; /** * 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. */ class ModbusSlaveRTU { public: /*! Status of the internal modbus FSM. */ enum MbStatusTypes_t { LISTENING = 0x20, /**< Listening for incomming requests.*/ PROCESSING = 0x21, /**< Processing received request.*/ SENDING = 0x23 /**< Sending generated response.*/ }; private: /*! Modbus response message bytes indexes. */ enum MbByteIndex_t { ADDRESS = 0x00, /**< Modbus address position.*/ FUNCTION = 0x01, /**< Modbus function position.*/ BYTE_COUNT = 0x02, /**< Byte count high byte position.*/ DATA_START = 0x03, /**< Returned data start position.*/ BYTE_OFFSET = 0x02, /**< Starting register in bytes, high byte position.*/ REGISTER_COUNT = 0x04 /**< Number of registers to be read, high byte position.*/ }; /*! Modbus errors reported during message processing. */ enum MbReceivedMessageErrors_t { NO_ERROR = 0x10, /**< No error.*/ ADDRESS_ERROR = 0x11, /**< Wrong slave address.*/ CRC_ERROR = 0x12, /**< CRC from received message doesn't match with locally calculated CRC.*/ OFFSET_ERROR = 0x13, /**< Offset is out of range.*/ BYTE_COUNT_ERROR = 0x14 /**< Byte count requested is out of range.*/ }; /*! Internal modbus FSM states. */ enum MbSlaveRTUStates_t { WAIT_REQUEST_MESSAGE = 0x00, /**< Idle while bytes are being received.*/ GET_RECEIVED_BYTES = 0x01, /**< Copy received bytes into the internal buffer.*/ BUILD_RESPONSE_MESSAGE = 0x02, /**< Building response message.*/ TRANSMIT_RESPONSE_MESSAGE = 0x03 /**< Transmitting response message.*/ }; /*! Modbus function codes. */ enum MbFunctionCodes_t { READ_COIL_STATUS = 0x01, /**< Function to read a single coil status.*/ READ_INPUT_STATUS = 0x02, /**< Function to read input register.*/ READ_HOLDING_REGISTERS = 0x03, /**< Function to read one or more internal holding resgisters.*/ READ_INPUT_REGISTERS = 0x04, /**< Function to read one or more input resgisters.*/ FORCE_SINGLE_COIL = 0x05, /**< Function to write a value into a single discrete output.*/ PRESET_SINGLE_REGISTER = 0x06, /**< Function to write a value into a single holding register.*/ READ_EXCEPTION_STATUS = 0x07, /**< Function to request the value of the status byte.*/ LOOPBACK_TEST = 0x08, /**< Function to test the communications interface. Returns the same message.*/ FORCE_MULTIPLE_COILS = 0x0F /**< Function to set more than one coil to a given value*/ }; /*! Modbus frame structure elements. */ struct MbSlaveRTUFrame_t { uint8_t mAddress; /**< Slave device address.*/ MbFunctionCodes_t mFunction; /**< Requested function of type MbFunctionCodes_t.*/ uint16_t mOffset; /**< Offset in bytes from the starting address.*/ uint16_t mByteCount; /**< Number of bytes to respond.*/ uint8_t mCRCH; /**< CRC high byte.*/ uint8_t mCRCL; /**< CRC low byte.*/ uint16_t mSize; /**< Size of the frame in bytes.*/ }; /*! Memory map structure. */ struct MemoryMap_t { ThreadSafeArray_t *coilRegisters; /**< Pointer to the coil registers array.*/ ThreadSafeArray_t *holdingRegisters; /**< Pointer to the holding registers array.*/ ThreadSafeArray_t *inputRegisters; /**< Pointer to the input registers array.*/ }; public: /** * Creates a Modbus Slave RTU object. * @param id Mosbus address. * @param txQueue Message queue to write modbus responses into. * @param rxQueue Message queue to read modbus requests from. * @param *coilRegisters Pointer to the memory space reserved for the coil registers. * @param *inputRegisters Pointer to the memory space reserved for the input registers. * @param *inputRegisters Pointer to the memory space reserved for the holding registers. */ ModbusSlaveRTU( uint8_t id, MessageQueue<uint8_t>* txQueue, MessageQueue<uint8_t>* rxQueue, ThreadSafeArray_t *coilRegisters, ThreadSafeArray_t *inputRegisters, ThreadSafeArray_t *holdingRegisters); public: /** * Function to start the Modbus RTU Slave engine. */ void trigger(void); /** * Gets the status of the internal FSM. * @return Status value as defined in MbStatusTypes_t. */ MbStatusTypes_t getStatus(void); /** * Internal FSM process. */ void FSM(void); private: /** * Handler for read holding registers function request. * @return Error or success code as defined in MbReceivedMessageErrors_t. */ MbReceivedMessageErrors_t readHoldingRegistersHandler(void); /** * Handler for read coil registers function request. * @return Error or success code as defined in MbReceivedMessageErrors_t. */ MbReceivedMessageErrors_t readCoilRegistersHandler(void); /** * Builds response message. * @return Error or success code as defined in MbReceivedMessageErrors_t. */ MbReceivedMessageErrors_t buildResponse(void); /** * Function that computes the CRC of a Modbus message. * @param *data Pointer to the message data. * @param uint8_t Length of the message. * @return The CRC Code. */ uint16_t getCRC(uint8_t * data,uint8_t len); /** * Verifies the CRC value of a message to determine it has been received correctly. * @param *data Pointer to the message data. * @return Returns 1 if the message has been well received, 0 otherwise. */ uint8_t checkMessageCRC(uint8_t * data); /** * Function that appends the header and tail bytes for a response message. * @return void. */ void appendHeaderAndTailToMessage(void); /** * Function that checks for error in the received message. * @param *array Safe array being processed depending on the modbus function. * @return The error or success code as defined in MbReceivedMessageErrors_t. */ MbReceivedMessageErrors_t checkReceivedMessageErrors(ThreadSafeArray_t *array); private: /** Internal state of the modbus FSM. */ MbSlaveRTUStates_t m_state; /** Response frame. */ MbSlaveRTUFrame_t m_frame; /** Modbus address. */ uint8_t m_address; /** Modbus process status. */ MbStatusTypes_t m_status; /** Memory map for registers. */ MemoryMap_t m_memoryMap; /** Queue to write response data. */ MessageQueue<uint8_t>* m_bTxQueue; /** Queue to read incomming requests from. */ MessageQueue<uint8_t>* m_bRxQueue; /** Internal byte array to copy incomming requests. */ uint8_t m_receivedMessage[MODBUS_MAX_LEN]; /** Internal byte array to generate responses. */ uint8_t m_responseMessage[MODBUS_MAX_LEN]; }; #endif