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:
- 4:9751b0a81ded
- Parent:
- 3:71ae7fd3f2fa
- Child:
- 5:7cec6597adee
File content as of revision 4:9751b0a81ded:
/** 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 = 0, /**< Modbus address position.*/
FUNCTION = 1, /**< Modbus function position.*/
BYTE_COUNT = 2, /**< Byte count high byte position.*/
DATA_START = 3, /**< Returned data start position.*/
BYTE_OFFSET = 2, /**< Starting register in bytes, high byte position.*/
REGISTER_COUNT = 4 /**< 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.
* @return void
*/
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