2024-12-17 18:24:41 +03:00
|
|
|
|
/**
|
|
|
|
|
**************************************************************************
|
|
|
|
|
* @file modbus.h
|
|
|
|
|
* @brief Заголовочный файл модуля MODBUS.
|
|
|
|
|
* @details Данный файл необходимо подключить в rs_message.h. После подключать
|
|
|
|
|
* rs_message.h к основному проекту.
|
|
|
|
|
*
|
|
|
|
|
* @defgroup MODBUS
|
|
|
|
|
* @brief Modbus stuff
|
|
|
|
|
*
|
|
|
|
|
*************************************************************************/
|
|
|
|
|
#ifndef __MODBUS_H_
|
|
|
|
|
#define __MODBUS_H_
|
|
|
|
|
|
|
|
|
|
#include "mylibs_include.h"
|
|
|
|
|
#include "modbus_data.h"
|
|
|
|
|
//#include "settings.h" // for modbus settings
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @addtogroup MODBUS_SETTINGS
|
|
|
|
|
* @ingroup MODBUS
|
|
|
|
|
* @brief Some defines for modbus
|
|
|
|
|
@{
|
|
|
|
|
*/
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////---SETTINGS---/////////////////////////////
|
|
|
|
|
// USER SETTINGS FOR MODBUS IN interface_config.h
|
|
|
|
|
//////////////////////////---SETTINGS---/////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
/////////////////////---USER MESSAGE DEFINES---//////////////////////
|
|
|
|
|
//-------------DEFINES FOR STRUCTURE----------------
|
|
|
|
|
/* defines for structure of modbus message */
|
|
|
|
|
#define MbAddr_SIZE 1 ///< size of (MbAddr)
|
|
|
|
|
#define Func_Code_SIZE 1 ///< size of (Func_Code)
|
|
|
|
|
#define Addr_SIZE 2 ///< size of (Addr)
|
|
|
|
|
#define Qnt_SIZE 2 ///< size of (Qnt)
|
|
|
|
|
#define ByteCnt_SIZE 1 ///< size of (ByteCnt)
|
|
|
|
|
#define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE)
|
|
|
|
|
#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes
|
|
|
|
|
|
|
|
|
|
/** @brief Size of whole message */
|
|
|
|
|
#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE)
|
|
|
|
|
|
|
|
|
|
/** @brief Size of first part of message that will be received
|
|
|
|
|
first receive info part of message, than defines size of rest message*/
|
|
|
|
|
#define RX_FIRST_PART_SIZE INFO_SIZE_MAX
|
|
|
|
|
|
|
|
|
|
/** @brief Size of buffer: max size of whole message */
|
|
|
|
|
#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message
|
|
|
|
|
|
|
|
|
|
/** @brief Structure for modbus exception codes */
|
|
|
|
|
typedef enum //MB_ExceptionTypeDef
|
|
|
|
|
{
|
|
|
|
|
// reading
|
|
|
|
|
NO_ERRORS = 0x00, ///< no errors
|
|
|
|
|
ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан
|
|
|
|
|
ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен
|
|
|
|
|
ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной
|
|
|
|
|
SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие
|
|
|
|
|
// ACKNOWLEDGE = 0x05, ///< idk
|
|
|
|
|
// SLAVE_DEVICE_BUSY = 0x06, ///< idk
|
|
|
|
|
// MEMORY_PARITY_ERROR = 0x08, ///< idk
|
|
|
|
|
}MB_ExceptionTypeDef;
|
|
|
|
|
|
|
|
|
|
#define ERR_VALUES_START 0x80U ///< from this value starts error func codes
|
|
|
|
|
/** @brief Structure for modbus func codes */
|
|
|
|
|
typedef enum //MB_FunctonTypeDef
|
|
|
|
|
{
|
|
|
|
|
/* COMMANDS */
|
|
|
|
|
// reading
|
|
|
|
|
MB_R_COILS = 0x01, ///< Чтение битовых ячеек
|
|
|
|
|
MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов
|
2024-12-24 11:20:19 +03:00
|
|
|
|
#ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
|
2024-12-17 18:24:41 +03:00
|
|
|
|
MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров
|
|
|
|
|
MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения
|
|
|
|
|
#else
|
|
|
|
|
MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров
|
|
|
|
|
MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// writting
|
|
|
|
|
MB_W_COIL = 0x05, ///< Запись битовой ячейки
|
|
|
|
|
MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра
|
|
|
|
|
MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
|
|
|
|
|
MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
|
|
|
|
|
|
|
|
|
|
/* ERRORS */
|
|
|
|
|
// error reading
|
|
|
|
|
MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек
|
|
|
|
|
MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов
|
|
|
|
|
MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения
|
|
|
|
|
MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров
|
|
|
|
|
|
|
|
|
|
// error writting
|
|
|
|
|
MB_ERR_W_COIL = MB_W_COIL + ERR_VALUES_START, ///< Ошибка записи битовой ячейки
|
|
|
|
|
MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра
|
|
|
|
|
MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
|
|
|
|
|
MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров
|
|
|
|
|
}MB_FunctonTypeDef;
|
|
|
|
|
|
|
|
|
|
/** @brief Structure for modbus messsage */
|
|
|
|
|
typedef struct // RS_MsgTypeDef
|
|
|
|
|
{
|
|
|
|
|
uint8_t MbAddr; ///< Modbus Slave Address
|
|
|
|
|
MB_FunctonTypeDef Func_Code; ///< Modbus Function Code
|
|
|
|
|
uint16_t Addr; ///< Modbus Address of data
|
|
|
|
|
uint16_t Qnt; ///< Quantity of modbus data
|
|
|
|
|
uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive
|
|
|
|
|
|
|
|
|
|
uint16_t DATA[DATA_SIZE]; ///< Modbus Data
|
|
|
|
|
MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command
|
|
|
|
|
|
|
|
|
|
uint16_t MB_CRC; ///< Modbus CRC
|
|
|
|
|
}RS_MsgTypeDef;
|
|
|
|
|
//--------------------------------------------------
|
|
|
|
|
extern RS_MsgTypeDef MODBUS_MSG;
|
|
|
|
|
/////////////////////---MODBUS USER SETTINGS---//////////////////////
|
|
|
|
|
|
|
|
|
|
/** MODBUS_SETTINGS
|
|
|
|
|
* @}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
|
|
|
|
|
/**
|
|
|
|
|
* @addtogroup MODBUS_MESSAGE_DEFINES
|
|
|
|
|
* @ingroup MODBUS
|
|
|
|
|
* @brief Some defines for modbus
|
|
|
|
|
@{
|
|
|
|
|
*/
|
|
|
|
|
/** @brief Structure for coils operation */
|
|
|
|
|
typedef enum
|
|
|
|
|
{
|
|
|
|
|
SET_COIL,
|
|
|
|
|
RESET_COIL,
|
|
|
|
|
TOOGLE_COIL,
|
|
|
|
|
}MB_CoilsOpTypeDef;
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Macros to set pointer to 16-bit array
|
|
|
|
|
* @param _arr_ - массив регистров (16-бит).
|
|
|
|
|
*/
|
|
|
|
|
#define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_)))
|
|
|
|
|
/**
|
|
|
|
|
* @brief Macros to set pointer to register
|
|
|
|
|
* @param _parr_ - массив регистров.
|
|
|
|
|
* @param _addr_ - Номер регистра (его индекс) от начала массива _arr_.
|
|
|
|
|
*/
|
|
|
|
|
#define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_))
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Macros to set pointer to a certain register that contains certain coil
|
|
|
|
|
* @param _parr_ - массив коилов.
|
|
|
|
|
* @param _coil_ - Номер коила от начала массива _arr_.
|
|
|
|
|
* @note Используется вместе с @ref MB_Set_Coil_Mask
|
|
|
|
|
@verbatim Пояснение выражений
|
|
|
|
|
(_coil_/16) - get index (address shift) of register that contain certain coil
|
|
|
|
|
Visual explanation: 30th coil in coils registers array
|
|
|
|
|
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|
|
|
|
|
|register[0]----| |register[1]----|
|
|
|
|
|
|skip this------| |get this-------|
|
|
|
|
|
|shift to 14 bit|
|
|
|
|
|
@endverbatim
|
|
|
|
|
*/
|
|
|
|
|
#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16))
|
|
|
|
|
/**
|
|
|
|
|
* @brief Macros to set mask to a certain bit in coils register
|
|
|
|
|
* @param _coil_ - Номер коила от начала массива _arr_.
|
|
|
|
|
* @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr
|
|
|
|
|
@verbatim Пояснение выражений
|
|
|
|
|
(16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register
|
|
|
|
|
_coil_-(16*(_coil_/16)) - shift to certain coil in certain register
|
|
|
|
|
e.g. Coil(30) gets in register[1] (30/16 = 1) coil №14 (30 - (16*30/16) = 30 - 16 = 14)
|
|
|
|
|
|
|
|
|
|
Visual explanation: 30th coil in coils registers array
|
|
|
|
|
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|
|
|
|
|
|register[0]----| |register[1]----|
|
|
|
|
|
|skip this------| |get this-------|
|
|
|
|
|
|shift to 14 bit|
|
|
|
|
|
@endverbatim
|
|
|
|
|
*/
|
|
|
|
|
#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) ))
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Read Coil at its local address.
|
|
|
|
|
* @param _parr_ - массив коилов.
|
|
|
|
|
* @param _coil_ - Номер коила от начала массива _arr_.
|
|
|
|
|
* @return uint16_t - Возвращает запрошенный коил на 0м бите.
|
|
|
|
|
*
|
|
|
|
|
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
|
|
|
|
*/
|
|
|
|
|
#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_))
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set Coil at its local address.
|
|
|
|
|
* @param _parr_ - указатель на массив коилов.
|
|
|
|
|
* @param _coil_ - Номер коила от начала массива _arr_.
|
|
|
|
|
*
|
|
|
|
|
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
|
|
|
|
*/
|
|
|
|
|
#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_)
|
|
|
|
|
/**
|
|
|
|
|
* @brief Reset Coil at its local address.
|
|
|
|
|
* @param _parr_ - указатель на массив коилов.
|
|
|
|
|
* @param _coil_ - Номер коила от начала массива _arr_.
|
|
|
|
|
*
|
|
|
|
|
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
|
|
|
|
*/
|
|
|
|
|
#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_))
|
|
|
|
|
/**
|
|
|
|
|
* @brief Set Coil at its local address.
|
|
|
|
|
* @param _parr_ - указатель на массив коилов.
|
|
|
|
|
* @param _coil_ - Номер коила от начала массива _arr_.
|
|
|
|
|
*
|
|
|
|
|
* @details Позволяет обратиться к коилу по адресу относительно _arr_.
|
|
|
|
|
*/
|
|
|
|
|
#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_)
|
|
|
|
|
//--------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------OTHER DEFINES-------------------
|
|
|
|
|
#define RegisterType_Holding 0
|
|
|
|
|
#define RegisterType_Input 1
|
|
|
|
|
#define RegisterType_Discrete 2
|
|
|
|
|
// create hadnles and settings for uart, tim, rs with _modbus_ name
|
|
|
|
|
#define CONCAT(a,b) a##b
|
|
|
|
|
#define Create_MODBUS_Handles(_modbus_) \
|
|
|
|
|
UART_SettingsTypeDef CONCAT(_modbus_, _suart); \
|
|
|
|
|
UART_HandleTypeDef CONCAT(_modbus_, _huart); \
|
|
|
|
|
TIM_SettingsTypeDef CONCAT(_modbus_, _stim); \
|
|
|
|
|
TIM_HandleTypeDef CONCAT(_modbus_, _htim); \
|
|
|
|
|
RS_HandleTypeDef CONCAT(h, _modbus_)
|
|
|
|
|
//--------------------------------------------------
|
|
|
|
|
/** GENERAL_MODBUS_STUFF
|
|
|
|
|
* @}
|
|
|
|
|
*/
|
|
|
|
|
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
/////////////////////////---FUNCTIONS---/////////////////////////////
|
|
|
|
|
/**
|
|
|
|
|
* @addtogroup MODBUS_FUNCTIONS
|
|
|
|
|
* @ingroup MODBUS
|
|
|
|
|
* @brief Function for controling modbus communication
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
//----------------FUNCTIONS FOR USER----------------
|
|
|
|
|
/**
|
|
|
|
|
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS
|
|
|
|
|
* @ingroup MODBUS_FUNCTIONS
|
|
|
|
|
* @brief Function for user use
|
|
|
|
|
@{
|
|
|
|
|
*/
|
|
|
|
|
/* First set up of MODBUS */
|
|
|
|
|
void MODBUS_FirstInit(void);
|
|
|
|
|
/* Set or Reset Coil at its global address */
|
|
|
|
|
MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal);
|
|
|
|
|
/* Read Coil at its global address */
|
|
|
|
|
uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception);
|
|
|
|
|
|
|
|
|
|
/** MODBUS_DATA_ACCESS_FUNCTIONS
|
|
|
|
|
* @}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
//---------PROCESS MODBUS COMMAND FUNCTIONS---------
|
|
|
|
|
/**
|
|
|
|
|
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
|
|
|
|
|
* @ingroup MODBUS_FUNCTIONS
|
|
|
|
|
* @brief Function process commands
|
|
|
|
|
@{
|
|
|
|
|
*/
|
|
|
|
|
/* Check is address valid for certain array */
|
|
|
|
|
MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB);
|
|
|
|
|
/* Define Address Origin for Input/Holding Registers */
|
|
|
|
|
MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType);
|
|
|
|
|
/* Define Address Origin for coils */
|
|
|
|
|
MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag);
|
|
|
|
|
/* Proccess command Read Coils (01 - 0x01) */
|
|
|
|
|
uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg);
|
|
|
|
|
/* Proccess command Read Holding Registers (03 - 0x03) */
|
|
|
|
|
uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg);
|
|
|
|
|
/* Proccess command Read Input Registers (04 - 0x04) */
|
|
|
|
|
uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg);
|
|
|
|
|
/* Proccess command Write Single Coils (05 - 0x05) */
|
|
|
|
|
uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg);
|
|
|
|
|
/* Proccess command Write Multiple Coils (15 - 0x0F) */
|
|
|
|
|
uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg);
|
|
|
|
|
/* Proccess command Write Multiple Register (16 - 0x10) */
|
|
|
|
|
uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg);
|
|
|
|
|
|
|
|
|
|
/** MODBUS_DATA_ACCESS_FUNCTIONS
|
|
|
|
|
* @}
|
|
|
|
|
*/
|
|
|
|
|
/////////////////////////---FUNCTIONS---/////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
/////////////////////////---CALC DEFINES---//////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TRACES DEFINES
|
|
|
|
|
#ifndef Trace_MB_UART_Enter
|
|
|
|
|
#define Trace_MB_UART_Enter()
|
|
|
|
|
#endif //Trace_MB_UART_Enter
|
|
|
|
|
|
|
|
|
|
#ifndef Trace_MB_UART_Exit
|
|
|
|
|
#define Trace_MB_UART_Exit()
|
|
|
|
|
#endif //Trace_MB_UART_Exit
|
|
|
|
|
|
|
|
|
|
#ifndef Trace_MB_TIM_Enter
|
|
|
|
|
#define Trace_MB_TIM_Enter()
|
|
|
|
|
#endif //Trace_MB_TIM_Enter
|
|
|
|
|
|
|
|
|
|
#ifndef Trace_MB_TIM_Exit
|
|
|
|
|
#define Trace_MB_TIM_Exit()
|
|
|
|
|
#endif //Trace_MB_TIM_Exit
|
|
|
|
|
|
|
|
|
|
#endif //__MODBUS_H_
|