Files
UKSI_TEST/AllLibs/Modbus/Inc/modbus_core.h
2025-12-16 17:57:59 +03:00

317 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
*******************************************************************************
* @file modbus_core.h
* @brief Ядро Modbus протокола - определения и структуры
*******************************************************************************
@addtogroup MODBUS_INTERNAL Modbus Internal Tools
@ingroup MODBUS
@brief Внутренние штуки библиотеки
@{
*******************************************************************************
* @details
Базовые определения для реализации Modbus RTU устройства:
- Структуры сообщений Modbus
Коды функций и исключений
Константы размеров полей
Вспомогательные макросы
@section msg Структура сообщения:
[ADDR][FUNC][DATA...][CRC]
- Адрес: 1 байт
- Функция: 1 байт
- Данные: переменной длины
- CRC: 2 байта
******************************************************************************/
#ifndef __MODBUS_CORE_H_
#define __MODBUS_CORE_H_
#include "modbus_config.h"
#include "modbus_data.h"
#include "__crc_algs.h"
/**
* @addtogroup MODBUS_MESSAGE_DEFINES Modbus Message Tools
* @ingroup MODBUS
* @brief Определения протокола модбас
* @{
*/
/////////////////////////////////////////////////////////////////////
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
//-------------DEFINES FOR STRUCTURE----------------
/* defines for structure of modbus message */
#define MbTransactionID_size 2 ///< size of (Transaction ID)
#define MbProtocolID_size 2 ///< size of (Protocol ID)
#define MbPDULength_size 2 ///< size of (PDU Length)
#define MbDeviceAddr_size 1 ///< size of (Slave Addr)
#define MbFuncCode_size 1 ///< size of (Function Code)
#define MbAddr_size 2 ///< size of (Address)
#define MbQnt_size 2 ///< size of (Quantity)
#define MbByteCnt_size 1 ///< size of (Byte Count)
#define MbData_size 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE)
#define MbCRC_size 2 ///< size of (MbCRC) in bytes
#ifndef MODBUS_PROTOCOL_TCP
/** @brief Size of whole RTU message */
#define RS_INFO_SIZE_MAX (MbDeviceAddr_size+MbFuncCode_size+MbAddr_size+MbQnt_size+MbByteCnt_size)
#else
/** @brief Size of whole TCP message */
#define RS_INFO_SIZE_MAX (MbTransactionID_size+MbProtocolID_size+MbPDULength_size+MbDeviceAddr_size+MbFuncCode_size+MbAddr_size+MbQnt_size)
#endif
/** @brief Size of first part of message that will be received
first receive info part of message, than defines size of rest message*/
#define RS_RX_FIRST_PART_SIZE RS_INFO_SIZE_MAX
/** @brief Size of buffer: max size of whole message */
#define RS_MSG_SIZE_MAX (RS_INFO_SIZE_MAX + MbData_size*2 + MbCRC_size) // max possible size of message
/**
* @brief Enum for modbus exception codes
* @details Prefix ET for Error Type
*/
typedef enum //MB_ExceptionTypeDef
{
// reading
ET_NO_ERRORS = 0x00, ///< no errors
ET_ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан
ET_ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен
ET_ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной
ET_SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие
// ET_ACKNOWLEDGE = 0x05, ///< idk
// ET_SLAVE_DEVICE_BUSY = 0x06, ///< idk
// ET_MEMORY_PARITY_ERROR = 0x08, ///< idk
}MB_ExceptionTypeDef;
#define FC_ERR_VALUES_START 0x80U ///< from this value starts error func codes
/**
* @brief Enum for modbus func codes
* @details Prefix FC for Function Code
*/
typedef enum //MB_FunctonTypeDef
{
/* COMMANDS */
// reading
FC_R_COILS = 0x01, ///< Чтение битовых ячеек
FC_R_DISC_IN = 0x02, ///< Чтение дискретных входов
#ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
FC_R_HOLD_REGS = 0x03, ///< Чтение входных регистров
FC_R_IN_REGS = 0x04, ///< Чтение регистров хранения
#else
FC_R_HOLD_REGS = 0x04, ///< Чтение входных регистров
FC_R_IN_REGS = 0x03, ///< Чтение регистров хранения
#endif
// writting
FC_W_COIL = 0x05, ///< Запись битовой ячейки
FC_W_HOLD_REG = 0x06, ///< Запись одиночного регистра
FC_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
FC_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
FC_R_DIAGNOSTICS = 0x08, ///< Чтение диагностической информации устройства
FC_R_DEVICE_ID = 0x2B, ///< Чтение информации об устройстве
/* ERRORS */
// error reading
FC_ERR_R_COILS = FC_R_COILS + FC_ERR_VALUES_START, ///< Ошибка чтения битовых ячеек
FC_ERR_R_DISC_IN = FC_R_DISC_IN + FC_ERR_VALUES_START, ///< Ошибка чтения дискретных входов
FC_ERR_R_IN_REGS = FC_R_IN_REGS + FC_ERR_VALUES_START, ///< Ошибка чтения регистров хранения
FC_ERR_R_HOLD_REGS = FC_R_HOLD_REGS + FC_ERR_VALUES_START, ///< Ошибка чтения входных регистров
// error writting
FC_ERR_W_COIL = FC_W_COIL + FC_ERR_VALUES_START, ///< Ошибка записи битовой ячейки
FC_ERR_W_HOLD_REG = FC_W_HOLD_REG + FC_ERR_VALUES_START, ///< Ошибка записи одиночного регистра
FC_ERR_W_COILS = FC_W_COILS + FC_ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
FC_ERR_W_HOLD_REGS = FC_W_HOLD_REGS + FC_ERR_VALUES_START, ///< Ошибка записи нескольких регистров
FC_ERR_R_DIAGNOSTIC = FC_R_DIAGNOSTICS + FC_ERR_VALUES_START, ///< Ошибка чтения диагностической информации устройства
FC_ERR_R_DEVICE_INFO = FC_R_DEVICE_ID + FC_ERR_VALUES_START, ///< Ошибка чтения информации об устройстве
}MB_FunctonTypeDef;
/**
* @brief Enum for MEI func codes
*/
typedef enum //MB_FunctonTypeDef
{
MEI_DEVICE_IDENTIFICATIONS = 0x0E,
}MB_MEITypeDef;
/**
* @brief Enum for Read Device Id codes
* @details Prefix RID for Read ID
*/
typedef enum //MB_FunctonTypeDef
{
RID_BASIC_IDENTIFICATIONS = 0x01, /*!< @brief Basic Device Identifications.
@details All objects of this category are mandatory:
VendorName, Product code, and revision number */
RID_REGULAR_IDENTIFICATIONS = 0x02, /*!< @brief Regular Device Identifications.
@details The device provides additional and optional
identifications and description data objects */
RID_EXTENDED_IDENTIFICATIONS = 0x03, /*!< @brief Extended Device Identifications.
@details The device provides additional and optional
identifications and description private data about the physical
device itself. All of these data are device dependent. */
RID_SPEDIFIC_IDENTIFICATIONS = 0x04, /*!< @brief Specific Device Identifications.
@details The device provides one specific identifications object. */
}MB_ReadDevId;
/** @brief Structure for device identifications message type */
typedef struct
{
MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identifications Interface
MB_ReadDevId ReadDevId;
uint8_t Conformity; ///< Identification conformity level of the device and type of supported access @ref MODBUS_DEVICE_CONFORMITY
uint8_t MoreFollows;
uint8_t NextObjId;
uint8_t NumbOfObj;
}MB_DevIdMsgTypeDef;
/** @brief Structure for modbus messsage */
typedef struct // RS_MsgTypeDef
{
#ifdef MODBUS_PROTOCOL_TCP
uint16_t TransactionID; ///< Modbus TCP: ID Transaction
uint16_t ProtocolID; ///< Modbus TCP: ID Protocol
uint16_t PDULength; ///< Modbus TCP: PDU Length
#endif
uint8_t DeviceAddr; ///< Modbus Slave Address
MB_FunctonTypeDef FuncCode; ///< Modbus Function Code
MB_DevIdMsgTypeDef DevId; ///< Read Device Identifications Header struct
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 MbData[MbData_size]; ///< Modbus Data
MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command
uint16_t MbCRC; ///< Modbus CRC
}RS_MsgTypeDef;
//--------------------------------------------------
extern RS_MsgTypeDef MODBUS_MSG;
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
/////////////////////////////////////////////////////////////////////
////////////////////---MODBUS FUNCTION DEFINES---////////////////////
/**
* @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 Макрос для установки указателя на регистр, содержащий запрашиваемый коил
* @param _parr_ - массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_.
* @note Используется вместе с @ref MB_Set_Coil_Mask
@code Пояснение выражений
- (_coil_/16) - индекс регистра, в котором содержится коил по адресу _coil_
Визуальный пример: 30 коил будет в 30/16 = 1 регистре (индексация с 0)
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|register[0]----| |register[1]----|
|skip this------| |get this-------|
|shift to 14 bit|
@endcode
*/
#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16))
/**
* @brief Макрос для установки маски, чтобы выделить запрашиваемый коил из регистра
* @param _coil_ - Номер коила от начала массива _arr_.
* @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr
@code Пояснение выражений
- (16*(_coil_/16) - сколько коилов нужно пропустить. прим. (16*30/16) - первые 16 коилов находятся вне регистра
- _coil_-(16*(_coil_/16)) - сдвинуть бит на место запрашиваемого коила в регистре
Визуальный пример: 30 коил будет регистре[1], на 14 бите:
register = 30/16 = 1
bit = 30 - (16*30/16) = 30 - 16 = 14
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|register[0]----| |register[1]----|
|skip this------| |get this-------|
|shift to 14 bit|
@endcode
*/
#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) ))
/** GENERAL_MODBUS_STUFF
* @}
*/
//------------------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
//--------------------------------------------------
#ifndef Divide_Up
/**
* @brief Calc dividing including remainder
* @param _val_ - делимое.
* @param _div_ - делитель.
* @details Если результат деления без остатка: он возвращается как есть
Если с остатком - округляется вверх
*/
//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */
#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */
#endif
#ifndef ByteSwap16
/**
* @brief Swap between Little Endian and Big Endian
* @param v - Переменная для свапа.
* @return v (new) - Свапнутая переменная.
* @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты.
*/
#define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8)))
#endif
////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////---FUNCTIONS---/////////////////////////////
/**
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
* @{
*/
/* Реализация этих функций лежит в modbus_data.c */
/* 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, uint8_t WriteFlag);
/* 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);
/** MODBUS_CMD_PROCESS_FUNCTIONS
* @}
*/
/////////////////////////---FUNCTIONS---/////////////////////////////
#include "__modbus_compat.h"
#endif //__MODBUS_CORE_H_
/** MODBUS_INTERNAL
* @}
*/