Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: Nucleo_modbus_protocol_test
ModbusSlaveRTU.h
- Committer:
- gabrielrivas
- Date:
- 2015-01-19
- Revision:
- 0:81fee41d95f1
- Child:
- 1:5efaa10b9a3f
File content as of revision 0:81fee41d95f1:
#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;
};
class ModbusSlaveRTU
{
public:
/*! Modbus response message bytes indexes. */
enum MbResponseByteIndex_t {
ADDRESS = 0,
FUNCTION = 1,
BYTE_COUNT = 2,
DATA_START = 3
};
/*! Modbus errors reported during message processing. */
enum MbReceivedMessageErrors_t {
ADDRESS_ERROR = 0x10,
CRC_ERROR = 0x11,
OFFSET_ERROR = 0x12,
BYTE_COUNT_ERROR = 0x13
};
enum MbStatusTypes_t {
MESSAGE_LISTENING = 0x20,
MESSAGE_PROCESSING = 0x21,
MESSAGE_SENDING = 0x23
};
enum MbSlaveRTUStates_t {
WAIT_REQUEST_MESSAGE = 0x00,
GET_RECEIVED_BYTES = 0x01,
BUILD_RESPONSE_MESSAGE = 0x02,
TRANSMIT_RESPONSE_MESSAGE = 0x03
};
/*! 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;
uint8_t mCRCH;
uint8_t mCRCL;
uint16_t mSize;
};
struct MemoryMap_t {
ThreadSafeArray_t *coilRegisters;
ThreadSafeArray_t *holdingRegisters;
ThreadSafeArray_t *inputRegisters;
};
typedef struct MbSlaveRTUControl {
uint8_t MbAddress;
uint8_t rxByte;
uint32_t receiveIndex;
MbStatusTypes_t status;
} MbSlaveRTUControl_t;
public:
/**
* @brief Initialization function for the Modbus RTU Slave.
* @param id.
* @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.
* @return void
*/
ModbusSlaveRTU( uint8_t id,
MessageQueue<uint8_t>* txQueue,
MessageQueue<uint8_t>* rxQueue,
ThreadSafeArray_t *coilRegisters,
ThreadSafeArray_t *inputRegisters,
ThreadSafeArray_t *holdingRegisters);
public:
/**
* @brief Function to start the Modbus RTU Slave engine.
* @return void
*/
void trigger(void);
/**
* @brief Function to start the Modbus RTU Slave engine.
* @return MbStatusTypes_t
*/
MbStatusTypes_t getStatus(void);
void FSM(void);
private:
uint8_t readHoldingRegistersHandler(void);
uint8_t readCoilRegistersHandler(void);
uint8_t buildResponse(void);
/**
* @brief 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);
/**
* @brief 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);
/**
* @brief Function that appends the header and tail bytes for a response message.
* @return void.
*/
void appendHeaderAndTailToMessage(void);
/**
* @brief Function that checks for error in the received message.
* @param *array Safe array being processed depending on the modbus function.
* @return uint8_t the error or success code.
*/
uint8_t checkReceivedMessageErrors(ThreadSafeArray_t *array);
private:
MbSlaveRTUStates_t m_state;
MbSlaveRTUFrame_t m_frame;
MbSlaveRTUControl_t m_control;
MemoryMap_t m_memoryMap;
MessageQueue<uint8_t>* m_bTxQueue;
MessageQueue<uint8_t>* m_bRxQueue;
uint8_t m_receivedMessage[MODBUS_MAX_LEN];
uint8_t m_responseMessage[MODBUS_MAX_LEN];
};
#endif