diff --git a/Inc/__modbus_compat.h b/Inc/__modbus_compat.h new file mode 100644 index 0000000..1c045c9 --- /dev/null +++ b/Inc/__modbus_compat.h @@ -0,0 +1,118 @@ +/** +******************************************************************************* +* @file __modbus_compat.h +* @brief Модуль для совместимости библиотеки MODBUS. +******************************************************************************* +* @details Файл содержит API старых функций, а также заглушки для отключенных модулей: +******************************************************************************/ +#include "modbus_core.h" + + +/** @addtogroup MODBUS_LEGACY_API Legacy API + * @ingroup MODBUS_FUNCTIONS + * @brief Старые API функций, сохранённые для обратной совместимости. + * @note Не используйте эти функции в новом коде. Они могут быть удалены в будущих версиях. + * Вместо них используйте функции из основных групп MODBUS API. + * @{ + */ + + + +/** MODBUS_LEGACY_API + * @} + */ + +/** @cond Заглушки отключенных модулей */ + +#ifndef MODBUS_ENABLE_COILS + #define MB_Coil_Write_Global(Addr, WriteVal) ET_ILLEGAL_FUNCTION + #define MB_Coil_Read_Global(Addr, Exception) 0 + #define MB_Process_Read_Coils(modbus_msg) 0 + #define MB_Process_Write_Single_Coil(modbus_msg) 0 + #define MB_Process_Write_Miltuple_Coils(modbus_msg) 0 +#endif + +#ifndef MODBUS_ENABLE_HOLDINGS + #define MB_Holding_Write_Global(Addr, WriteVal) ET_ILLEGAL_FUNCTION + #define MB_Holding_Read_Global(Addr, Exception) 0 + #define MB_Process_Read_Hold_Regs(modbus_msg) 0 + #define MB_Process_Write_Single_Reg(modbus_msg) 0 + #define MB_Process_Write_Miltuple_Regs(modbus_msg) 0 +#endif + +#ifndef MODBUS_ENABLE_INPUTS + #define MB_Input_Write_Global(Addr, WriteVal) ET_ILLEGAL_FUNCTION + #define MB_Input_Read_Global(Addr, Exception) 0 + #define MB_Process_Read_Input_Regs(modbus_msg) 0 +#endif + +#ifndef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS + #define MB_WriteSingleObjectToMessage(mbdata, ind, obj) + #define MB_WriteObjectsToMessage(modbus_msg, maxidofobj) + #define MB_Process_Read_Device_Identifications(modbus_msg) 0 + #define MB_DeviceInentificationInit() +#endif + + +#ifndef MODBUS_ENABLE_DIAGNOSTICS + #define MB_DiagnosticsInit() + #define MB_Diagnostics_WriteBit(bit_num, bit_state) 0 + #define MB_Diagnostics_GetBit(bit_num) 0 + #define MB_Process_Diagnostics(modbus_msg) 0 + #define MB_Diagnostics_BusMessageCnt() + #define MB_Diagnostics_CommunicationErrorCnt() + #define MB_Diagnostics_ExceptionErrorCnt() + #define MB_Diagnostics_CharacterOverrunCnt() + #define MB_Diagnostics_SlaveMessageCnt() + #define MB_Diagnostics_SlaveNoResponseCnt() + #define MB_Diagnostics_SlaveNAKCnt() + #define MB_Diagnostics_SlaveBusyCnt() + #define MB_GetDeviceMode() MODBUS_NORMAL_MODE +#endif + + + +#ifndef MODBUS_ENABLE_MASTER + #define MB_RespGet_RegisterValue(modbus_msg, reg_addr, reg_value) 0 + #define MB_RespGet_CoilState(modbus_msg, coil_addr, coil_state) 0 + #define MB_RespGet_NumberOfObjects(modbus_msg) 0 + #define MB_RespGet_ObjectById(modbus_msg, obj_id, obj_data, obj_length) 0 + #define MB_RespGet_ObjectByIndex(modbus_msg, index, obj_id, obj_data, obj_length) 0 + #define MB_RespGet_Diagnostic(modbus_msg, data) 0 + #define MB_REQUEST_READ_COILS(slave_addr, start_addr, quantity) {0} + #define MB_REQUEST_READ_DISCRETE_INPUTS(slave_addr, start_addr, quantity) {0} + #define MB_REQUEST_READ_HOLDING_REGS(slave_addr, start_addr, quantity) {0} + #define MB_REQUEST_READ_INPUT_REGS(slave_addr, start_addr, quantity) {0} + #define MB_REQUEST_WRITE_SINGLE_COIL(slave_addr, coil_addr, value) {0} + #define MB_REQUEST_WRITE_SINGLE_REG(slave_addr, reg_addr, value) {0} + #define MB_REQUEST_WRITE_MULTIPLE_COILS(slave_addr, start_addr, quantity, coils_data) {0} + #define MB_REQUEST_WRITE_MULTIPLE_REGS(slave_addr, start_addr, quantity, regs_data) {0} + #define MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, sub_function, data) {0} + #define MB_REQUEST_RETURN_QUERY_DATA(slave_addr) {0} + #define MB_REQUEST_RESTART_COMMUNICATIONS(slave_addr, data) {0} + #define MB_REQUEST_RETURN_DIAGNOSTIC_REGISTER(slave_addr) {0} + #define MB_REQUEST_FORCE_LISTEN_ONLY_MODE(slave_addr) {0} + #define MB_REQUEST_CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER(slave_addr) {0} + #define MB_REQUEST_RETURN_BUS_MESSAGE_COUNT(slave_addr) {0} + #define MB_REQUEST_RETURN_BUS_COMMUNICATION_ERROR_COUNT(slave_addr) {0} + #define MB_REQUEST_RETURN_SLAVE_EXCEPTION_ERROR_COUNT(slave_addr) {0} + #define MB_REQUEST_RETURN_SLAVE_MESSAGE_COUNT(slave_addr) {0} + #define MB_REQUEST_RETURN_SLAVE_NO_RESPONSE_COUNT(slave_addr) {0} + #define MB_REQUEST_RETURN_SLAVE_NAK_COUNT(slave_addr) {0} + #define MB_REQUEST_RETURN_SLAVE_BUSY_COUNT(slave_addr) {0} + #define MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(slave_addr) {0} + #define MB_REQUEST_READ_DEVICE_ID_BASIC(slave_addr) {0} + #define MB_REQUEST_READ_DEVICE_ID_REGULAR(slave_addr) {0} + #define MB_REQUEST_READ_DEVICE_ID_EXTENDED(slave_addr) {0} + #define MB_REQUEST_READ_DEVICE_ID_SPECIFIC(slave_addr, object_id) {0} + #define MB_Master_Collect_Message(hmodbus, modbus_msg, modbus_uart_buff) RS_ERR + #define MB_Master_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff) RS_ERR +#endif + +#ifndef MODBUS_ENABLE_SLAVE + #define MB_Slave_Response(hmodbus, modbus_msg) RS_ERR + #define MB_Slave_Collect_Message(hmodbus, modbus_msg, modbus_uart_buff) RS_ERR + #define MB_Slave_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff) RS_ERR +#endif + +/** @endcond */ diff --git a/Inc/modbus.h b/Inc/modbus.h index 38b7538..121630c 100644 --- a/Inc/modbus.h +++ b/Inc/modbus.h @@ -1,20 +1,22 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus.h * @brief Главный заголовочный файл Modbus библиотеки -****************************************************************************** +******************************************************************************* @addtogroup MODBUS Modbus tools -****************************************************************************** +@brief Библиотека реализующая протокол Modbus +******************************************************************************* @addtogroup MODBUS_FUNCTIONS Main API for Modbus Library @ingroup MODBUS +@brief Публичные функции библиотеки @{ -****************************************************************************** +******************************************************************************* * @details Объединяющий файл для подключения всей функциональности Modbus. Подключает все необходимые модули: -@section init Инструкция по подключению +@section Start Инструкция по подключению Для корректной работы надо: - Подключить обработчики RS_UART_Handler(), RS_TIM_Handler(), в соответствубщие низкоуровневые прерывания UART_IRQHandler, TIM_IRQHandler вместо HAL'овского обработчика @@ -23,43 +25,43 @@ - Инициализировать хендл мобдас. По умолчанию глобально создается hmodbus1 - После для запуска Modbus: - @verbatim + @code //----------------Слейв модбас----------------// #include "modbus.h" MODBUS_FirstInit(&hmodbus1, &huart1, &htim3); - MODBUS_Config(&hmodbus1, 1, 1000, MODBUS_MODE_SLAVE); + MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); MODBUS_SlaveStart(&hmodbus1, NULL); - @endverbatim - @verbatim + @endcode + @code //----------------Мастер модбас----------------// #include "modbus.h" MODBUS_FirstInit(&hmodbus1, &huart1, &htim3); - MODBUS_Config(&hmodbus1, 0, 1000, MODBUS_MODE_MASTER); + MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER); // Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук RS_MsgTypeDef msg = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10); MODBUS_MasterRequest(&hmodbus1, &msg, &callback_func); - void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) - { - // MB_RespGet_... Чтобы достать нужные данные из ответа - if(hmodbus->RS_STATUS == RS_OK) - { - for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) - { - uint16_t value; - if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) - { - read_hold[i] = value; - } - } - } - } - @endverbatim + void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) + { + // MB_RespGet_... Чтобы достать нужные данные из ответа + if(hmodbus->RS_STATUS == RS_OK) + { + for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) + { + uint16_t value; + if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) + { + read_hold[i] = value; + } + } + } + } + @endcode -@section Подключаемые модули: +@section modules Подключаемые модули: - rs_message.h - работа с uart - modbus_core.h - базовые определения - modbus_coils.h - работа с дискретными выходами @@ -69,7 +71,7 @@ - modbus_diag.h - диагностика modbus -@section Структура данных Modbus +@section data Структура данных Modbus #### Holding/Input Registers: - Регистры — 16-битные слова. Доступ к регистрам осуществляется через указатель. @@ -84,21 +86,35 @@ #define __MODBUS_H_ #include "rs_message.h" +#ifdef MODBUS_ENABLE_MASTER #include "modbus_master.h" +#endif +#ifdef MODBUS_ENABLE_SLAVE #include "modbus_slave.h" +#endif +#ifdef MODBUS_ENABLE_COILS #include "modbus_coils.h" +#endif +#ifdef MODBUS_ENABLE_HOLDINGS #include "modbus_holdregs.h" +#endif +#ifdef MODBUS_ENABLE_INPUTS #include "modbus_inputregs.h" +#endif +#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS #include "modbus_devid.h" +#endif +#ifdef MODBUS_ENABLE_DIAGNOSTICS #include "modbus_diag.h" +#endif #ifdef MODBUS_ENABLE_MASTER -#define MODBUS_MODE_MASTER 1 +#define MODBUS_MODE_MASTER 1 ///< Псевдо-enum: Режим мастер #endif #ifdef MODBUS_ENABLE_SLAVE -#define MODBUS_MODE_SLAVE 0 +#define MODBUS_MODE_SLAVE 0 ///< Псевдо-enum: Режим слейв #endif ///////////////////////////////////////////////////////////////////// @@ -124,4 +140,5 @@ HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef /** MODBUS_FUNCTIONS * @} - */ \ No newline at end of file + */ + \ No newline at end of file diff --git a/Inc/modbus_coils.h b/Inc/modbus_coils.h index c03cf8b..f01cafd 100644 --- a/Inc/modbus_coils.h +++ b/Inc/modbus_coils.h @@ -1,23 +1,27 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_coils.h * @brief Работа с коилами Modbus -****************************************************************************** +******************************************************************************* @addtogroup MODBUS_COILS Coils Tools @ingroup MODBUS_INTERNAL -****************************************************************************** +@brief Функции для работы с коилами +******************************************************************************* * @details +Модуль для доступа к coils внутри программы: +- Функции для доступа к coils по глобальным адресам +- Макросы для доступа к coils по локальным адресам + Модуль предоставляет функции и макросы для работы с битовыми данными: - Чтение coils (0x01) Упаковка битов в байты - Запись одиночного coil (0x05) Установка/сброс бита - Запись множественных coils (0x0F) - распаковка байтов в биты -- Макросы для локального доступа к coils -@section Организация битовых данных: +@section cbits Организация битовых данных: Coils упакованы в 16-битные слова для эффективного использования памяти. Биты нумеруются от младшего к старшему внутри каждого слова. -@section Адресация: +@section caddr Адресация: - Глобальная - абсолютный адрес в пространстве Modbus - Локальная - относительный адрес внутри массива coils - Макросы автоматически вычисляют смещения и маски @@ -44,7 +48,7 @@ Coils упакованы в 16-битные слова для эффективн /** * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS API for Data Access * @ingroup MODBUS_FUNCTIONS - * @brief Функции для доступа к данным модбас + * @brief API для доступа к данным модбас внутри программы * @{ */ @@ -101,7 +105,7 @@ uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); /** * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS - @{ + * @{ */ /* Обработать функцию Read Coils (01 - 0x01) */ uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg); @@ -115,4 +119,4 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg); */ /////////////////////////---FUNCTIONS---///////////////////////////// -#endif //__MODBUS_COILS_H_ \ No newline at end of file +#endif //__MODBUS_COILS_H_ diff --git a/Inc/modbus_core.h b/Inc/modbus_core.h index cf11c46..b37df86 100644 --- a/Inc/modbus_core.h +++ b/Inc/modbus_core.h @@ -1,12 +1,13 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_core.h * @brief Ядро Modbus протокола - определения и структуры -****************************************************************************** +******************************************************************************* @addtogroup MODBUS_INTERNAL Modbus Internal Tools @ingroup MODBUS +@brief Внутренние штуки библиотеки @{ -****************************************************************************** +******************************************************************************* * @details Базовые определения для реализации Modbus RTU устройства: - Структуры сообщений Modbus @@ -14,7 +15,7 @@ Константы размеров полей Вспомогательные макросы -@section Структура сообщения: +@section msg Структура сообщения: [ADDR][FUNC][DATA...][CRC] - Адрес: 1 байт - Функция: 1 байт @@ -28,28 +29,37 @@ #include "modbus_config.h" #include "modbus_data.h" #include "__crc_algs.h" +#include "__modbus_compat.h" /** * @addtogroup MODBUS_MESSAGE_DEFINES Modbus Message Tools * @ingroup MODBUS * @brief Определения протокола модбас - @{ + * @{ */ ///////////////////////////////////////////////////////////////////// ////////////////////---MODBUS 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 TransactionID_size 2 ///< size of (Transaction ID) +#define ProtocolID_size 2 ///< size of (Protocol ID) +#define PDULength_size 2 ///< size of (PDU Length) +#define MbAddr_SIZE 1 ///< size of (Slave Addr) +#define Func_Code_SIZE 1 ///< size of (Function Code) +#define Addr_SIZE 2 ///< size of (Address) +#define Qnt_SIZE 2 ///< size of (Quantity) +#define ByteCnt_SIZE 1 ///< size of (Byte Count) #define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE) -#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes +#define CRC_SIZE 2 ///< size of (MbCRC) in bytes -/** @brief Size of whole message */ +#ifndef MODBUS_PROTOCOL_TCP +/** @brief Size of whole RTU message */ #define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE) +#else +/** @brief Size of whole TCP message */ +#define INFO_SIZE_MAX (TransactionID_size+ProtocolID_size+PDULength_size+MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_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*/ @@ -58,100 +68,104 @@ first receive info part of message, than defines size of rest message*/ /** @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 */ +/** + * @brief Enum for modbus exception codes + * @details Prefix ET for Error Type + */ 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 + 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 ERR_VALUES_START 0x80U ///< from this value starts error func codes -/** @brief Structure for modbus func codes */ +#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 - MB_R_COILS = 0x01, ///< Чтение битовых ячеек - MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов + FC_R_COILS = 0x01, ///< Чтение битовых ячеек + FC_R_DISC_IN = 0x02, ///< Чтение дискретных входов #ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS - MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров - MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения + FC_R_HOLD_REGS = 0x03, ///< Чтение входных регистров + FC_R_IN_REGS = 0x04, ///< Чтение регистров хранения #else - MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров - MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения + FC_R_HOLD_REGS = 0x04, ///< Чтение входных регистров + FC_R_IN_REGS = 0x03, ///< Чтение регистров хранения #endif // writting - MB_W_COIL = 0x05, ///< Запись битовой ячейки - MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра - MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек - MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров + FC_W_COIL = 0x05, ///< Запись битовой ячейки + FC_W_HOLD_REG = 0x06, ///< Запись одиночного регистра + FC_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек + FC_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров - MB_R_DIAGNOSTIC = 0x08, ///< Чтение диагностической информации устройства - MB_R_DEVICE_INFO = 0x2B, ///< Чтение информации об устройстве + FC_R_DIAGNOSTICS = 0x08, ///< Чтение диагностической информации устройства + FC_R_DEVICE_ID = 0x2B, ///< Чтение информации об устройстве /* 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, ///< Ошибка чтения входных регистров + 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 - 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, ///< Ошибка записи нескольких регистров + 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, ///< Ошибка записи нескольких регистров - MB_ERR_R_DIAGNOSTIC = MB_R_DIAGNOSTIC + ERR_VALUES_START, ///< Ошибка чтения диагностической информации устройства - MB_ERR_R_DEVICE_INFO = MB_R_DEVICE_INFO + 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 Structure for MEI func codes */ +/** @brief Enum for MEI func codes */ typedef enum //MB_FunctonTypeDef { MEI_DEVICE_IDENTIFICATIONS = 0x0E, }MB_MEITypeDef; -/** @brief Structure for comformity */ +/** + * @brief Enum for Read Device Id codes + * @details Prefix RID for Read ID + */ typedef enum //MB_FunctonTypeDef { - MB_BASIC_IDENTIFICATIONS = 0x01, /*!< @brief Basic Device Identifications. + RID_BASIC_IDENTIFICATIONS = 0x01, /*!< @brief Basic Device Identifications. @details All objects of this category are mandatory: - VendorName,Product code, and revision number */ + VendorName, Product code, and revision number */ - MB_REGULAR_IDENTIFICATIONS = 0x02, /*!< @brief Regular Device Identifications. + RID_REGULAR_IDENTIFICATIONS = 0x02, /*!< @brief Regular Device Identifications. @details The device provides additional and optional identifications and description data objects */ - MB_EXTENDED_IDENTIFICATIONS = 0x03, /*!< @brief Extended Device Identifications. + 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. */ - MB_SPEDIFIC_IDENTIFICATIONS = 0x04, /*!< @brief Specific Device Identifications. + RID_SPEDIFIC_IDENTIFICATIONS = 0x04, /*!< @brief Specific Device Identifications. @details The device provides one specific identifications object. */ - /* ERRORS */ - MB_ERR_BASIC_IDENTIFICATIONS = MB_BASIC_IDENTIFICATIONS + ERR_VALUES_START, - MB_ERR_REGULAR_IDENTIFICATIONS = MB_REGULAR_IDENTIFICATIONS + ERR_VALUES_START, - MB_ERR_EXTENDED_IDENTIFICATIONS = MB_REGULAR_IDENTIFICATIONS + ERR_VALUES_START, - MB_ERR_SPEDIFIC_IDENTIFICATIONS = MB_REGULAR_IDENTIFICATIONS + ERR_VALUES_START, -}MB_ConformityTypeDef; +}MB_ReadDevId; -/** @brief Structure for decive identifications message type */ +/** @brief Structure for device identifications message type */ typedef struct { MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identifications Interface - MB_ConformityTypeDef ReadDevId; - MB_ConformityTypeDef Conformity; + 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; @@ -161,17 +175,23 @@ typedef struct /** @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 MbAddr; ///< Modbus Slave Address - MB_FunctonTypeDef Func_Code; ///< Modbus Function Code + 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 DATA[DATA_SIZE]; ///< Modbus Data + uint16_t MbData[DATA_SIZE]; ///< Modbus Data MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command - uint16_t MB_CRC; ///< Modbus CRC + uint16_t MbCRC; ///< Modbus CRC }RS_MsgTypeDef; //-------------------------------------------------- extern RS_MsgTypeDef MODBUS_MSG; @@ -199,7 +219,7 @@ extern RS_MsgTypeDef MODBUS_MSG; * @param _parr_ - массив коилов. * @param _coil_ - Номер коила от начала массива _arr_. * @note Используется вместе с @ref MB_Set_Coil_Mask - @verbatim Пояснение выражений + @code Пояснение выражений - (_coil_/16) - индекс регистра, в котором содержится коил по адресу _coil_ Визуальный пример: 30 коил будет в 30/16 = 1 регистре (индексация с 0) @@ -207,14 +227,14 @@ extern RS_MsgTypeDef MODBUS_MSG; |register[0]----| |register[1]----| |skip this------| |get this-------| |shift to 14 bit| - @endverbatim + @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 - @verbatim Пояснение выражений + @code Пояснение выражений - (16*(_coil_/16) - сколько коилов нужно пропустить. прим. (16*30/16) - первые 16 коилов находятся вне регистра - _coil_-(16*(_coil_/16)) - сдвинуть бит на место запрашиваемого коила в регистре @@ -226,7 +246,7 @@ extern RS_MsgTypeDef MODBUS_MSG; |register[0]----| |register[1]----| |skip this------| |get this-------| |shift to 14 bit| - @endverbatim + @endcode */ #define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) @@ -271,7 +291,7 @@ extern RS_MsgTypeDef MODBUS_MSG; /** * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS - @{ + * @{ */ /* Реализация этих функций лежит в modbus_data.c */ @@ -285,8 +305,11 @@ MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint /** MODBUS_CMD_PROCESS_FUNCTIONS * @} */ + + + /////////////////////////---FUNCTIONS---///////////////////////////// #endif //__MODBUS_CORE_H_ /** MODBUS_INTERNAL * @} - */ \ No newline at end of file + */ diff --git a/Inc/modbus_devid.h b/Inc/modbus_devid.h index 1d37fbb..b232e3d 100644 --- a/Inc/modbus_devid.h +++ b/Inc/modbus_devid.h @@ -1,18 +1,19 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_devid.h * @brief Идентификаторы устройства Modbus -****************************************************************************** +******************************************************************************* @addtogroup MODBUS_DEVID Device Identifications Tools @ingroup MODBUS_INTERNAL -****************************************************************************** +@brief Функции для работы с идентификаторами устройства +******************************************************************************* * @details Модуль реализации функции Read Device Identifications (0x2B): - Базовая идентификация (Vendor, Product, Revision) - Расширенная идентификация (URL, Model, User fields) - Поддержка потоковой передачи больших объектов -@section Объекты идентификации: +@section devobj Объекты идентификации: - VendorName, ProductCode, Revision - обязательные - VendorUrl, ProductName, ModelName - опциональные - User objects - пользовательские поля @@ -31,6 +32,12 @@ * @{ */ +#if MODBUS_NUMB_OF_USEROBJECTS > 0 +#define MODBUS_DEVICE_CONFORMITY 0x83 +#else +#define MODBUS_DEVICE_CONFORMITY 0x82 +#endif + /** @brief Структура для объекта (идентификатора устройства модбас) */ typedef struct { @@ -102,7 +109,7 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj); /** * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS - @{ + * @{ */ /* Обработать функцию Read Device Identifications (43/14 - 0x2B/0E) */ @@ -113,3 +120,4 @@ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg); /////////////////////////---FUNCTIONS---///////////////////////////// #endif //__MODBUS_DEVID_H_ + diff --git a/Inc/modbus_diag.h b/Inc/modbus_diag.h index 90d256d..94b0349 100644 --- a/Inc/modbus_diag.h +++ b/Inc/modbus_diag.h @@ -1,18 +1,19 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_diag.h * @brief Диагностика устройства Modbus -****************************************************************************** +******************************************************************************* @addtogroup MODBUS_DIAG Diagnostics Tools @ingroup MODBUS_INTERNAL -****************************************************************************** +@brief Функции для работы с диагностикой +******************************************************************************* * @details Модуль реализации Diagnostics (Serial Line only) (0x08): - Полная поддержка всех подфункций диагностики - Возможность выставить/сбросить любой бит в диагностическом регистре - Сбор статистики работы устройства - Управление режимами работы -****************************************** ************************************/ +******************************************************************************/ #ifndef __MODBUS_DIAG_H_ #define __MODBUS_DIAG_H_ #include "modbus_core.h" @@ -100,7 +101,7 @@ void MB_Diagnostics_SlaveBusyCnt(void); /** * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS - @{ + * @{ */ /* Обработка команды диагностики (0x08) */ @@ -119,4 +120,5 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg); /** MODBUS_DIAG * @} - */ \ No newline at end of file + */ + \ No newline at end of file diff --git a/Inc/modbus_holdregs.h b/Inc/modbus_holdregs.h index 7ab4e67..98f6bef 100644 --- a/Inc/modbus_holdregs.h +++ b/Inc/modbus_holdregs.h @@ -1,18 +1,22 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_holdregs.h * @brief Работа с регистрами хранения Modbus -****************************************************************************** +******************************************************************************* @addtogroup MODBUS_INS Input Register Tools @ingroup MODBUS_INTERNAL -****************************************************************************** +@brief Функции для работы с входными регистрами +******************************************************************************* * @details +Модуль для доступа к регистрам внутри программы: +- Функции для доступа к регистрам хранения по глобальным адресам + Модуль обработки команд для регистров хранения (Holding Registers): - Чтение множества регистров (0x03) - Запись одиночного регистра (0x06) - Запись множества регистров (0x10) -@section Регистры хранения: +@section hold Регистры хранения: - Read/Write доступ - 16-битные значения (uint16_t) ******************************************************************************/ @@ -41,7 +45,7 @@ uint16_t MB_Holding_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); /** * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS - @{ + * @{ */ /* Обработать функцию Read Holding Registers (03 - 0x03) */ uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg); diff --git a/Inc/modbus_inputregs.h b/Inc/modbus_inputregs.h index 7912553..ff3f9d1 100644 --- a/Inc/modbus_inputregs.h +++ b/Inc/modbus_inputregs.h @@ -1,16 +1,20 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_inputregs.h * @brief Работа с входными регистрами Modbus -****************************************************************************** +******************************************************************************* @addtogroup MODBUS_HOLD Holding Registers Tools @ingroup MODBUS_INTERNAL -****************************************************************************** +@brief Функции для работы с регистрами хранения +******************************************************************************* * @details +Модуль для доступа к регистрам внутри программы: +- Функции для доступа к входным регистрам по глобальным адресам + Модуль обработки команд для входных регистров (Input Registers): - Чтение множества регистров (0x04) -@section Входные регистры: +@section in Входные регистры: - Read-Only доступ - 16-битные значения ******************************************************************************/ @@ -40,7 +44,7 @@ uint16_t MB_Input_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS Internal Process Functions * @ingroup MODBUS_INTERNAL * @brief Функции обработки запросов модбас - @{ + * @{ */ /* Обработать функцию Read Input Registers (04 - 0x04) */ uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg); diff --git a/Inc/modbus_master.h b/Inc/modbus_master.h index 60df97f..84cf4ea 100644 --- a/Inc/modbus_master.h +++ b/Inc/modbus_master.h @@ -1,13 +1,14 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_master.h * @brief Главный заголовочный файл Modbus библиотеки -****************************************************************************** +******************************************************************************* @addtogroup MODBUS_MASTER Modbus master funtions @ingroup MODBUS_CMD_PROCESS_FUNCTIONS -****************************************************************************** +@brief Функции для работы в режиме Master +******************************************************************************* * @details -Модуль реализации обработки UART сообщение в режиме мастер +Модуль реализации Modbus в режиме мастер ******************************************************************************/ #ifndef __MODBUS_MASTER_H_ #define __MODBUS_MASTER_H_ @@ -17,7 +18,7 @@ /** * @addtogroup MODBUS_REQUEST_MSG API for Master Requests * @ingroup MODBUS_FUNCTIONS - * @brief Макросы для создания запросов в режиме мастер + * @brief API для формирования фрейма-запроса в режиме мастер * @details Примеры использования: * @code * // Чтение 10 holding registers начиная с адреса 0 @@ -80,24 +81,20 @@ RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t obj * @code * // Пример: Запросили 10 регистров с адреса 100, хотим получить значение регистра 105 * uint16_t reg_value; - * if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, ®_value)) + * if(MB_RespGet_RegisterValue(modbus_msg, 105, ®_value)) * { * printf("Register 105 value: %d\n", reg_value); * } * * // Пример: Получить все запрошенные регистры - * for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) - * { - * uint16_t value; - * if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) - * { - * printf("Register %d: %d\n", addr, value); - * } - * } + * uint16_t reg_value[125]; + * MB_RespGet_RegisterAll(modbus_msg) * @endcode * @{ */ - +/* Получить значение ВСЕХ регистров в ответе */ +int MB_RespGet_RegisterAll(RS_MsgTypeDef *modbus_msg, uint16_t *reg_arr); +/* Получить значение регистра в ответе по его адресу */ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value); @@ -115,7 +112,7 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1 * @code * // Пример: Запросили 10 coils с адреса 20, хотим узнать состояние coil 25 * int coil_state; - * if(MB_RespGet_CoilState(&MODBUS_MSG, 25, &coil_state)) + * if(MB_RespGet_CoilState(modbus_msg, 25, &coil_state)) * { * printf("Coil 25 state: %s\n", coil_state ? "ON" : "OFF"); * } @@ -124,7 +121,7 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1 * for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) * { * int state; - * if(MB_RespGet_CoilState(&MODBUS_MSG, addr, &state)) + * if(MB_RespGet_CoilState(modbus_msg, addr, &state)) * { * printf("Coil %d: %s\n", addr, state ? "ON" : "OFF"); * } @@ -132,7 +129,9 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1 * @endcode * @{ */ - +/* Получить состояние ВСЕХ coil в ответе */ +int MB_RespGet_CoilAll(RS_MsgTypeDef *modbus_msg, int *coil_arr); +/* Получить состояние coil в ответе по его адресу */ int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state); /** MODBUS_REQ_COILS_API @@ -150,7 +149,7 @@ int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coi * // Пример 1: Получить VendorName (ID = 0x00) * uint8_t length; * char vendor_name[64]; - * if(MB_RespGet_ObjectById(&MODBUS_MSG, 0x00, vendor_name, &length)) + * if(MB_RespGet_ObjectById(modbus_msg, 0x00, vendor_name, &length)) * { * // получено * } @@ -159,12 +158,12 @@ int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coi * uint8_t obj_id, obj_length; * char obj_data[256]; * - * int obj_count = MB_RespGet_NumberOfObjects(&MODBUS_MSG); + * int obj_count = MB_RespGet_NumberOfObjects(modbus_msg); * printf("Total objects: %d\n", obj_count); * * for(int i = 0; i < obj_count; i++) * { - * if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, i, &obj_id, obj_data, &obj_length)) + * if(MB_RespGet_ObjectByIndex(modbus_msg, i, &obj_id, obj_data, &obj_length)) * { * // получено * } @@ -196,7 +195,7 @@ int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_ * @code * // Получить данные диагностики (значение счетчика) * uint16_t counter_value; - * if(MB_RespGet_Diagnostic(&MODBUS_MSG, &counter_value)) + * if(MB_RespGet_Diagnostic(modbus_msg, &counter_value)) * { * printf("Counter value: %d\n", counter_value); * } @@ -204,6 +203,7 @@ int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_ * @{ */ +/* Получить */ int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data); /** MODBUS_REQ_DIAG_API diff --git a/Inc/modbus_slave.h b/Inc/modbus_slave.h index 9db55a4..9320c6b 100644 --- a/Inc/modbus_slave.h +++ b/Inc/modbus_slave.h @@ -1,13 +1,14 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_slave.h * @brief Главный заголовочный файл Modbus библиотеки -****************************************************************************** +******************************************************************************* @addtogroup MODBUS_SLAVE Modbus slave funtions @ingroup MODBUS_CMD_PROCESS_FUNCTIONS -****************************************************************************** +@brief Функции для работы в режиме Slave +******************************************************************************* * @details -Модуль реализации обработки UART сообщение в режиме слейв +Модуль реализации Modbus в режиме слейв ******************************************************************************/ #ifndef __MODBUS_SLAVE_H_ #define __MODBUS_SLAVE_H_ diff --git a/Inc/rs_message.h b/Inc/rs_message.h index ee8dd34..8723a98 100644 --- a/Inc/rs_message.h +++ b/Inc/rs_message.h @@ -1,29 +1,29 @@ /** -****************************************************************************** +******************************************************************************* * @file rs_message.h * @brief Библиотека обмена сообщениями по RS-интерфейсу -****************************************************************************** +******************************************************************************* @defgroup RS_TOOLS RS Tools @brief Всякое для работы по UART/RS @{ -****************************************************************************** +******************************************************************************* * @details Универсальная библиотека для работы с последовательными протоколами (Modbus, Custom) через UART в режиме прерываний с поддержкой таймаутов. -@section Основные возможности: +@section posibility Основные возможности: - Прием/передача в прерываниях - Обработка IDLE линии для определения конца фрейма - Таймауты приема через TIM - Гибкая настройка размера сообщений -@section Использование: +@section usage Использование: 1. Определить структуру сообщения и размеры буфера 2. Реализовать weak-функции обработки сообщений 3. Добавить вызовы RS_UART_Handler/RS_TIM_Handler в прерывания 4. Инициализировать через RS_Init() и запустить прием RS_Receive_IT() -@section Особенности: +@section features Особенности: - Буфер: RS_Buffer[MSG_SIZE_MAX] Общий для приема/передачи - Состояния: отслеживается через флаги в RS_HandleTypeDef - Таймауты: контролируют максимальное время ожидания фрейма @@ -76,42 +76,6 @@ #define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1) -#ifndef printf_rs_err -#define printf_rs_err(...) -#endif - -#ifndef printf_rs -#define printf_rs(...) -#endif - -#ifndef __MYLIBS_CONFIG_H_ -// дефайны из mylibs include -static int dummy; -#define TrackerTypeDef(num_user_vars) void * -#define num_of_usercnts(_user_) 0 -#define assert_tracecnt(_cntstruct_, _uservarnumb_) 0 -#define if_assert_usertracker(_cntstruct_, _uservarnumb_) if(0) -#define tern_assert_usertracker(_cntstruct_, _uservarnumb_) 0 -#define TrackerGet_Ok(_cntstruct_) dummy -#define TrackerGet_Err(_cntstruct_) dummy -#define TrackerGet_Warn(_cntstruct_) dummy -#define TrackerGet_User(_cntstruct_, _uservarnumb_) dummy -#define TrackerCnt_Ok(_cntstruct_) -#define TrackerCnt_Err(_cntstruct_) -#define TrackerCnt_Warn(_cntstruct_) -#define TrackerCnt_User(_cntstruct_, _uservarnumb_) -#define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_) -#define TrackerClear_All(_cntstruct_) -#define TrackerClear_Ok(_cntstruct_) -#define TrackerClear_Err(_cntstruct_) -#define TrackerClear_Warn(_cntstruct_) -#define TrackerClear_User(_cntstruct_) -#define TrackerClear_UserAll(_cntstruct_) -#else -#include "mylibs_include.h" -#endif - - #ifndef RS_USER_VARS_NUMB #define RS_USER_VARS_NUMB 0 #endif @@ -122,6 +86,65 @@ static int dummy; /** @endcond */ +/** + * @addtogroup RS_DEBUG Tools for debug RS/UART/TIM + * @ingroup RS_TOOLS + * @brief Дефайны для отладки периферии + * @{ + */ + +#ifndef RS_USER_VARS_NUMB +#define RS_USER_VARS_NUMB 0 ///< Количество переменных в @ref TrackerTypeDef +#endif + +/** + * @brief Тип структуры для счетчиков-переменных + * @param num_user_vars Есть возмоность добавления num_user_vars количества пользовательскиъх переменных + */ +#define TrackerTypeDef(num_user_vars) void * +/** @brief Инкрементировать переменную - успешных событий */ +#define TrackerCnt_Ok(_cntstruct_) +/** @brief Инкрементировать переменную - ошибок */ +#define TrackerCnt_Err(_cntstruct_) +/** @brief Инкрементировать переменную - предупреждений */ +#define TrackerCnt_Warn(_cntstruct_) + + + +#ifndef printf_rs +/** @brief Printf обычных событий RS/UART/TIM */ +#define printf_rs(...) +#endif + +#ifndef printf_rs_err +/** @brief Printf ошибок RS/UART/TIM */ +#define printf_rs_err(...) +#endif + + +#ifndef RS_TIM_Handler_ENTER +/** @brief Действия при заходе в прерывания таймера */ +#define RS_TIM_Handler_ENTER() +#endif +#ifndef RS_TIM_Handler_EXIT +/** @brief Действия при выходе из прерывания таймера */ +#define RS_TIM_Handler_EXIT() +#endif + +#ifndef RS_UART_Handler_ENTER +/** @brief Действия при заходе в прерывания UART */ +#define RS_UART_Handler_ENTER() +#endif +#ifndef RS_UART_Handler_EXIT +/** @brief Действия при выходе из прерывания UART */ +#define RS_UART_Handler_EXIT() +#endif +/** RS_TOOLS + * @} + */ + + + // направление передачи rs485 #ifndef RS_EnableReceive #define RS_EnableReceive() ///< Функция изменения направления передачи на ПРИЕМ для RS-485 diff --git a/README.md b/README.md index 7a4e12b..b20d31b 100644 --- a/README.md +++ b/README.md @@ -6,40 +6,40 @@ *Note: Файлы начинающиеся с `__` и которых **нет** в этом дереве являются **внутренними/непротестированными/недокументированными*** ``` -Modbus/ Иерархия модулей: -│ inc/ modbus -│ ├── modbus.h # Главный заголовочный файл modbus_slave -│ ├── modbus_core.h # Базовые определения и структуры modbus_master -│ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils -│ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs -│ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs -│ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid -│ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag -├── src/ └── rs_message -│ ├── modbus.c # Основная логика Modbus │ -│ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро) -│ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config -│ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data -│ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs -│ ├── modbus_inputregs.c # Реализация входных регистров -│ ├── modbus_devid.c # Реализация идентификации устройства -│ ├── modbus_data.c # Функции доступа к данным -│ └── rs_message.c # Реализация драйвера RS -├── __modbus_config.h # Конфигурация Modbus (надо заменить) -├── __modbus_data.h # Структуры данных (надо заменить) -└── __modbus_data.c # Функции доступа (надо заменить) +Modbus/ Иерархия модулей: +│ inc/ modbus +│ ├── modbus.h # Главный заголовочный файл modbus_slave +│ ├── modbus_core.h # Базовые определения и структуры modbus_master +│ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils +│ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs +│ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs +│ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid +│ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag +├── src/ └── rs_message +│ ├── modbus.c # Основная логика Modbus │ +│ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро) +│ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config +│ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data +│ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs +│ ├── modbus_inputregs.c # Реализация входных регистров +│ ├── modbus_devid.c # Реализация идентификации устройства +│ ├── modbus_data.c # Функции доступа к данным +│ └── rs_message.c # Реализация драйвера RS +├── __modbus_config.h # Конфигурация Modbus (надо заменить) +├── __modbus_data.h # Структуры данных (надо заменить) +└── __modbus_data.c # Функции доступа (надо заменить) ``` ## Инструкция по подключению -1. **Склонируйте субмодуль** в ваш проект: +### 1. **Склонируйте субмодуль** в ваш проект: ```bash git submodule add https://git.arktika.cyou/set506/STM32_Modbus path/to/Modbus git submodule update --init --recursive ``` -2. **Скопируйте файлы конфигурации** в отдельную папку в вашем проекте (вне субмодуля) и удалите `__` из имени файлов: +### 2. **Скопируйте файлы конфигурации** в отдельную папку в вашем проекте (вне субмодуля) и удалите `__` из имени файлов: ``` ProjectRoot/ @@ -47,219 +47,210 @@ ProjectRoot/ │ ├── modbus_config.h # скопировать из __modbus_config.h │ ├── modbus_data.h # скопировать из __modbus_data.h │ └── modbus_data.c # скопировать из __modbus_data.c -└── Modbus/ # Субмодуль +└── Modbus/ # Субмодуль ``` -3. **Настройте конфигурацию** под ваш проект: - - 3.1. Настройка периферии +### 3. **Настройте конфигурацию** под ваш проект: + #### 3.1. Настройка периферии - - **UART**: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1 - - **TIM**: Настройте таймер для генерации прерываний (например, 1ms tick) - - **Включите прерывания** для UART и TIM + - **UART**: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1 + - **TIM**: Настройте таймер для генерации прерываний (например, 1ms tick) + - **Включите прерывания** для UART и TIM - 3.2. Подключение обработчиков прерываний + #### 3.2. Подключение обработчиков прерываний - Подключите обработчики прерываний **UART** и **TIM** в свои IRQ обработчики ***вместо*** HAL-обработчиков: + Подключите обработчики прерываний **UART** и **TIM** в свои IRQ обработчики ***вместо*** HAL-обработчиков: - ```c - #include "modbus.h" +```c +#include "modbus.h" - void USARTx_IRQHandler(void) - { - RS_UART_Handler(&hmodbus1); - return; - HAL_UART_IRQHandler(&huart); - } +void USARTx_IRQHandler(void) +{ + RS_UART_Handler(&hmodbus1); + return; + HAL_UART_IRQHandler(&huart); +} - void TIMx_IRQHandler(void) - { - RS_TIM_Handler(&hmodbus1); - return; - HAL_TIM_IRQHandler(&htim); - } - ``` +void TIMx_IRQHandler(void) +{ + RS_TIM_Handler(&hmodbus1); + return; + HAL_TIM_IRQHandler(&htim); +} +``` + #### 3.3. В `modbus_config.h` укажите параметры устройства - 3.3. В `modbus_config.h` укажите параметры устройства + #### 3.4. Инициализация в коде + + Чтобы настроить Slave-режим `main()` после инициализации HAL: - 3.4. Инициализация в коде - - Чтобы настроить Slave-режим `main()` после инициализации HAL: +```c +#include "modbus.h" - ```c - #include "modbus.h" +int main(void) +{ + // Инициализация HAL + HAL_Init(); + SystemClock_Config(); + MX_GPIO_Init(); + MX_USART1_UART_Init(); + MX_TIM3_Init(); + + // Инициализация Modbus + MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim); + MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); + + // Запуск приема Modbus + MODBUS_SlaveStart(&hmodbus1, NULL); + + while (1) + { + // Основной цикл + } +} +``` + Чтобы настроить Master-режим `main()` после инициализации HAL: - int main(void) - { - // Инициализация HAL - HAL_Init(); - SystemClock_Config(); - MX_GPIO_Init(); - MX_USART1_UART_Init(); - MX_TIM3_Init(); - - // Инициализация Modbus - MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim); - MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); - - // Запуск приема Modbus - MODBUS_SlaveStart(&hmodbus1, NULL); - - while (1) - { - // Основной цикл - } - } - ``` +```c +#include "modbus.h" +// Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук +RS_MsgTypeDef read_hold_cmd = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10); +// коллбек, вызовется при получении ответа от слейва +read_hold[10]; +void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) +{ + // MB_RespGet_... Чтобы достать нужные данные из ответа + if(hmodbus->RS_STATUS == RS_OK) + { + for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) + { + uint16_t value; + if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) + { + read_hold[i] = value; + } + } + } +} +int main(void) +{ + // Инициализация HAL + HAL_Init(); + SystemClock_Config(); + MX_GPIO_Init(); + MX_USART1_UART_Init(); + MX_TIM3_Init(); + + // Инициализация Modbus + MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim); + MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER); + + // Запрос по Modbus + MODBUS_MasterRequest(&hmodbus1, &read_hold_cmd, &callback_func); - Чтобы настроить Master-режим `main()` после инициализации HAL: +} +``` + #### 3.5. Настройка карты данных - ```c - #include "modbus.h" - // Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук - RS_MsgTypeDef read_hold_cmd = MB_MASTER_READ_HOLDING_REGS(1, 0, 10); - // коллбек, вызовется при получении ответа от слейва - read_hold[10]; - void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) - { - // MB_RespGet_... Чтобы достать нужные данные из ответа - if(hmodbus->RS_STATUS == RS_OK) - { - for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) - { - uint16_t value; - if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) - { - read_hold[i] = value; - } - } - } - } - int main(void) - { - // Инициализация HAL - HAL_Init(); - SystemClock_Config(); - MX_GPIO_Init(); - MX_USART1_UART_Init(); - MX_TIM3_Init(); - - // Инициализация Modbus - MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim); - MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER); - - // Запрос по Modbus - MODBUS_MasterRequest(&hmodbus1, &read_hold_cmd, &callback_func); + В `modbus_data.h` настройте регистры и coils под ваше устройство: - } - ``` - 3.5. Настройка карты данных + **Input Registers (только чтение)** +```c +typedef struct +{ + uint16_t Temperature; // Адрес 0 + uint16_t Humidity; // Адрес 1 + uint16_t Pressure; // Адрес 2 + uint16_t Voltage; // Адрес 3 +} MB_DataInRegsTypeDef; - В `modbus_data.h` настройте регистры и coils под ваше устройство: +#define R_INPUT_ADDR 0 // Начальный адрес Input регистров +#define R_INPUT_QNT 4 // Количество Input регистров +``` + **Holding Registers (чтение/запись)** +```c +typedef struct +{ + uint16_t SetpointTemp; // Адрес 0 + uint16_t SetpointHumidity; // Адрес 1 + uint16_t ControlMode; // Адрес 2 +} MB_DataHoldRegsTypeDef; - **Input Registers (только чтение)** - ```c - typedef struct - { - uint16_t Temperature; // Адрес 0 - uint16_t Humidity; // Адрес 1 - uint16_t Pressure; // Адрес 2 - uint16_t Voltage; // Адрес 3 - } MB_DataInRegsTypeDef; +#define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров +#define R_HOLDING_QNT 3 // Количество Holding регистров +``` + **Coils (1-битные)** +```c +typedef struct +{ + unsigned Relay1 : 1; // Адрес 0 + unsigned Relay2 : 1; // Адрес 1 + unsigned Pump : 1; // Адрес 2 + unsigned Heater : 1; // Адрес 3 + unsigned reserved : 12; // Резерв (выравнивание до 16 бит) +} MB_DataCoilsTypeDef; - #define R_INPUT_ADDR 0 // Начальный адрес Input регистров - #define R_INPUT_QNT 4 // Количество Input регистров - ``` +#define C_COILS_ADDR 0 // Начальный адрес Coils +#define C_COILS_QNT 4 // Количество Coils +``` + #### 3.6. Доступ к данным в коде - **Holding Registers (чтение/запись)** - ```c - typedef struct - { - uint16_t SetpointTemp; // Адрес 0 - uint16_t SetpointHumidity; // Адрес 1 - uint16_t ControlMode; // Адрес 2 - } MB_DataHoldRegsTypeDef; + В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля +```c +// Чтение входных регистров +uint16_t temp = MB_DATA.InRegs.Temperature; - #define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров - #define R_HOLDING_QNT 3 // Количество Holding регистров - ``` +// Запись в регистры хранения +MB_DATA.HoldRegs.SetpointTemp = 2500; - **Coils (1-битные)** - ```c - typedef struct - { - unsigned Relay1 : 1; // Адрес 0 - unsigned Relay2 : 1; // Адрес 1 - unsigned Pump : 1; // Адрес 2 - unsigned Heater : 1; // Адрес 3 - unsigned reserved : 12; // Резерв (выравнивание до 16 бит) - } MB_DataCoilsTypeDef; +// Управление coils +MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить Relay1 +MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить Relay2 - #define C_COILS_ADDR 0 // Начальный адрес Coils - #define C_COILS_QNT 4 // Количество Coils - ``` +// Чтение coil +if (MB_Coil_Read_Local(&MB_DATA.Coils, 2)) { + // Pump включен +} +``` + В режиме мастера есть функции для получения информации из ответа `MB_RespGet_...()` +```c +// Чтение регистров: Получить запрошенные регистры +uint16_t value; +if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, ®_value)) +{ + printf("Register 105 value: %d\n", reg_value); +} +// Чтение коилов: Получить запрошенные коилы +int state; +if(MB_RespGet_CoilState(&MODBUS_MSG, 25, &coil_state)) +{ + printf("Coil 25 state: %s\n", coil_state ? "ON" : "OFF"); +} +// Чтение диагностики: Получить запрошенныую диагностику +uint16_t counter_value; +if(MB_RespGet_DiagnosticResponse(&MODBUS_MSG, &counter_value)) +{ + printf("Counter value: %d\n", counter_value); +} +// Чтение идентификаторов: Получить запрошенные идентификаторы +uint8_t length; +char vendor_name[64]; +if(MB_RespGet_ObjectById(&MODBUS_MSG, 0x00, vendor_name, &length)) +{ + printf("Vendor Name: %s (length: %d)\n", vendor_name, length); +} - 3.6. Доступ к данным в коде - - - В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля - ```c - // Чтение входных регистров - uint16_t temp = MB_DATA.InRegs.Temperature; - - // Запись в регистры хранения - MB_DATA.HoldRegs.SetpointTemp = 2500; - - // Управление coils - MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить Relay1 - MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить Relay2 - - // Чтение coil - if (MB_Coil_Read_Local(&MB_DATA.Coils, 2)) { - // Pump включен - } - ``` - - В режиме мастера есть функции для получения информации из ответа `MB_RespGet_...()` - ```c - // Чтение регистров: Получить запрошенные регистры - uint16_t value; - if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, ®_value)) - { - printf("Register 105 value: %d\n", reg_value); - } - // Чтение коилов: Получить запрошенные коилы - int state; - if(MB_RespGet_CoilState(&MODBUS_MSG, 25, &coil_state)) - { - printf("Coil 25 state: %s\n", coil_state ? "ON" : "OFF"); - } - // Чтение диагностики: Получить запрошенныую диагностику - uint16_t counter_value; - if(MB_RespGet_DiagnosticResponse(&MODBUS_MSG, &counter_value)) - { - printf("Counter value: %d\n", counter_value); - } - // Чтение идентификаторов: Получить запрошенные идентификаторы - uint8_t length; - char vendor_name[64]; - if(MB_RespGet_ObjectById(&MODBUS_MSG, 0x00, vendor_name, &length)) - { - printf("Vendor Name: %s (length: %d)\n", vendor_name, length); - } - - uint8_t obj_id, obj_length; - char obj_data[64]; - if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, 0x00, &obj_id, obj_data, &obj_length)) - { - printf("First object - ID: 0x%02X, Data: %s\n", obj_id, obj_data); - } - ``` +uint8_t obj_id, obj_length; +char obj_data[64]; +if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, 0x00, &obj_id, obj_data, &obj_length)) +{ + printf("First object - ID: 0x%02X, Data: %s\n", obj_id, obj_data); +} +``` -5. **Обновление библиотеки**: - +### 5. **Обновление библиотеки**: После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся: ```bash diff --git a/Src/__modbus_compat.c b/Src/__modbus_compat.c new file mode 100644 index 0000000..3f2cf3f --- /dev/null +++ b/Src/__modbus_compat.c @@ -0,0 +1,7 @@ +/** +******************************************************************************* +* @file __modbus_compat.c +* @brief Модуль для совместимости библиотеки MODBUS. +******************************************************************************* +******************************************************************************/ +#include "modbus.h" diff --git a/Src/modbus.c b/Src/modbus.c index 72ba6eb..3973261 100644 --- a/Src/modbus.c +++ b/Src/modbus.c @@ -1,12 +1,12 @@ /** -************************************************************************** -* @file modbus.c -* @brief Модуль для реализации MODBUS. -************************************************************************** +******************************************************************************* +* @file modbus.c +* @brief Модуль для реализации MODBUS. +******************************************************************************* * @details Файл содержит реализацию функций работы с Modbus. -@section Функции и макросы +@section mbapi Функции и макросы ### Инициализация: - MODBUS_FirstInit() — Инициализация Modbus (подключение UART, TIM) @@ -164,9 +164,15 @@ HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef return HAL_ERROR; } +//------------------------------------------------------------------- +//-----------------------------INTERNAL------------------------------ - - +/** + * @brief Дефолтный коллбек для мастера. + * @param hmodbus Указатель на хендлер RS + * @param modbus_msg Указатель на структуру сообщения + * @details В этот коллбек попадут все запросы, с NULL-коллбеком + */ static void MB_DefaultCallback(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) { __NOP(); @@ -206,4 +212,4 @@ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modb { return MB_Master_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff); } -} \ No newline at end of file +} diff --git a/Src/modbus_coils.c b/Src/modbus_coils.c index 5b2d4d9..6c3430e 100644 --- a/Src/modbus_coils.c +++ b/Src/modbus_coils.c @@ -1,14 +1,22 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_coils.c * @brief Реализация работы с коилами Modbus -****************************************************************************** +******************************************************************************* * @details +Модуль для доступа к coils внутри программы: +- Функции для доступа к coils по глобальным адресам +- Макросы для доступа к coils по локальным адресам + Модуль обработки команд для coils (битовых данных): - Чтение coils (0x01) - упаковка битов в байты для передачи - Запись одиночного coil (0x05) - установка/сброс бита - Запись множественных coils (0x0F) - распаковка битов из байтов +@section cvalid Валидация данных: +- Проверка соответствия количества байт и регистров +- Валидация адресов через MB_DefineRegistersAddress() +- Обработка исключений при некорректных запросах ******************************************************************************/ #include "modbus_coils.h" @@ -18,7 +26,7 @@ * @brief Выставить/сбросить коил по глобальному адресу. * @param Addr Адрес коила. * @param WriteVal Что записать в коил: 0 или 1. - * @return ExceptionCode Код исключения если коила по адресу не существует, и NO_ERRORS если все ок. + * @return ExceptionCode Код исключения если коила по адресу не существует, и ET_NO_ERRORS если все ок. * * @details Позволяет обратиться к любому коилу по его глобальному адрессу. Вне зависимости от того как коилы размещены в памяти. @@ -26,13 +34,13 @@ MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) { //---------CHECK FOR ERRORS---------- - MB_ExceptionTypeDef Exception = NO_ERRORS; + MB_ExceptionTypeDef Exception = ET_NO_ERRORS; uint16_t *coils; uint16_t start_shift = 0; // shift in coils register //------------WRITE COIL------------- Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 1); - if(Exception == NO_ERRORS) + if(Exception == ET_NO_ERRORS) { switch(WriteVal) { @@ -75,7 +83,7 @@ uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) //------------READ COIL-------------- *Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 0); - if(*Exception == NO_ERRORS) + if(*Exception == ET_NO_ERRORS) { return ((*coils)&(1<Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0); - if(modbus_msg->Except_Code != NO_ERRORS) + if(modbus_msg->Except_Code != ET_NO_ERRORS) return 0; //-----------READING COIL------------ @@ -127,14 +135,14 @@ uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg) shift = 0; // set shift to zero for the next step //-----------READ COILS-------------- - modbus_msg->DATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift; + modbus_msg->MbData[ind] = (*(coils+ind)&mask_for_coils) >> start_shift; if(ind > 0) - modbus_msg->DATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift; + modbus_msg->MbData[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift; } - // т.к. DATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты + // т.к. MbData 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты for(; ind >= 0; --ind) - modbus_msg->DATA[ind] = ByteSwap16(modbus_msg->DATA[ind]); + modbus_msg->MbData[ind] = ByteSwap16(modbus_msg->MbData[ind]); return 1; } @@ -150,14 +158,14 @@ uint8_t MB_Process_Write_Single_Coil(RS_MsgTypeDef *modbus_msg) //---------CHECK FOR ERRORS---------- if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00)) { - modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; + modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE; return 0; } // define position of coil uint16_t *coils; uint16_t start_shift = 0; // shift in coils register modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1); - if(modbus_msg->Except_Code != NO_ERRORS) + if(modbus_msg->Except_Code != ET_NO_ERRORS) return 0; @@ -181,14 +189,14 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) //---------CHECK FOR ERRORS---------- if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8)) { // if quantity too large OR if quantity and bytes count arent match - modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; + modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE; return 0; } // define position of coil uint16_t *coils; // pointer to coils uint16_t start_shift = 0; // shift in coils register modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1); - if(modbus_msg->Except_Code != NO_ERRORS) + if(modbus_msg->Except_Code != ET_NO_ERRORS) return 0; //----------WRITTING COILS----------- @@ -218,10 +226,10 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) // get current coils temp_reg = *(coils+ind); // set coils - setted_coils = ByteSwap16(modbus_msg->DATA[ind]) << start_shift; + setted_coils = ByteSwap16(modbus_msg->MbData[ind]) << start_shift; if(ind > 0) { - setted_coils |= ((ByteSwap16(modbus_msg->DATA[ind-1]) << start_shift) >> 16); + setted_coils |= ((ByteSwap16(modbus_msg->MbData[ind-1]) << start_shift) >> 16); } // write coils @@ -236,13 +244,5 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) return 1; } -#else //MODBUS_ENABLE_COILS - -MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) {return ILLEGAL_FUNCTION;} -uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;} -uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg) {return 0;} -uint8_t MB_Process_Write_Single_Coil(RS_MsgTypeDef *modbus_msg) {return 0;} -uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) {return 0;} - -#endif \ No newline at end of file +#endif //MODBUS_ENABLE_COILS diff --git a/Src/modbus_core.c b/Src/modbus_core.c index 69d74ea..9e9dfcc 100644 --- a/Src/modbus_core.c +++ b/Src/modbus_core.c @@ -1,10 +1,10 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_core.c * @brief Базовая реализация ядра Modbus -****************************************************************************** +******************************************************************************* * @details В текущей реализации этот файл служит заглушкой для будущего расширения функциональности ядра Modbus протокола. ******************************************************************************/ -#include "modbus_core.h" \ No newline at end of file +#include "modbus_core.h" diff --git a/Src/modbus_devid.c b/Src/modbus_devid.c index 129b1c7..45453b7 100644 --- a/Src/modbus_devid.c +++ b/Src/modbus_devid.c @@ -1,15 +1,15 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_devid.c * @brief Реализация идентификаторов устройства Modbus -****************************************************************************** +******************************************************************************* * @details Модуль обработки запросов идентификации устройства через MEI-тип 0x0E: - Формирование иерархии объектов идентификации - Поддержка потоковой передачи при большом количестве объектов - Автоматический расчет MoreFollows флагов -@section Потоковая передача: +@section stream Потоковая передача: При большом количестве объектов идентификация разбивается на несколько сообщений с установкой флага MoreFollows и указанием NextObjId для продолжения чтения в следующем запросе. @@ -47,11 +47,16 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj) { MB_DeviceObjectTypeDef *obj = (MB_DeviceObjectTypeDef *)&MB_DEVID; unsigned objidtmp = modbus_msg->DevId.NextObjId; - + modbus_msg->Except_Code = ET_NO_ERRORS; + /* Define number of object in one message */ unsigned lastobjid = 0; for(int i = 0; i < DATA_SIZE*2;) { + /* Если объект за пределами допутимого - выходим из цикла */ + if(objidtmp >= 0xFF + MODBUS_NUMB_OF_USEROBJECTS) + break; + i += 2; i += obj[objidtmp].length; /* Если все еще помещается в массив переходим на следующий объект */ @@ -59,6 +64,7 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj) { objidtmp++; } + /* Если объекты для записи закончились - выходим из цикла*/ if(objidtmp > maxidofobj) break; @@ -67,7 +73,7 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj) /* Fill message with objects data */ - char *mbdata = (char *)&modbus_msg->DATA; + char *mbdata = (char *)&modbus_msg->MbData; unsigned ind = 0; unsigned objid = modbus_msg->DevId.NextObjId; for(; objid <= lastobjid; objid++) @@ -76,15 +82,23 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj) MB_WriteSingleObjectToMessage(mbdata, &ind, &obj[objid]); } objid--; - modbus_msg->ByteCnt = ind; - modbus_msg->DevId.NextObjId = lastobjid+1; - if(objid == maxidofobj) + + if(modbus_msg->ByteCnt != 0) { - modbus_msg->DevId.MoreFollows = 0; + modbus_msg->ByteCnt = ind; + modbus_msg->DevId.NextObjId = lastobjid+1; + if(objid == maxidofobj) + { + modbus_msg->DevId.MoreFollows = 0; + } + else + { + modbus_msg->DevId.MoreFollows = 0xFF; + } } else { - modbus_msg->DevId.MoreFollows = 0xFF; + modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE; } } @@ -97,9 +111,11 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj) */ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg) { + modbus_msg->DevId.Conformity = MODBUS_DEVICE_CONFORMITY; + switch(modbus_msg->DevId.ReadDevId) { - case MB_BASIC_IDENTIFICATIONS: + case RID_BASIC_IDENTIFICATIONS: if (modbus_msg->DevId.NextObjId == 0) { modbus_msg->DevId.NextObjId = 0; @@ -109,7 +125,7 @@ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg) modbus_msg->DevId.NumbOfObj = 3; break; - case MB_REGULAR_IDENTIFICATIONS: + case RID_REGULAR_IDENTIFICATIONS: if (modbus_msg->DevId.NextObjId == 0) { modbus_msg->DevId.NextObjId = 3; @@ -119,29 +135,38 @@ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg) modbus_msg->DevId.NumbOfObj = 4; break; - case MB_EXTENDED_IDENTIFICATIONS: + case RID_EXTENDED_IDENTIFICATIONS: if(MODBUS_NUMB_OF_USEROBJECTS <= 0 || MODBUS_NUMB_OF_USEROBJECTS > 128) { - return 0; + modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE; + break; } if (modbus_msg->DevId.NextObjId == 0) { modbus_msg->DevId.NextObjId = 0x80; } - + MB_WriteObjectsToMessage(modbus_msg, 0x80+MODBUS_NUMB_OF_USEROBJECTS); modbus_msg->DevId.NumbOfObj = MODBUS_NUMB_OF_USEROBJECTS; break; - case MB_SPEDIFIC_IDENTIFICATIONS: + case RID_SPEDIFIC_IDENTIFICATIONS: MB_WriteObjectsToMessage(modbus_msg, modbus_msg->DevId.NextObjId); modbus_msg->DevId.NumbOfObj = 1; break; default: return 0; } - return 1; + + if(modbus_msg->Except_Code != ET_NO_ERRORS) + { + return 0; + } + else + { + return 1; + } } @@ -158,400 +183,391 @@ void MB_DeviceInentificationInit(void) MB_ObjectInit(&MB_DEVID.ProductName, MODBUS_PRODUCT_NAME); MB_ObjectInit(&MB_DEVID.ModelName, MODBUS_MODEL_NAME); -#ifdef MODBUS_USEROBJECT_0_NAME - MB_ObjectInit(&MB_DEVID.User[0], MODBUS_USEROBJECT_0_NAME); +#if defined(MODBUS_USEROBJECT_0_NAME) && MODBUS_NUMB_OF_USEROBJECTS>0 + MB_ObjectInit(&MB_DEVID.User[0], MODBUS_USEROBJECT_0_NAME); #endif -#ifdef MODBUS_USEROBJECT_1_NAME - MB_ObjectInit(&MB_DEVID.User[1], MODBUS_USEROBJECT_1_NAME); +#if defined(MODBUS_USEROBJECT_1_NAME) && MODBUS_NUMB_OF_USEROBJECTS>1 + MB_ObjectInit(&MB_DEVID.User[1], MODBUS_USEROBJECT_1_NAME); #endif -#ifdef MODBUS_USEROBJECT_2_NAME - MB_ObjectInit(&MB_DEVID.User[2], MODBUS_USEROBJECT_2_NAME); +#if defined(MODBUS_USEROBJECT_2_NAME) && MODBUS_NUMB_OF_USEROBJECTS>2 + MB_ObjectInit(&MB_DEVID.User[2], MODBUS_USEROBJECT_2_NAME); #endif -#ifdef MODBUS_USEROBJECT_3_NAME - MB_ObjectInit(&MB_DEVID.User[3], MODBUS_USEROBJECT_3_NAME); +#if defined(MODBUS_USEROBJECT_3_NAME) && MODBUS_NUMB_OF_USEROBJECTS>3 + MB_ObjectInit(&MB_DEVID.User[3], MODBUS_USEROBJECT_3_NAME); #endif -#ifdef MODBUS_USEROBJECT_4_NAME - MB_ObjectInit(&MB_DEVID.User[4], MODBUS_USEROBJECT_4_NAME); +#if defined(MODBUS_USEROBJECT_4_NAME) && MODBUS_NUMB_OF_USEROBJECTS>4 + MB_ObjectInit(&MB_DEVID.User[4], MODBUS_USEROBJECT_4_NAME); #endif -#ifdef MODBUS_USEROBJECT_5_NAME - MB_ObjectInit(&MB_DEVID.User[5], MODBUS_USEROBJECT_5_NAME); +#if defined(MODBUS_USEROBJECT_5_NAME) && MODBUS_NUMB_OF_USEROBJECTS>5 + MB_ObjectInit(&MB_DEVID.User[5], MODBUS_USEROBJECT_5_NAME); #endif -#ifdef MODBUS_USEROBJECT_6_NAME - MB_ObjectInit(&MB_DEVID.User[6], MODBUS_USEROBJECT_6_NAME); +#if defined(MODBUS_USEROBJECT_6_NAME) && MODBUS_NUMB_OF_USEROBJECTS>6 + MB_ObjectInit(&MB_DEVID.User[6], MODBUS_USEROBJECT_6_NAME); #endif -#ifdef MODBUS_USEROBJECT_7_NAME - MB_ObjectInit(&MB_DEVID.User[7], MODBUS_USEROBJECT_7_NAME); +#if defined(MODBUS_USEROBJECT_7_NAME) && MODBUS_NUMB_OF_USEROBJECTS>7 + MB_ObjectInit(&MB_DEVID.User[7], MODBUS_USEROBJECT_7_NAME); #endif -#ifdef MODBUS_USEROBJECT_8_NAME - MB_ObjectInit(&MB_DEVID.User[8], MODBUS_USEROBJECT_8_NAME); +#if defined(MODBUS_USEROBJECT_8_NAME) && MODBUS_NUMB_OF_USEROBJECTS>8 + MB_ObjectInit(&MB_DEVID.User[8], MODBUS_USEROBJECT_8_NAME); #endif -#ifdef MODBUS_USEROBJECT_9_NAME - MB_ObjectInit(&MB_DEVID.User[9], MODBUS_USEROBJECT_9_NAME); +#if defined(MODBUS_USEROBJECT_9_NAME) && MODBUS_NUMB_OF_USEROBJECTS>9 + MB_ObjectInit(&MB_DEVID.User[9], MODBUS_USEROBJECT_9_NAME); #endif -#ifdef MODBUS_USEROBJECT_10_NAME - MB_ObjectInit(&MB_DEVID.User[10], MODBUS_USEROBJECT_10_NAME); +#if defined(MODBUS_USEROBJECT_10_NAME) && MODBUS_NUMB_OF_USEROBJECTS>10 + MB_ObjectInit(&MB_DEVID.User[10], MODBUS_USEROBJECT_10_NAME); #endif -#ifdef MODBUS_USEROBJECT_11_NAME - MB_ObjectInit(&MB_DEVID.User[11], MODBUS_USEROBJECT_11_NAME); +#if defined(MODBUS_USEROBJECT_11_NAME) && MODBUS_NUMB_OF_USEROBJECTS>11 + MB_ObjectInit(&MB_DEVID.User[11], MODBUS_USEROBJECT_11_NAME); #endif -#ifdef MODBUS_USEROBJECT_12_NAME - MB_ObjectInit(&MB_DEVID.User[12], MODBUS_USEROBJECT_12_NAME); +#if defined(MODBUS_USEROBJECT_12_NAME) && MODBUS_NUMB_OF_USEROBJECTS>12 + MB_ObjectInit(&MB_DEVID.User[12], MODBUS_USEROBJECT_12_NAME); #endif -#ifdef MODBUS_USEROBJECT_13_NAME +#if defined(MODBUS_USEROBJECT_13_NAME) && MODBUS_NUMB_OF_USEROBJECTS>13 MB_ObjectInit(&MB_DEVID.User[13], MODBUS_USEROBJECT_13_NAME); #endif -#ifdef MODBUS_USEROBJECT_14_NAME +#if defined(MODBUS_USEROBJECT_14_NAME) && MODBUS_NUMB_OF_USEROBJECTS>14 MB_ObjectInit(&MB_DEVID.User[14], MODBUS_USEROBJECT_14_NAME); #endif -#ifdef MODBUS_USEROBJECT_15_NAME +#if defined(MODBUS_USEROBJECT_15_NAME) && MODBUS_NUMB_OF_USEROBJECTS>15 MB_ObjectInit(&MB_DEVID.User[15], MODBUS_USEROBJECT_15_NAME); #endif -#ifdef MODBUS_USEROBJECT_16_NAME +#if defined(MODBUS_USEROBJECT_16_NAME) && MODBUS_NUMB_OF_USEROBJECTS>16 MB_ObjectInit(&MB_DEVID.User[16], MODBUS_USEROBJECT_16_NAME); #endif -#ifdef MODBUS_USEROBJECT_17_NAME +#if defined(MODBUS_USEROBJECT_17_NAME) && MODBUS_NUMB_OF_USEROBJECTS>17 MB_ObjectInit(&MB_DEVID.User[17], MODBUS_USEROBJECT_17_NAME); #endif -#ifdef MODBUS_USEROBJECT_18_NAME +#if defined(MODBUS_USEROBJECT_18_NAME) && MODBUS_NUMB_OF_USEROBJECTS>18 MB_ObjectInit(&MB_DEVID.User[18], MODBUS_USEROBJECT_18_NAME); #endif -#ifdef MODBUS_USEROBJECT_19_NAME +#if defined(MODBUS_USEROBJECT_19_NAME) && MODBUS_NUMB_OF_USEROBJECTS>19 MB_ObjectInit(&MB_DEVID.User[19], MODBUS_USEROBJECT_19_NAME); #endif -#ifdef MODBUS_USEROBJECT_20_NAME +#if defined(MODBUS_USEROBJECT_20_NAME) && MODBUS_NUMB_OF_USEROBJECTS>20 MB_ObjectInit(&MB_DEVID.User[20], MODBUS_USEROBJECT_20_NAME); #endif -#ifdef MODBUS_USEROBJECT_21_NAME +#if defined(MODBUS_USEROBJECT_21_NAME) && MODBUS_NUMB_OF_USEROBJECTS>21 MB_ObjectInit(&MB_DEVID.User[21], MODBUS_USEROBJECT_21_NAME); #endif -#ifdef MODBUS_USEROBJECT_22_NAME +#if defined(MODBUS_USEROBJECT_22_NAME) && MODBUS_NUMB_OF_USEROBJECTS>22 MB_ObjectInit(&MB_DEVID.User[22], MODBUS_USEROBJECT_22_NAME); #endif -#ifdef MODBUS_USEROBJECT_23_NAME +#if defined(MODBUS_USEROBJECT_23_NAME) && MODBUS_NUMB_OF_USEROBJECTS>23 MB_ObjectInit(&MB_DEVID.User[23], MODBUS_USEROBJECT_23_NAME); #endif -#ifdef MODBUS_USEROBJECT_24_NAME +#if defined(MODBUS_USEROBJECT_24_NAME) && MODBUS_NUMB_OF_USEROBJECTS>24 MB_ObjectInit(&MB_DEVID.User[24], MODBUS_USEROBJECT_24_NAME); #endif -#ifdef MODBUS_USEROBJECT_25_NAME +#if defined(MODBUS_USEROBJECT_25_NAME) && MODBUS_NUMB_OF_USEROBJECTS>25 MB_ObjectInit(&MB_DEVID.User[25], MODBUS_USEROBJECT_25_NAME); #endif -#ifdef MODBUS_USEROBJECT_26_NAME +#if defined(MODBUS_USEROBJECT_26_NAME) && MODBUS_NUMB_OF_USEROBJECTS>26 MB_ObjectInit(&MB_DEVID.User[26], MODBUS_USEROBJECT_26_NAME); #endif -#ifdef MODBUS_USEROBJECT_27_NAME +#if defined(MODBUS_USEROBJECT_27_NAME) && MODBUS_NUMB_OF_USEROBJECTS>27 MB_ObjectInit(&MB_DEVID.User[27], MODBUS_USEROBJECT_27_NAME); #endif -#ifdef MODBUS_USEROBJECT_28_NAME +#if defined(MODBUS_USEROBJECT_28_NAME) && MODBUS_NUMB_OF_USEROBJECTS>28 MB_ObjectInit(&MB_DEVID.User[28], MODBUS_USEROBJECT_28_NAME); #endif -#ifdef MODBUS_USEROBJECT_29_NAME +#if defined(MODBUS_USEROBJECT_29_NAME) && MODBUS_NUMB_OF_USEROBJECTS>29 MB_ObjectInit(&MB_DEVID.User[29], MODBUS_USEROBJECT_29_NAME); #endif -#ifdef MODBUS_USEROBJECT_30_NAME +#if defined(MODBUS_USEROBJECT_30_NAME) && MODBUS_NUMB_OF_USEROBJECTS>30 MB_ObjectInit(&MB_DEVID.User[30], MODBUS_USEROBJECT_30_NAME); #endif -#ifdef MODBUS_USEROBJECT_31_NAME +#if defined(MODBUS_USEROBJECT_31_NAME) && MODBUS_NUMB_OF_USEROBJECTS>31 MB_ObjectInit(&MB_DEVID.User[31], MODBUS_USEROBJECT_31_NAME); #endif -#ifdef MODBUS_USEROBJECT_32_NAME +#if defined(MODBUS_USEROBJECT_32_NAME) && MODBUS_NUMB_OF_USEROBJECTS>32 MB_ObjectInit(&MB_DEVID.User[32], MODBUS_USEROBJECT_32_NAME); #endif -#ifdef MODBUS_USEROBJECT_33_NAME +#if defined(MODBUS_USEROBJECT_33_NAME) && MODBUS_NUMB_OF_USEROBJECTS>33 MB_ObjectInit(&MB_DEVID.User[33], MODBUS_USEROBJECT_33_NAME); #endif -#ifdef MODBUS_USEROBJECT_34_NAME +#if defined(MODBUS_USEROBJECT_34_NAME) && MODBUS_NUMB_OF_USEROBJECTS>34 MB_ObjectInit(&MB_DEVID.User[34], MODBUS_USEROBJECT_34_NAME); #endif -#ifdef MODBUS_USEROBJECT_35_NAME +#if defined(MODBUS_USEROBJECT_35_NAME) && MODBUS_NUMB_OF_USEROBJECTS>35 MB_ObjectInit(&MB_DEVID.User[35], MODBUS_USEROBJECT_35_NAME); #endif -#ifdef MODBUS_USEROBJECT_36_NAME +#if defined(MODBUS_USEROBJECT_36_NAME) && MODBUS_NUMB_OF_USEROBJECTS>36 MB_ObjectInit(&MB_DEVID.User[36], MODBUS_USEROBJECT_36_NAME); #endif -#ifdef MODBUS_USEROBJECT_37_NAME +#if defined(MODBUS_USEROBJECT_37_NAME) && MODBUS_NUMB_OF_USEROBJECTS>37 MB_ObjectInit(&MB_DEVID.User[37], MODBUS_USEROBJECT_37_NAME); #endif -#ifdef MODBUS_USEROBJECT_38_NAME +#if defined(MODBUS_USEROBJECT_38_NAME) && MODBUS_NUMB_OF_USEROBJECTS>38 MB_ObjectInit(&MB_DEVID.User[38], MODBUS_USEROBJECT_38_NAME); #endif -#ifdef MODBUS_USEROBJECT_39_NAME +#if defined(MODBUS_USEROBJECT_39_NAME) && MODBUS_NUMB_OF_USEROBJECTS>39 MB_ObjectInit(&MB_DEVID.User[39], MODBUS_USEROBJECT_39_NAME); #endif -#ifdef MODBUS_USEROBJECT_40_NAME +#if defined(MODBUS_USEROBJECT_40_NAME) && MODBUS_NUMB_OF_USEROBJECTS>40 MB_ObjectInit(&MB_DEVID.User[40], MODBUS_USEROBJECT_40_NAME); #endif -#ifdef MODBUS_USEROBJECT_41_NAME +#if defined(MODBUS_USEROBJECT_41_NAME) && MODBUS_NUMB_OF_USEROBJECTS>41 MB_ObjectInit(&MB_DEVID.User[41], MODBUS_USEROBJECT_41_NAME); #endif -#ifdef MODBUS_USEROBJECT_42_NAME +#if defined(MODBUS_USEROBJECT_42_NAME) && MODBUS_NUMB_OF_USEROBJECTS>42 MB_ObjectInit(&MB_DEVID.User[42], MODBUS_USEROBJECT_42_NAME); #endif -#ifdef MODBUS_USEROBJECT_43_NAME +#if defined(MODBUS_USEROBJECT_43_NAME) && MODBUS_NUMB_OF_USEROBJECTS>43 MB_ObjectInit(&MB_DEVID.User[43], MODBUS_USEROBJECT_43_NAME); #endif -#ifdef MODBUS_USEROBJECT_44_NAME +#if defined(MODBUS_USEROBJECT_44_NAME) && MODBUS_NUMB_OF_USEROBJECTS>44 MB_ObjectInit(&MB_DEVID.User[44], MODBUS_USEROBJECT_44_NAME); #endif -#ifdef MODBUS_USEROBJECT_45_NAME +#if defined(MODBUS_USEROBJECT_45_NAME) && MODBUS_NUMB_OF_USEROBJECTS>45 MB_ObjectInit(&MB_DEVID.User[45], MODBUS_USEROBJECT_45_NAME); #endif -#ifdef MODBUS_USEROBJECT_46_NAME +#if defined(MODBUS_USEROBJECT_46_NAME) && MODBUS_NUMB_OF_USEROBJECTS>46 MB_ObjectInit(&MB_DEVID.User[46], MODBUS_USEROBJECT_46_NAME); #endif -#ifdef MODBUS_USEROBJECT_47_NAME +#if defined(MODBUS_USEROBJECT_47_NAME) && MODBUS_NUMB_OF_USEROBJECTS>47 MB_ObjectInit(&MB_DEVID.User[47], MODBUS_USEROBJECT_47_NAME); #endif -#ifdef MODBUS_USEROBJECT_48_NAME +#if defined(MODBUS_USEROBJECT_48_NAME) && MODBUS_NUMB_OF_USEROBJECTS>48 MB_ObjectInit(&MB_DEVID.User[48], MODBUS_USEROBJECT_48_NAME); #endif -#ifdef MODBUS_USEROBJECT_49_NAME +#if defined(MODBUS_USEROBJECT_49_NAME) && MODBUS_NUMB_OF_USEROBJECTS>49 MB_ObjectInit(&MB_DEVID.User[49], MODBUS_USEROBJECT_49_NAME); #endif -#ifdef MODBUS_USEROBJECT_50_NAME +#if defined(MODBUS_USEROBJECT_50_NAME) && MODBUS_NUMB_OF_USEROBJECTS>50 MB_ObjectInit(&MB_DEVID.User[50], MODBUS_USEROBJECT_50_NAME); #endif -#ifdef MODBUS_USEROBJECT_51_NAME +#if defined(MODBUS_USEROBJECT_51_NAME) && MODBUS_NUMB_OF_USEROBJECTS>51 MB_ObjectInit(&MB_DEVID.User[51], MODBUS_USEROBJECT_51_NAME); #endif -#ifdef MODBUS_USEROBJECT_52_NAME +#if defined(MODBUS_USEROBJECT_52_NAME) && MODBUS_NUMB_OF_USEROBJECTS>52 MB_ObjectInit(&MB_DEVID.User[52], MODBUS_USEROBJECT_52_NAME); #endif -#ifdef MODBUS_USEROBJECT_53_NAME +#if defined(MODBUS_USEROBJECT_53_NAME) && MODBUS_NUMB_OF_USEROBJECTS>53 MB_ObjectInit(&MB_DEVID.User[53], MODBUS_USEROBJECT_53_NAME); #endif -#ifdef MODBUS_USEROBJECT_54_NAME +#if defined(MODBUS_USEROBJECT_54_NAME) && MODBUS_NUMB_OF_USEROBJECTS>54 MB_ObjectInit(&MB_DEVID.User[54], MODBUS_USEROBJECT_54_NAME); #endif -#ifdef MODBUS_USEROBJECT_55_NAME +#if defined(MODBUS_USEROBJECT_55_NAME) && MODBUS_NUMB_OF_USEROBJECTS>55 MB_ObjectInit(&MB_DEVID.User[55], MODBUS_USEROBJECT_55_NAME); #endif -#ifdef MODBUS_USEROBJECT_56_NAME +#if defined(MODBUS_USEROBJECT_56_NAME) && MODBUS_NUMB_OF_USEROBJECTS>56 MB_ObjectInit(&MB_DEVID.User[56], MODBUS_USEROBJECT_56_NAME); #endif -#ifdef MODBUS_USEROBJECT_57_NAME +#if defined(MODBUS_USEROBJECT_57_NAME) && MODBUS_NUMB_OF_USEROBJECTS>57 MB_ObjectInit(&MB_DEVID.User[57], MODBUS_USEROBJECT_57_NAME); #endif -#ifdef MODBUS_USEROBJECT_58_NAME +#if defined(MODBUS_USEROBJECT_58_NAME) && MODBUS_NUMB_OF_USEROBJECTS>58 MB_ObjectInit(&MB_DEVID.User[58], MODBUS_USEROBJECT_58_NAME); #endif -#ifdef MODBUS_USEROBJECT_59_NAME +#if defined(MODBUS_USEROBJECT_59_NAME) && MODBUS_NUMB_OF_USEROBJECTS>59 MB_ObjectInit(&MB_DEVID.User[59], MODBUS_USEROBJECT_59_NAME); #endif -#ifdef MODBUS_USEROBJECT_60_NAME +#if defined(MODBUS_USEROBJECT_60_NAME) && MODBUS_NUMB_OF_USEROBJECTS>60 MB_ObjectInit(&MB_DEVID.User[60], MODBUS_USEROBJECT_60_NAME); #endif -#ifdef MODBUS_USEROBJECT_61_NAME +#if defined(MODBUS_USEROBJECT_61_NAME) && MODBUS_NUMB_OF_USEROBJECTS>61 MB_ObjectInit(&MB_DEVID.User[61], MODBUS_USEROBJECT_61_NAME); #endif -#ifdef MODBUS_USEROBJECT_62_NAME +#if defined(MODBUS_USEROBJECT_62_NAME) && MODBUS_NUMB_OF_USEROBJECTS>62 MB_ObjectInit(&MB_DEVID.User[62], MODBUS_USEROBJECT_62_NAME); #endif -#ifdef MODBUS_USEROBJECT_63_NAME +#if defined(MODBUS_USEROBJECT_63_NAME) && MODBUS_NUMB_OF_USEROBJECTS>63 MB_ObjectInit(&MB_DEVID.User[63], MODBUS_USEROBJECT_63_NAME); #endif -#ifdef MODBUS_USEROBJECT_64_NAME +#if defined(MODBUS_USEROBJECT_64_NAME) && MODBUS_NUMB_OF_USEROBJECTS>64 MB_ObjectInit(&MB_DEVID.User[64], MODBUS_USEROBJECT_64_NAME); #endif -#ifdef MODBUS_USEROBJECT_65_NAME +#if defined(MODBUS_USEROBJECT_65_NAME) && MODBUS_NUMB_OF_USEROBJECTS>65 MB_ObjectInit(&MB_DEVID.User[65], MODBUS_USEROBJECT_65_NAME); #endif -#ifdef MODBUS_USEROBJECT_66_NAME +#if defined(MODBUS_USEROBJECT_66_NAME) && MODBUS_NUMB_OF_USEROBJECTS>66 MB_ObjectInit(&MB_DEVID.User[66], MODBUS_USEROBJECT_66_NAME); #endif -#ifdef MODBUS_USEROBJECT_67_NAME +#if defined(MODBUS_USEROBJECT_67_NAME) && MODBUS_NUMB_OF_USEROBJECTS>67 MB_ObjectInit(&MB_DEVID.User[67], MODBUS_USEROBJECT_67_NAME); #endif -#ifdef MODBUS_USEROBJECT_68_NAME +#if defined(MODBUS_USEROBJECT_68_NAME) && MODBUS_NUMB_OF_USEROBJECTS>68 MB_ObjectInit(&MB_DEVID.User[68], MODBUS_USEROBJECT_68_NAME); #endif -#ifdef MODBUS_USEROBJECT_69_NAME +#if defined(MODBUS_USEROBJECT_69_NAME) && MODBUS_NUMB_OF_USEROBJECTS>69 MB_ObjectInit(&MB_DEVID.User[69], MODBUS_USEROBJECT_69_NAME); #endif -#ifdef MODBUS_USEROBJECT_70_NAME +#if defined(MODBUS_USEROBJECT_70_NAME) && MODBUS_NUMB_OF_USEROBJECTS>70 MB_ObjectInit(&MB_DEVID.User[70], MODBUS_USEROBJECT_70_NAME); #endif -#ifdef MODBUS_USEROBJECT_71_NAME +#if defined(MODBUS_USEROBJECT_71_NAME) && MODBUS_NUMB_OF_USEROBJECTS>71 MB_ObjectInit(&MB_DEVID.User[71], MODBUS_USEROBJECT_71_NAME); #endif -#ifdef MODBUS_USEROBJECT_72_NAME +#if defined(MODBUS_USEROBJECT_72_NAME) && MODBUS_NUMB_OF_USEROBJECTS>72 MB_ObjectInit(&MB_DEVID.User[72], MODBUS_USEROBJECT_72_NAME); #endif -#ifdef MODBUS_USEROBJECT_73_NAME +#if defined(MODBUS_USEROBJECT_73_NAME) && MODBUS_NUMB_OF_USEROBJECTS>73 MB_ObjectInit(&MB_DEVID.User[73], MODBUS_USEROBJECT_73_NAME); #endif -#ifdef MODBUS_USEROBJECT_74_NAME +#if defined(MODBUS_USEROBJECT_74_NAME) && MODBUS_NUMB_OF_USEROBJECTS>74 MB_ObjectInit(&MB_DEVID.User[74], MODBUS_USEROBJECT_74_NAME); #endif -#ifdef MODBUS_USEROBJECT_75_NAME +#if defined(MODBUS_USEROBJECT_75_NAME) && MODBUS_NUMB_OF_USEROBJECTS>75 MB_ObjectInit(&MB_DEVID.User[75], MODBUS_USEROBJECT_75_NAME); #endif -#ifdef MODBUS_USEROBJECT_76_NAME +#if defined(MODBUS_USEROBJECT_76_NAME) && MODBUS_NUMB_OF_USEROBJECTS>76 MB_ObjectInit(&MB_DEVID.User[76], MODBUS_USEROBJECT_76_NAME); #endif -#ifdef MODBUS_USEROBJECT_77_NAME +#if defined(MODBUS_USEROBJECT_77_NAME) && MODBUS_NUMB_OF_USEROBJECTS>77 MB_ObjectInit(&MB_DEVID.User[77], MODBUS_USEROBJECT_77_NAME); #endif -#ifdef MODBUS_USEROBJECT_78_NAME +#if defined(MODBUS_USEROBJECT_78_NAME) && MODBUS_NUMB_OF_USEROBJECTS>78 MB_ObjectInit(&MB_DEVID.User[78], MODBUS_USEROBJECT_78_NAME); #endif -#ifdef MODBUS_USEROBJECT_79_NAME +#if defined(MODBUS_USEROBJECT_79_NAME) && MODBUS_NUMB_OF_USEROBJECTS>79 MB_ObjectInit(&MB_DEVID.User[79], MODBUS_USEROBJECT_79_NAME); #endif -#ifdef MODBUS_USEROBJECT_80_NAME +#if defined(MODBUS_USEROBJECT_80_NAME) && MODBUS_NUMB_OF_USEROBJECTS>80 MB_ObjectInit(&MB_DEVID.User[80], MODBUS_USEROBJECT_80_NAME); #endif -#ifdef MODBUS_USEROBJECT_81_NAME +#if defined(MODBUS_USEROBJECT_81_NAME) && MODBUS_NUMB_OF_USEROBJECTS>81 MB_ObjectInit(&MB_DEVID.User[81], MODBUS_USEROBJECT_81_NAME); #endif -#ifdef MODBUS_USEROBJECT_82_NAME +#if defined(MODBUS_USEROBJECT_82_NAME) && MODBUS_NUMB_OF_USEROBJECTS>82 MB_ObjectInit(&MB_DEVID.User[82], MODBUS_USEROBJECT_82_NAME); #endif -#ifdef MODBUS_USEROBJECT_83_NAME +#if defined(MODBUS_USEROBJECT_83_NAME) && MODBUS_NUMB_OF_USEROBJECTS>83 MB_ObjectInit(&MB_DEVID.User[83], MODBUS_USEROBJECT_83_NAME); #endif -#ifdef MODBUS_USEROBJECT_84_NAME +#if defined(MODBUS_USEROBJECT_84_NAME) && MODBUS_NUMB_OF_USEROBJECTS>84 MB_ObjectInit(&MB_DEVID.User[84], MODBUS_USEROBJECT_84_NAME); #endif -#ifdef MODBUS_USEROBJECT_85_NAME +#if defined(MODBUS_USEROBJECT_85_NAME) && MODBUS_NUMB_OF_USEROBJECTS>85 MB_ObjectInit(&MB_DEVID.User[85], MODBUS_USEROBJECT_85_NAME); #endif -#ifdef MODBUS_USEROBJECT_86_NAME +#if defined(MODBUS_USEROBJECT_86_NAME) && MODBUS_NUMB_OF_USEROBJECTS>86 MB_ObjectInit(&MB_DEVID.User[86], MODBUS_USEROBJECT_86_NAME); #endif -#ifdef MODBUS_USEROBJECT_87_NAME +#if defined(MODBUS_USEROBJECT_87_NAME) && MODBUS_NUMB_OF_USEROBJECTS>87 MB_ObjectInit(&MB_DEVID.User[87], MODBUS_USEROBJECT_87_NAME); #endif -#ifdef MODBUS_USEROBJECT_88_NAME +#if defined(MODBUS_USEROBJECT_88_NAME) && MODBUS_NUMB_OF_USEROBJECTS>88 MB_ObjectInit(&MB_DEVID.User[88], MODBUS_USEROBJECT_88_NAME); #endif -#ifdef MODBUS_USEROBJECT_89_NAME +#if defined(MODBUS_USEROBJECT_89_NAME) && MODBUS_NUMB_OF_USEROBJECTS>89 MB_ObjectInit(&MB_DEVID.User[89], MODBUS_USEROBJECT_89_NAME); #endif -#ifdef MODBUS_USEROBJECT_90_NAME +#if defined(MODBUS_USEROBJECT_90_NAME) && MODBUS_NUMB_OF_USEROBJECTS>90 MB_ObjectInit(&MB_DEVID.User[90], MODBUS_USEROBJECT_90_NAME); #endif -#ifdef MODBUS_USEROBJECT_91_NAME +#if defined(MODBUS_USEROBJECT_91_NAME) && MODBUS_NUMB_OF_USEROBJECTS>91 MB_ObjectInit(&MB_DEVID.User[91], MODBUS_USEROBJECT_91_NAME); #endif -#ifdef MODBUS_USEROBJECT_92_NAME +#if defined(MODBUS_USEROBJECT_92_NAME) && MODBUS_NUMB_OF_USEROBJECTS>92 MB_ObjectInit(&MB_DEVID.User[92], MODBUS_USEROBJECT_92_NAME); #endif -#ifdef MODBUS_USEROBJECT_93_NAME +#if defined(MODBUS_USEROBJECT_93_NAME) && MODBUS_NUMB_OF_USEROBJECTS>93 MB_ObjectInit(&MB_DEVID.User[93], MODBUS_USEROBJECT_93_NAME); #endif -#ifdef MODBUS_USEROBJECT_94_NAME +#if defined(MODBUS_USEROBJECT_94_NAME) && MODBUS_NUMB_OF_USEROBJECTS>94 MB_ObjectInit(&MB_DEVID.User[94], MODBUS_USEROBJECT_94_NAME); #endif -#ifdef MODBUS_USEROBJECT_95_NAME +#if defined(MODBUS_USEROBJECT_95_NAME) && MODBUS_NUMB_OF_USEROBJECTS>95 MB_ObjectInit(&MB_DEVID.User[95], MODBUS_USEROBJECT_95_NAME); #endif -#ifdef MODBUS_USEROBJECT_96_NAME +#if defined(MODBUS_USEROBJECT_96_NAME) && MODBUS_NUMB_OF_USEROBJECTS>96 MB_ObjectInit(&MB_DEVID.User[96], MODBUS_USEROBJECT_96_NAME); #endif -#ifdef MODBUS_USEROBJECT_97_NAME +#if defined(MODBUS_USEROBJECT_97_NAME) && MODBUS_NUMB_OF_USEROBJECTS>97 MB_ObjectInit(&MB_DEVID.User[97], MODBUS_USEROBJECT_97_NAME); #endif -#ifdef MODBUS_USEROBJECT_98_NAME +#if defined(MODBUS_USEROBJECT_98_NAME) && MODBUS_NUMB_OF_USEROBJECTS>98 MB_ObjectInit(&MB_DEVID.User[98], MODBUS_USEROBJECT_98_NAME); #endif -#ifdef MODBUS_USEROBJECT_99_NAME +#if defined(MODBUS_USEROBJECT_99_NAME) && MODBUS_NUMB_OF_USEROBJECTS>99 MB_ObjectInit(&MB_DEVID.User[99], MODBUS_USEROBJECT_99_NAME); #endif -#ifdef MODBUS_USEROBJECT_100_NAME +#if defined(MODBUS_USEROBJECT_100_NAME) && MODBUS_NUMB_OF_USEROBJECTS>100 MB_ObjectInit(&MB_DEVID.User[100], MODBUS_USEROBJECT_100_NAME); #endif -#ifdef MODBUS_USEROBJECT_101_NAME +#if defined(MODBUS_USEROBJECT_101_NAME) && MODBUS_NUMB_OF_USEROBJECTS>101 MB_ObjectInit(&MB_DEVID.User[101], MODBUS_USEROBJECT_101_NAME); #endif -#ifdef MODBUS_USEROBJECT_102_NAME +#if defined(MODBUS_USEROBJECT_102_NAME) && MODBUS_NUMB_OF_USEROBJECTS>102 MB_ObjectInit(&MB_DEVID.User[102], MODBUS_USEROBJECT_102_NAME); #endif -#ifdef MODBUS_USEROBJECT_103_NAME +#if defined(MODBUS_USEROBJECT_103_NAME) && MODBUS_NUMB_OF_USEROBJECTS>103 MB_ObjectInit(&MB_DEVID.User[103], MODBUS_USEROBJECT_103_NAME); #endif -#ifdef MODBUS_USEROBJECT_104_NAME +#if defined(MODBUS_USEROBJECT_104_NAME) && MODBUS_NUMB_OF_USEROBJECTS>104 MB_ObjectInit(&MB_DEVID.User[104], MODBUS_USEROBJECT_104_NAME); #endif -#ifdef MODBUS_USEROBJECT_105_NAME +#if defined(MODBUS_USEROBJECT_105_NAME) && MODBUS_NUMB_OF_USEROBJECTS>105 MB_ObjectInit(&MB_DEVID.User[105], MODBUS_USEROBJECT_105_NAME); #endif -#ifdef MODBUS_USEROBJECT_106_NAME +#if defined(MODBUS_USEROBJECT_106_NAME) && MODBUS_NUMB_OF_USEROBJECTS>106 MB_ObjectInit(&MB_DEVID.User[106], MODBUS_USEROBJECT_106_NAME); #endif -#ifdef MODBUS_USEROBJECT_107_NAME +#if defined(MODBUS_USEROBJECT_107_NAME) && MODBUS_NUMB_OF_USEROBJECTS>107 MB_ObjectInit(&MB_DEVID.User[107], MODBUS_USEROBJECT_107_NAME); #endif -#ifdef MODBUS_USEROBJECT_108_NAME +#if defined(MODBUS_USEROBJECT_108_NAME) && MODBUS_NUMB_OF_USEROBJECTS>108 MB_ObjectInit(&MB_DEVID.User[108], MODBUS_USEROBJECT_108_NAME); #endif -#ifdef MODBUS_USEROBJECT_109_NAME +#if defined(MODBUS_USEROBJECT_109_NAME) && MODBUS_NUMB_OF_USEROBJECTS>109 MB_ObjectInit(&MB_DEVID.User[109], MODBUS_USEROBJECT_109_NAME); #endif -#ifdef MODBUS_USEROBJECT_110_NAME +#if defined(MODBUS_USEROBJECT_110_NAME) && MODBUS_NUMB_OF_USEROBJECTS>110 MB_ObjectInit(&MB_DEVID.User[110], MODBUS_USEROBJECT_110_NAME); #endif -#ifdef MODBUS_USEROBJECT_111_NAME +#if defined(MODBUS_USEROBJECT_111_NAME) && MODBUS_NUMB_OF_USEROBJECTS>111 MB_ObjectInit(&MB_DEVID.User[111], MODBUS_USEROBJECT_111_NAME); #endif -#ifdef MODBUS_USEROBJECT_112_NAME +#if defined(MODBUS_USEROBJECT_112_NAME) && MODBUS_NUMB_OF_USEROBJECTS>112 MB_ObjectInit(&MB_DEVID.User[112], MODBUS_USEROBJECT_112_NAME); #endif -#ifdef MODBUS_USEROBJECT_113_NAME +#if defined(MODBUS_USEROBJECT_113_NAME) && MODBUS_NUMB_OF_USEROBJECTS>113 MB_ObjectInit(&MB_DEVID.User[113], MODBUS_USEROBJECT_113_NAME); #endif -#ifdef MODBUS_USEROBJECT_114_NAME +#if defined(MODBUS_USEROBJECT_114_NAME) && MODBUS_NUMB_OF_USEROBJECTS>114 MB_ObjectInit(&MB_DEVID.User[114], MODBUS_USEROBJECT_114_NAME); #endif -#ifdef MODBUS_USEROBJECT_115_NAME +#if defined(MODBUS_USEROBJECT_115_NAME) && MODBUS_NUMB_OF_USEROBJECTS>115 MB_ObjectInit(&MB_DEVID.User[115], MODBUS_USEROBJECT_115_NAME); #endif -#ifdef MODBUS_USEROBJECT_116_NAME +#if defined(MODBUS_USEROBJECT_116_NAME) && MODBUS_NUMB_OF_USEROBJECTS>116 MB_ObjectInit(&MB_DEVID.User[116], MODBUS_USEROBJECT_116_NAME); #endif -#ifdef MODBUS_USEROBJECT_117_NAME +#if defined(MODBUS_USEROBJECT_117_NAME) && MODBUS_NUMB_OF_USEROBJECTS>117 MB_ObjectInit(&MB_DEVID.User[117], MODBUS_USEROBJECT_117_NAME); #endif -#ifdef MODBUS_USEROBJECT_118_NAME +#if defined(MODBUS_USEROBJECT_118_NAME) && MODBUS_NUMB_OF_USEROBJECTS>118 MB_ObjectInit(&MB_DEVID.User[118], MODBUS_USEROBJECT_118_NAME); #endif -#ifdef MODBUS_USEROBJECT_119_NAME +#if defined(MODBUS_USEROBJECT_119_NAME) && MODBUS_NUMB_OF_USEROBJECTS>119 MB_ObjectInit(&MB_DEVID.User[119], MODBUS_USEROBJECT_119_NAME); #endif -#ifdef MODBUS_USEROBJECT_120_NAME +#if defined(MODBUS_USEROBJECT_120_NAME) && MODBUS_NUMB_OF_USEROBJECTS>120 MB_ObjectInit(&MB_DEVID.User[120], MODBUS_USEROBJECT_120_NAME); #endif -#ifdef MODBUS_USEROBJECT_121_NAME +#if defined(MODBUS_USEROBJECT_121_NAME) && MODBUS_NUMB_OF_USEROBJECTS>121 MB_ObjectInit(&MB_DEVID.User[121], MODBUS_USEROBJECT_121_NAME); #endif -#ifdef MODBUS_USEROBJECT_122_NAME +#if defined(MODBUS_USEROBJECT_122_NAME) && MODBUS_NUMB_OF_USEROBJECTS>122 MB_ObjectInit(&MB_DEVID.User[122], MODBUS_USEROBJECT_122_NAME); #endif -#ifdef MODBUS_USEROBJECT_123_NAME +#if defined(MODBUS_USEROBJECT_123_NAME) && MODBUS_NUMB_OF_USEROBJECTS>123 MB_ObjectInit(&MB_DEVID.User[123], MODBUS_USEROBJECT_123_NAME); #endif -#ifdef MODBUS_USEROBJECT_124_NAME +#if defined(MODBUS_USEROBJECT_124_NAME) && MODBUS_NUMB_OF_USEROBJECTS>124 MB_ObjectInit(&MB_DEVID.User[124], MODBUS_USEROBJECT_124_NAME); #endif -#ifdef MODBUS_USEROBJECT_125_NAME +#if defined(MODBUS_USEROBJECT_125_NAME) && MODBUS_NUMB_OF_USEROBJECTS>125 MB_ObjectInit(&MB_DEVID.User[125], MODBUS_USEROBJECT_125_NAME); #endif -#ifdef MODBUS_USEROBJECT_126_NAME +#if defined(MODBUS_USEROBJECT_126_NAME) && MODBUS_NUMB_OF_USEROBJECTS>126 MB_ObjectInit(&MB_DEVID.User[126], MODBUS_USEROBJECT_126_NAME); #endif -#ifdef MODBUS_USEROBJECT_127_NAME +#if defined(MODBUS_USEROBJECT_127_NAME) && MODBUS_NUMB_OF_USEROBJECTS>127 MB_ObjectInit(&MB_DEVID.User[127], MODBUS_USEROBJECT_127_NAME); #endif + } - -#else //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS - -/* Получить количество объектов в сообщении */ - -void MB_WriteSingleObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj) {} -void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj) {} -uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg) {return 0;} -void MB_DeviceInentificationInit(void) {} - -#endif \ No newline at end of file +#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS diff --git a/Src/modbus_diag.c b/Src/modbus_diag.c index e2cd966..2a6967a 100644 --- a/Src/modbus_diag.c +++ b/Src/modbus_diag.c @@ -1,8 +1,8 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_diag.c * @brief Реализация диагностики устройства Modbus -****************************************************************************** +******************************************************************************* * @details Модуль обработки запросов диагностической информации (0x08): - Полная поддержка всех подфункций диагностики согласно спецификации Modbus @@ -74,8 +74,8 @@ int MB_Diagnostics_GetBit(int bit_num) */ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) { - uint16_t sub_function = modbus_msg->DATA[0]; - uint16_t request_data = modbus_msg->DATA[1]; + uint16_t sub_function = modbus_msg->MbData[0]; + uint16_t request_data = modbus_msg->MbData[1]; // Если устройство в режиме Listen Only, отвечаем только на sub-function 0x01 if (MB_DIAG.DeviceMode == MODBUS_LISTEN_ONLY_MODE && sub_function != 0x0001) @@ -87,8 +87,8 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) { case 0x0000: // Return Query Data // Эхо-ответ с теми же данными - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = request_data; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = request_data; modbus_msg->ByteCnt = 4; break; @@ -114,21 +114,21 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) MB_DIAG.Counters.BusCharacterOverrun = 0; } - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = request_data; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = request_data; modbus_msg->ByteCnt = 4; break; case 0x0002: // Return Diagnostic Register - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.DiagnosticRegister; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.DiagnosticRegister; modbus_msg->ByteCnt = 4; break; case 0x0003: // Change ASCII Input Delimiter // В RTU режиме не поддерживается - modbus_msg->Func_Code |= ERR_VALUES_START; - modbus_msg->Except_Code = ILLEGAL_FUNCTION; + modbus_msg->FuncCode |= FC_ERR_VALUES_START; + modbus_msg->Except_Code = ET_ILLEGAL_FUNCTION; return 0; case 0x0004: // Force Listen Only Mode @@ -138,56 +138,56 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) case 0x000A: // Clear Counters and Diagnostic Register MB_DiagnosticsInit(); // Полный сброс - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = 0; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = 0; modbus_msg->ByteCnt = 4; break; case 0x000B: // Return Bus Message Count - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.Counters.BusMessage; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.Counters.BusMessage; modbus_msg->ByteCnt = 4; break; case 0x000C: // Return Bus Communication Error Count - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.Counters.BusCommunicationErr; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.Counters.BusCommunicationErr; modbus_msg->ByteCnt = 4; break; case 0x000D: // Return Bus Exception Error Count - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.Counters.BusExceptionErr; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.Counters.BusExceptionErr; modbus_msg->ByteCnt = 4; break; case 0x000E: // Return Server Message Count - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveMessage; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveMessage; modbus_msg->ByteCnt = 4; break; case 0x000F: // Return Slave No Response Count - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveNoResponse; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveNoResponse; modbus_msg->ByteCnt = 4; break; case 0x0010: // Return Slave NAK Count - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveNAK; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveNAK; modbus_msg->ByteCnt = 4; break; case 0x0011: // Return Slave Busy Count - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveBusy; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveBusy; modbus_msg->ByteCnt = 4; break; case 0x0012: // Return Bus Character Overrun Count - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = MB_DIAG.Counters.BusCharacterOverrun; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = MB_DIAG.Counters.BusCharacterOverrun; modbus_msg->ByteCnt = 4; break; @@ -195,14 +195,14 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) MB_DIAG.Counters.BusCharacterOverrun = 0; // Сбрасываем флаг переполнения в DiagnosticRegister MB_DIAG.DiagnosticRegister &= ~(1<<0); - modbus_msg->DATA[0] = sub_function; - modbus_msg->DATA[1] = 0; + modbus_msg->MbData[0] = sub_function; + modbus_msg->MbData[1] = 0; modbus_msg->ByteCnt = 4; break; default: - modbus_msg->Func_Code |= ERR_VALUES_START; - modbus_msg->Except_Code = ILLEGAL_FUNCTION; + modbus_msg->FuncCode |= FC_ERR_VALUES_START; + modbus_msg->Except_Code = ET_ILLEGAL_FUNCTION; return 0; } @@ -293,20 +293,4 @@ MB_DeviceModeTypeDef MB_GetDeviceMode(void) return MB_DIAG.DeviceMode; } -#else //MODBUS_ENABLE_DIAGNOSTICS - -void MB_DiagnosticsInit(void) {} -int MB_Diagnostics_WriteBit(int bit_num, int bit_state) {return 0;} -int MB_Diagnostics_GetBit(int bit_num) {return 0;} -uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) {return 0;} -void MB_Diagnostics_BusMessageCnt(void) {} -void MB_Diagnostics_CommunicationErrorCnt(void) {} -void MB_Diagnostics_ExceptionErrorCnt(void) {} -void MB_Diagnostics_CharacterOverrunCnt(void) {} -void MB_Diagnostics_SlaveMessageCnt(void) {} -void MB_Diagnostics_SlaveNoResponseCnt(void) {} -void MB_Diagnostics_SlaveNAKCnt(void) {} -void MB_Diagnostics_SlaveBusyCnt(void) {} -MB_DeviceModeTypeDef MB_GetDeviceMode(void) {return MODBUS_NORMAL_MODE;} - -#endif \ No newline at end of file +#endif //MODBUS_ENABLE_DIAGNOSTICS diff --git a/Src/modbus_holdregs.c b/Src/modbus_holdregs.c index 57503cf..88ab7f7 100644 --- a/Src/modbus_holdregs.c +++ b/Src/modbus_holdregs.c @@ -1,22 +1,21 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_holdregs.c * @brief Реализация работы с регистрами хранения Modbus -****************************************************************************** +******************************************************************************* * @details +Модуль для доступа к регистрам внутри программы: +- Функции для доступа к регистрам хранения по глобальным адресам + Модуль обработки команд для holding registers (регистров хранения): - Чтение множественных регистров (0x03) - копирование данных в буфер ответа - Запись одиночного регистра (0x06) - прямая запись значения - Запись множественных регистров (0x10) - пакетная запись из буфера -@section Валидация данных: +@section hvalid Валидация данных: - Проверка соответствия количества байт и регистров -Валидация адресов через MB_DefineRegistersAddress() +- Валидация адресов через MB_DefineRegistersAddress() - Обработка исключений при некорректных запросах - -@section Echo-ответы: -При успешной записи формируется echo-ответ с теми же данными, -что были в запросе (для функций 0x05, 0x06, 0x0F, 0x10). ******************************************************************************/ #include "modbus_inputregs.h" @@ -29,7 +28,7 @@ * @brief Записать регистр хранения по глобальному адресу. * @param Addr Адрес регистра. * @param WriteVal Число для записи. - * @return ExceptionCode Код исключения если регистра по адресу не существует, и NO_ERRORS если все ок. + * @return ExceptionCode Код исключения если регистра по адресу не существует, и ET_NO_ERRORS если все ок. * * @details Позволяет обратиться к любому регистру по его глобальному адрессу. Вне зависимости от того как регистры размещены в памяти. @@ -37,12 +36,12 @@ MB_ExceptionTypeDef MB_Holding_Write_Global(uint16_t Addr, uint16_t WriteVal) { //---------CHECK FOR ERRORS---------- - MB_ExceptionTypeDef Exception = NO_ERRORS; + MB_ExceptionTypeDef Exception = ET_NO_ERRORS; uint16_t *pHoldRegs; //------------WRITE COIL------------- Exception = MB_DefineRegistersAddress(&pHoldRegs, Addr, 1, RegisterType_Holding); - if(Exception == NO_ERRORS) + if(Exception == ET_NO_ERRORS) { *(pHoldRegs) = WriteVal; } @@ -72,7 +71,7 @@ uint16_t MB_Holding_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) if(Exception) // if exception is not given to func fill it *Exception = Exception_tmp; - if(Exception_tmp == NO_ERRORS) + if(Exception_tmp == ET_NO_ERRORS) { return *(pHoldRegs); } @@ -96,7 +95,7 @@ uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg) // get origin address for data uint16_t *pHoldRegs; modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) + if(modbus_msg->Except_Code != ET_NO_ERRORS) return 0; @@ -107,7 +106,7 @@ uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg) int i; for (i = 0; iQnt; i++) { - modbus_msg->DATA[i] = *(pHoldRegs++); + modbus_msg->MbData[i] = *(pHoldRegs++); } return 1; } @@ -123,7 +122,7 @@ uint8_t MB_Process_Write_Single_Reg(RS_MsgTypeDef *modbus_msg) // get origin address for data uint16_t *pHoldRegs; modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) + if(modbus_msg->Except_Code != ET_NO_ERRORS) return 0; //-----------WRITTING REG------------ @@ -148,24 +147,15 @@ uint8_t MB_Process_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg) // get origin address for data uint16_t *pHoldRegs; modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) + if(modbus_msg->Except_Code != ET_NO_ERRORS) return 0; //-----------WRITTING REGS----------- for (int i = 0; iQnt; i++) { - *(pHoldRegs++) = modbus_msg->DATA[i]; + *(pHoldRegs++) = modbus_msg->MbData[i]; } return 1; } - -#else //MODBUS_ENABLE_HOLDINGS - -MB_ExceptionTypeDef MB_Holding_Write_Global(uint16_t Addr, uint16_t WriteVal) {return ILLEGAL_FUNCTION;} -uint16_t MB_Holding_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;} -uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg) {return 0;} -uint8_t MB_Process_Write_Single_Reg(RS_MsgTypeDef *modbus_msg) {return 0;} -uint8_t MB_Process_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg) {return 0;} - -#endif \ No newline at end of file +#endif //MODBUS_ENABLE_HOLDINGS diff --git a/Src/modbus_inputregs.c b/Src/modbus_inputregs.c index 06d8981..41081d6 100644 --- a/Src/modbus_inputregs.c +++ b/Src/modbus_inputregs.c @@ -1,13 +1,18 @@ /** -****************************************************************************** +******************************************************************************* * @file modbus_inputregs.c * @brief Реализация работы с входными регистрами Modbus -****************************************************************************** +******************************************************************************* * @details +Модуль для доступа к регистрам внутри программы: +- Функции для доступа к входным регистрам по глобальным адресам + Модуль обработки команды чтения input registers (0x04): -- Чтение множественных входных регистров -Копирование данных из структур устройства в буфер ответа -- Поддержка знаковых и беззнаковых значений + +@section ivalid Валидация данных: +- Проверка соответствия количества байт и регистров +- Валидация адресов через MB_DefineRegistersAddress() +- Обработка исключений при некорректных запросах ******************************************************************************/ #include "modbus_inputregs.h" @@ -19,7 +24,7 @@ * @brief Записать входной регистр по глобальному адресу. * @param Addr Адрес регистра. * @param WriteVal Число для записи. - * @return ExceptionCode Код исключения если регистра по адресу не существует, и NO_ERRORS если все ок. + * @return ExceptionCode Код исключения если регистра по адресу не существует, и ET_NO_ERRORS если все ок. * * @details Позволяет обратиться к любому регистру по его глобальному адрессу. Вне зависимости от того как регистры размещены в памяти. @@ -27,12 +32,12 @@ MB_ExceptionTypeDef MB_Input_Write_Global(uint16_t Addr, uint16_t WriteVal) { //---------CHECK FOR ERRORS---------- - MB_ExceptionTypeDef Exception = NO_ERRORS; + MB_ExceptionTypeDef Exception = ET_NO_ERRORS; uint16_t *pInRegs; //------------WRITE COIL------------- Exception = MB_DefineRegistersAddress(&pInRegs, Addr, 1, RegisterType_Input); - if(Exception == NO_ERRORS) + if(Exception == ET_NO_ERRORS) { *(pInRegs) = WriteVal; } @@ -62,7 +67,7 @@ uint16_t MB_Input_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) if(Exception) // if exception is not given to func fill it *Exception = Exception_tmp; - if(Exception_tmp == NO_ERRORS) + if(Exception_tmp == ET_NO_ERRORS) { return *(pInRegs); } @@ -85,7 +90,7 @@ uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg) // get origin address for data uint16_t *pInRegs; modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров - if(modbus_msg->Except_Code != NO_ERRORS) + if(modbus_msg->Except_Code != ET_NO_ERRORS) return 0; @@ -97,17 +102,11 @@ uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg) for (i = 0; iQnt; i++) { if(*((int16_t *)pInRegs) > 0) - modbus_msg->DATA[i] = (*pInRegs++); + modbus_msg->MbData[i] = (*pInRegs++); else - modbus_msg->DATA[i] = (*pInRegs++); + modbus_msg->MbData[i] = (*pInRegs++); } return 1; } -#else //MODBUS_ENABLE_INPUTS - -MB_ExceptionTypeDef MB_Input_Write_Global(uint16_t Addr, uint16_t WriteVal) {return ILLEGAL_FUNCTION;} -uint16_t MB_Input_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;} -uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg) {return 0;} - -#endif \ No newline at end of file +#endif //MODBUS_ENABLE_INPUTS diff --git a/Src/modbus_master.c b/Src/modbus_master.c index a6d5709..e5305ad 100644 --- a/Src/modbus_master.c +++ b/Src/modbus_master.c @@ -1,12 +1,22 @@ /** -************************************************************************** -* @file modbus_master.c -* @brief Модуль для реализации мастера MODBUS. -************************************************************************** +******************************************************************************* +* @file modbus_master.c +* @brief Модуль для реализации мастера MODBUS. +******************************************************************************* * @details Файл содержит реализацию функций для работы Modbus в режиме мастера. -@section Функции и макросы +@section mast Функции и макросы +- MB_RespGet_RegisterAll() — Считать все регистра из ответа +- MB_RespGet_RegisterValue() — Считать один регистр из ответа +- MB_RespGet_CoilAll() — Считать все коилы из ответа +- MB_RespGet_CoilState() — Считать один коил из ответа +- MB_RespGet_NumberOfObjects() — Считать количество принятых объектов идентификатора +- MB_RespGet_ObjectById() — Считать объект идентификатора по + его ID +- MB_RespGet_ObjectByIndex() — Считать объект идентификатора по + порядковому номеру в сообщении +- MB_RespGet_Diagnostic() — Считать запрошенный диагностический счетчик - MB_Master_Collect_Message() — Сбор сообщения в режиме мастера - MB_Master_Parse_Message() — Парс сообщения в режиме мастера @@ -16,8 +26,35 @@ #ifdef MODBUS_ENABLE_MASTER +//------------------------------------------------------------------- +//-----------------------------FOR USER------------------------------ /** - * @brief Получить значение регистра из ответа по его адресу + * @brief Получить значение ВСЕХ регистров в ответе + * @param modbus_msg Указатель на структуру сообщения + * @param reg_addr Адрес регистра, значение которого нужно получить + * @param reg_arr Указатель для массив для сохранения значений регистров + * @return количество считанных регистров, 0 - ошибка + */ +int MB_RespGet_RegisterAll(RS_MsgTypeDef *modbus_msg, uint16_t *reg_arr) +{ + if(modbus_msg == NULL || reg_arr == NULL) + return 0; + int read_cnt = 0; + int i = 0; + for(int addr = modbus_msg->Addr; addr < modbus_msg->Addr + modbus_msg->Qnt; addr++) + { + if(MB_RespGet_RegisterValue(modbus_msg, addr, ®_arr[i])) + { + read_cnt++; + } + i++; + } + + return read_cnt; +} + +/** + * @brief Получить значение регистра в ответе по его адресу * @param modbus_msg Указатель на структуру сообщения * @param reg_addr Адрес регистра, значение которого нужно получить * @param reg_value Указатель для значения регистра @@ -29,9 +66,9 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1 return 0; // Проверяем что ответ связан с регистрами - if((modbus_msg->Func_Code != MB_R_DISC_IN) && - (modbus_msg->Func_Code != MB_R_HOLD_REGS) && - (modbus_msg->Func_Code != MB_R_IN_REGS)) + if((modbus_msg->FuncCode != FC_R_DISC_IN) && + (modbus_msg->FuncCode != FC_R_HOLD_REGS) && + (modbus_msg->FuncCode != FC_R_IN_REGS)) { return 0; } @@ -48,13 +85,38 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1 return 0; // Получаем значение регистра - *reg_value = modbus_msg->DATA[reg_index]; + *reg_value = modbus_msg->MbData[reg_index]; return 1; } +/** + * @brief Получить состояние ВСЕХ coil в ответе + * @param modbus_msg Указатель на структуру сообщения + * @param coil_arr Указатель для массив доя сохранения состояний coil (1 - ON, 0 - OFF) + * @return 1 - успех, 0 - ошибка или coil_addr вне диапазона запроса + */ +int MB_RespGet_CoilAll(RS_MsgTypeDef *modbus_msg, int *coil_arr) +{ + if(modbus_msg == NULL || coil_arr == NULL) + return 0; + + int read_cnt = 0; + int i = 0; + for(int addr = modbus_msg->Addr; addr < modbus_msg->Addr + modbus_msg->Qnt; addr++) + { + if(MB_RespGet_CoilState(modbus_msg, addr, &coil_arr[i])) + { + read_cnt++; + } + i++; + } + + return 1; +} + /** * @brief Получить состояние coil в ответе по его адресу * @param modbus_msg Указатель на структуру сообщения @@ -68,7 +130,7 @@ int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coi return 0; // Проверяем что ответ связан с коилами - if(modbus_msg->Func_Code != MB_R_COILS) + if(modbus_msg->FuncCode != FC_R_COILS) { return 0; } @@ -91,9 +153,9 @@ int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coi // Получаем байт и проверяем бит if(bit_index < 8) - *coil_state = (modbus_msg->DATA[data_index] >> (bit_index+8)) & 0x01; + *coil_state = (modbus_msg->MbData[data_index] >> (bit_index+8)) & 0x01; else - *coil_state = (modbus_msg->DATA[data_index] >> bit_index) & 0x01; + *coil_state = ((modbus_msg->MbData[data_index]&0xFF) >> (bit_index-8)) & 0x01; return 1; @@ -112,7 +174,7 @@ int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg) return 0; } // Проверяем что ответ связан с диагностикой - if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + if(modbus_msg->FuncCode != FC_R_DEVICE_ID) { return 0; } @@ -134,12 +196,12 @@ int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_d return 0; // Проверяем что ответ связан с диагностикой - if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + if(modbus_msg->FuncCode != FC_R_DEVICE_ID) { return 0; } - uint8_t *data = (uint8_t*)modbus_msg->DATA; + uint8_t *data = (uint8_t*)modbus_msg->MbData; unsigned ind = 0; for(int i = 0; i < modbus_msg->DevId.NumbOfObj; i++) @@ -185,7 +247,7 @@ int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_ return 0; // Проверяем что ответ связан с диагностикой - if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + if(modbus_msg->FuncCode != FC_R_DEVICE_ID) { return 0; } @@ -193,7 +255,7 @@ int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_ if(index >= modbus_msg->DevId.NumbOfObj) return 0; - uint8_t *data = (uint8_t*)modbus_msg->DATA; + uint8_t *data = (uint8_t*)modbus_msg->MbData; unsigned ind = 0; for(int i = 0; i <= index; i++) @@ -227,7 +289,7 @@ int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_ /** - * @brief Получить данные диагностики из сообщения (DATA[1]) + * @brief Получить данные диагностики из сообщения (MbData[1]) * @param modbus_msg Указатель на структуру сообщения * @param data Указатель куда положить данные * @return 1 - успех, 0 - ошибка @@ -238,18 +300,22 @@ int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data) return 0; // Проверяем что ответ связан с диагностикой - if(modbus_msg->Func_Code != MB_R_DIAGNOSTIC) + if(modbus_msg->FuncCode != FC_R_DIAGNOSTICS) { return 0; } - *data = modbus_msg->DATA[1]; + *data = modbus_msg->MbData[1]; return 1; } + + +//------------------------------------------------------------------- +//-----------------------------INTERNAL------------------------------ /** * @brief Определить размер модбас запроса (МАСТЕР версия). * @param hRS Указатель на хендлер RS. @@ -264,24 +330,24 @@ static int MB_Define_Size_of_Function(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef * // Master mode - calculating response size from slave - if (modbus_msg->Func_Code & ERR_VALUES_START) + if (modbus_msg->FuncCode & FC_ERR_VALUES_START) { // Error response: [Addr][Func|0x80][ExceptCode][CRC] mb_func_size = -1; // Only Exception Code } - else if (modbus_msg->Func_Code == MB_R_DIAGNOSTIC) + else if (modbus_msg->FuncCode == FC_R_DIAGNOSTICS) { // Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO] mb_func_size = 1; } - else if (modbus_msg->Func_Code == MB_R_DEVICE_INFO) + else if (modbus_msg->FuncCode == FC_R_DEVICE_ID) { // Device identifications: variable size, need to read first to determine mb_func_size = 0; // Will be determined after reading header } else { - switch (modbus_msg->Func_Code & ~ERR_VALUES_START) + switch (modbus_msg->FuncCode & ~FC_ERR_VALUES_START) { case 0x01: // Read Coils case 0x02: // Read Discrete Inputs @@ -329,25 +395,30 @@ RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgType modbus_uart_buff[ind++] = modbus_msg->MbAddr; // set function code - modbus_uart_buff[ind++] = modbus_msg->Func_Code; + modbus_uart_buff[ind++] = modbus_msg->FuncCode; - if(modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur + if(modbus_msg->FuncCode < FC_ERR_VALUES_START) // if no error occur { // fill modbus header - if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // device identifications request + if(0) {} +#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS + else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // device identifications request { modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type; modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId; modbus_uart_buff[ind++] = modbus_msg->DevId.NextObjId; } - else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC) +#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS +#ifdef MODBUS_ENABLE_DIAGNOSTICS + else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS) { // Diagnostics: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO] - modbus_uart_buff[ind++] = modbus_msg->DATA[0] >> 8; // Sub-function HI - modbus_uart_buff[ind++] = modbus_msg->DATA[0] & 0xFF; // Sub-function LO - modbus_uart_buff[ind++] = modbus_msg->DATA[1] >> 8; // Data HI - modbus_uart_buff[ind++] = modbus_msg->DATA[1] & 0xFF; // Data LO + modbus_uart_buff[ind++] = modbus_msg->MbData[0] >> 8; // Sub-function HI + modbus_uart_buff[ind++] = modbus_msg->MbData[0] & 0xFF; // Sub-function LO + modbus_uart_buff[ind++] = modbus_msg->MbData[1] >> 8; // Data HI + modbus_uart_buff[ind++] = modbus_msg->MbData[1] & 0xFF; // Data LO } +#endif //MODBUS_ENABLE_DIAGNOSTICS else // classic modbus request { // set address @@ -359,12 +430,12 @@ RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgType modbus_uart_buff[ind++] = modbus_msg->Qnt & 0xFF; // for write multiple functions - if((modbus_msg->Func_Code == 0x0F) || (modbus_msg->Func_Code == 0x10)) + if((modbus_msg->FuncCode == 0x0F) || (modbus_msg->FuncCode == 0x10)) { modbus_uart_buff[ind++] = modbus_msg->ByteCnt; // write data bytes - uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; + uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData; for(int i = 0; i < modbus_msg->ByteCnt; i++) { modbus_uart_buff[ind++] = tmp_data_addr[i]; @@ -379,7 +450,7 @@ RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgType //---------------CRC---------------- //---------[last 2 bytes]---------- uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); - modbus_msg->MB_CRC = CRC_VALUE; + modbus_msg->MbCRC = CRC_VALUE; modbus_uart_buff[ind++] = CRC_VALUE & 0xFF; modbus_uart_buff[ind++] = CRC_VALUE >> 8; @@ -404,15 +475,17 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe modbus_msg->MbAddr = modbus_uart_buff[ind++]; // get function code (check if error response) - modbus_msg->Func_Code = modbus_uart_buff[ind++]; + modbus_msg->FuncCode = modbus_uart_buff[ind++]; - if(modbus_msg->Func_Code & ERR_VALUES_START) // error response + if(modbus_msg->FuncCode & FC_ERR_VALUES_START) // error response { modbus_msg->Except_Code = modbus_uart_buff[ind++]; } - else if(modbus_msg->Func_Code < ERR_VALUES_START) // normal response + else if(modbus_msg->FuncCode < FC_ERR_VALUES_START) // normal response { - if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // device identifications response + if(0) {} +#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS + else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // device identifications response { modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++]; modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++]; @@ -424,7 +497,7 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe modbus_msg->ByteCnt = 0; // Парсинг объектов идентификации устройства - uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; + uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData; int data_index = 0; for(int obj = 0; obj < modbus_msg->DevId.NumbOfObj; obj++) @@ -446,24 +519,27 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe modbus_msg->ByteCnt += (2 + object_length); // ID + длина + данные } } - else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC) +#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS +#ifdef MODBUS_ENABLE_DIAGNOSTICS + else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS) { // Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO] - modbus_msg->DATA[0] = modbus_uart_buff[ind++] << 8; - modbus_msg->DATA[0] |= modbus_uart_buff[ind++]; - modbus_msg->DATA[1] = modbus_uart_buff[ind++] << 8; - modbus_msg->DATA[1] |= modbus_uart_buff[ind++]; + modbus_msg->MbData[0] = modbus_uart_buff[ind++] << 8; + modbus_msg->MbData[0] |= modbus_uart_buff[ind++]; + modbus_msg->MbData[1] = modbus_uart_buff[ind++] << 8; + modbus_msg->MbData[1] |= modbus_uart_buff[ind++]; } +#endif //MODBUS_ENABLE_DIAGNOSTICS else // classic modbus response { // get byte count for read functions - if((modbus_msg->Func_Code == 0x01) || (modbus_msg->Func_Code == 0x02) || - (modbus_msg->Func_Code == 0x03) || (modbus_msg->Func_Code == 0x04)) + if((modbus_msg->FuncCode == 0x01) || (modbus_msg->FuncCode == 0x02) || + (modbus_msg->FuncCode == 0x03) || (modbus_msg->FuncCode == 0x04)) { modbus_msg->ByteCnt = modbus_uart_buff[ind++]; // read data bytes - uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; + uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData; for(int i = 0; i < modbus_msg->ByteCnt; i++) { if(i % 2 == 0) // HI byte @@ -473,8 +549,8 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe } } // for write functions - echo address and quantity - else if((modbus_msg->Func_Code == 0x05) || (modbus_msg->Func_Code == 0x06) || - (modbus_msg->Func_Code == 0x0F) || (modbus_msg->Func_Code == 0x10)) + else if((modbus_msg->FuncCode == 0x05) || (modbus_msg->FuncCode == 0x06) || + (modbus_msg->FuncCode == 0x0F) || (modbus_msg->FuncCode == 0x10)) { modbus_msg->Addr = modbus_uart_buff[ind++] << 8; modbus_msg->Addr |= modbus_uart_buff[ind++]; @@ -488,10 +564,10 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe //---------------CRC---------------- //----------[last 2 bytes]---------- uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); - modbus_msg->MB_CRC = modbus_uart_buff[ind++]; - modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8; + modbus_msg->MbCRC = modbus_uart_buff[ind++]; + modbus_msg->MbCRC |= modbus_uart_buff[ind++] << 8; - if(modbus_msg->MB_CRC != CRC_VALUE) + if(modbus_msg->MbCRC != CRC_VALUE) { TrackerCnt_Err(hmodbus->rs_err); return RS_PARSE_MSG_ERR; @@ -507,58 +583,58 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe /** @brief Сформировать запрос на чтение коилов */ RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) { - RS_MsgTypeDef msg = {slave_addr, MB_R_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; return msg; } /** @brief Сформировать запрос на чтение дискретных регистров */ RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DISC_IN, {0}, start_addr, quantity, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_DISC_IN, {0}, start_addr, quantity, 0, {0}, 0, 0}; return msg; } /** @brief Сформировать запрос на чтение холдинг регистров */ RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) { - RS_MsgTypeDef msg = {slave_addr, MB_R_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; return msg; } /** @brief Сформировать запрос на чтение инпут регистров */ RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) { - RS_MsgTypeDef msg = {slave_addr, MB_R_IN_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_IN_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; return msg; } /** @brief Сформировать запрос на запись одного коила */ RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value) { - RS_MsgTypeDef msg = {slave_addr, MB_W_COIL, {0}, coil_addr, (value ? 0xFF00 : 0x0000), 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_W_COIL, {0}, coil_addr, (value ? 0xFF00 : 0x0000), 0, {0}, 0, 0}; return msg; } /** @brief Сформировать запрос на запись одного регистра */ RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value) { - RS_MsgTypeDef msg = {slave_addr, MB_W_HOLD_REG, {0}, reg_addr, value, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_W_HOLD_REG, {0}, reg_addr, value, 0, {0}, 0, 0}; return msg; } /** @brief Сформировать запрос на запись нескольких регистров */ RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint8_t *coils_data) { - RS_MsgTypeDef msg = {slave_addr, MB_W_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_W_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; // Calculate byte count and prepare data uint8_t byte_count = (quantity + 7) / 8; msg.ByteCnt = byte_count; - // Copy coil data to message DATA array + // Copy coil data to message MbData array for(int i = 0; i < byte_count; i++) { if(i < DATA_SIZE) { - msg.DATA[i] = coils_data[i]; + msg.MbData[i] = coils_data[i]; } } @@ -568,13 +644,13 @@ RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start /** @brief Сформировать запрос на запись нескольких коилов */ RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint16_t *regs_data) { - RS_MsgTypeDef msg = {slave_addr, MB_W_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_W_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; msg.ByteCnt = quantity * 2; // Each register is 2 bytes - // Copy register data to message DATA array + // Copy register data to message MbData array for(int i = 0; i < quantity && i < DATA_SIZE; i++) { - msg.DATA[i] = regs_data[i]; + msg.MbData[i] = regs_data[i]; } return msg; @@ -583,7 +659,7 @@ RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_ //---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ----------- RS_MsgTypeDef MB_REQUEST_DIAGNOSTIC_QUERY(uint8_t slave_addr, uint16_t sub_function, uint16_t data) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DIAGNOSTIC, {0}, 0, 0, 0, {sub_function, data}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_DIAGNOSTICS, {0}, 0, 0, 0, {sub_function, data}, 0, 0}; return msg; } RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr) @@ -654,76 +730,26 @@ RS_MsgTypeDef MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(uint8_t slave_addr) //---------ИДЕНТИФИКАТОРЫ МОДБАС----------- RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_BASIC(uint8_t slave_addr) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x01, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x01, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; return msg; } RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_REGULAR(uint8_t slave_addr) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x02, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x02, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; return msg; } RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_EXTENDED(uint8_t slave_addr) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x03, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x03, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; return msg; } RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t object_id) { - RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; return msg; } - - - - -#else -RS_MsgTypeDef msg_dummy = {0}; - -int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value) {return 0;} -int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state) {return 0;} -int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg) {return 0;} -int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length) {return 0;} -int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length) {return 0;} -int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data) {return 0;} - -RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint8_t *coils_data) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint16_t *regs_data) {return msg_dummy;} - -//---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ----------- -RS_MsgTypeDef MB_REQUEST_DIAGNOSTIC_QUERY(uint8_t slave_addr, uint16_t sub_function, uint16_t data) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RESTART_COMMUNICATIONS(uint8_t slave_addr, uint16_t data) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_DIAGNOSTIC_REGISTER(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_FORCE_LISTEN_ONLY_MODE(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_BUS_MESSAGE_COUNT(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_BUS_COMMUNICATION_ERROR_COUNT(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_EXCEPTION_ERROR_COUNT(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_MESSAGE_COUNT(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NO_RESPONSE_COUNT(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NAK_COUNT(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_BUSY_COUNT(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(uint8_t slave_addr) {return msg_dummy;} - -//---------ИДЕНТИФИКАТОРЫ МОДБАС----------- -RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_BASIC(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_REGULAR(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_EXTENDED(uint8_t slave_addr) {return msg_dummy;} -RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t object_id) {return msg_dummy;} - -RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) {return RS_ERR;} -RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) {return RS_ERR;} -#endif - - - +#endif //MODBUS_ENABLE_MASTER diff --git a/Src/modbus_slave.c b/Src/modbus_slave.c index 982bc1a..77fa6fb 100644 --- a/Src/modbus_slave.c +++ b/Src/modbus_slave.c @@ -1,12 +1,12 @@ /** -************************************************************************** -* @file modbus_slave.c -* @brief Модуль для реализации слейв MODBUS. -************************************************************************** +******************************************************************************* +* @file modbus_slave.c +* @brief Модуль для реализации слейв MODBUS. +******************************************************************************* * @details Файл содержит реализацию функций для работы Modbus в режиме слейва. -@section Функции и макросы +@section slave Функции и макросы - MB_Slave_Response() — Ответ на запрос - MB_Slave_Collect_Message() — Сбор сообщения в режиме слейва. @@ -37,26 +37,26 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod } MB_Diagnostics_SlaveMessageCnt(); - if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing + if(modbus_msg->FuncCode < FC_ERR_VALUES_START)// if no errors after parsing { - switch (modbus_msg->Func_Code) + switch (modbus_msg->FuncCode) { // Read Coils - case MB_R_COILS: + case FC_R_COILS: hmodbus->f.MessageHandled = MB_Process_Read_Coils(hmodbus->pMessagePtr); break; // Read Hodling Registers - case MB_R_HOLD_REGS: + case FC_R_HOLD_REGS: hmodbus->f.MessageHandled = MB_Process_Read_Hold_Regs(hmodbus->pMessagePtr); break; - case MB_R_IN_REGS: + case FC_R_IN_REGS: hmodbus->f.MessageHandled = MB_Process_Read_Input_Regs(hmodbus->pMessagePtr); break; // Write Single Coils - case MB_W_COIL: + case FC_W_COIL: hmodbus->f.MessageHandled = MB_Process_Write_Single_Coil(hmodbus->pMessagePtr); if(hmodbus->f.MessageHandled) { @@ -66,7 +66,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod } break; - case MB_W_HOLD_REG: + case FC_W_HOLD_REG: hmodbus->f.MessageHandled = MB_Process_Write_Single_Reg(hmodbus->pMessagePtr); if(hmodbus->f.MessageHandled) { @@ -77,7 +77,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod break; // Write Multiple Coils - case MB_W_COILS: + case FC_W_COILS: hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Coils(hmodbus->pMessagePtr); if(hmodbus->f.MessageHandled) { @@ -88,7 +88,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod break; // Write Multiple Registers - case MB_W_HOLD_REGS: + case FC_W_HOLD_REGS: hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Regs(hmodbus->pMessagePtr); if(hmodbus->f.MessageHandled) { @@ -98,12 +98,12 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod } break; - case MB_R_DEVICE_INFO: + case FC_R_DEVICE_ID: hmodbus->f.MessageHandled = MB_Process_Read_Device_Identifications(hmodbus->pMessagePtr); break; // Добавить в switch-case после других case: - case MB_R_DIAGNOSTIC: + case FC_R_DIAGNOSTICS: hmodbus->f.MessageHandled = MB_Process_Diagnostics(hmodbus->pMessagePtr); break; @@ -126,7 +126,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod { MB_Diagnostics_ExceptionErrorCnt(); TrackerCnt_Warn(hmodbus->rs_err); - modbus_msg->Func_Code |= ERR_VALUES_START; + modbus_msg->FuncCode |= FC_ERR_VALUES_START; } else { @@ -173,17 +173,29 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD else { //------INFO ABOUT DATA/MESSAGE------ +#ifdef MODBUS_PROTOCOL_TCP + modbus_uart_buff[ind++] = modbus_msg->TransactionID >> 8; + modbus_uart_buff[ind++] = modbus_msg->TransactionID& 0xFF; + + modbus_uart_buff[ind++] = modbus_msg->ProtocolID >> 8; + modbus_uart_buff[ind++] = modbus_msg->ProtocolID& 0xFF; + + modbus_uart_buff[ind++] = modbus_msg->PDULength >> 8; + modbus_uart_buff[ind++] = modbus_msg->PDULength& 0xFF; +#endif //-----------[first bytes]----------- // set ID of message/user modbus_uart_buff[ind++] = modbus_msg->MbAddr; // set dat or err response - modbus_uart_buff[ind++] = modbus_msg->Func_Code; + modbus_uart_buff[ind++] = modbus_msg->FuncCode; - if (modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur + if (modbus_msg->FuncCode < FC_ERR_VALUES_START) // if no error occur { // fill modbus header - if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // devide identifications header + if(0) {} +#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS + else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // devide identifications header { modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type; modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId; @@ -201,7 +213,7 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD //---------------DATA---------------- //-----------[data bytes]------------ - uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; + uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData; for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data { // set data modbus_uart_buff[ind++] = *tmp_data_addr; @@ -209,14 +221,17 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD } } - else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC) +#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS +#ifdef MODBUS_ENABLE_DIAGNOSTICS + else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS) { // Diagnostics special format: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO] - modbus_uart_buff[ind++] = modbus_msg->DATA[0] >> 8; // Sub-function HI - modbus_uart_buff[ind++] = modbus_msg->DATA[0] & 0xFF; // Sub-function LO - modbus_uart_buff[ind++] = modbus_msg->DATA[1] >> 8; // Data HI - modbus_uart_buff[ind++] = modbus_msg->DATA[1] & 0xFF; // Data LO + modbus_uart_buff[ind++] = modbus_msg->MbData[0] >> 8; // Sub-function HI + modbus_uart_buff[ind++] = modbus_msg->MbData[0] & 0xFF; // Sub-function LO + modbus_uart_buff[ind++] = modbus_msg->MbData[1] >> 8; // Data HI + modbus_uart_buff[ind++] = modbus_msg->MbData[1] & 0xFF; // Data LO } +#endif //MODBUS_ENABLE_DIAGNOSTICS else // modbus data header { // set size of received data @@ -230,7 +245,7 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD //---------------DATA---------------- //-----------[data bytes]------------ - uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; + uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData; for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data { // set data if (i%2 == 0) // HI byte @@ -255,12 +270,14 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD //---------------CRC---------------- //---------[last 16 bytes]---------- +#ifndef MODBUS_PROTOCOL_TCP // calc crc of received data uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); // write crc to message structure and modbus-uart buffer - modbus_msg->MB_CRC = CRC_VALUE; + modbus_msg->MbCRC = CRC_VALUE; modbus_uart_buff[ind++] = CRC_VALUE; modbus_uart_buff[ind++] = CRC_VALUE >> 8; +#endif hmodbus->RS_Message_Size = ind; @@ -279,15 +296,15 @@ static int MB_Define_Size_of_Function(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef * RS_StatusTypeDef MB_RES = 0; int mb_func_size = 0; - if (modbus_msg->Func_Code == MB_R_DIAGNOSTIC) + if (modbus_msg->FuncCode == FC_R_DIAGNOSTICS) { mb_func_size = 1; } - else if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) + else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) { mb_func_size = 0; } - else if ((modbus_msg->Func_Code & ~ERR_VALUES_START) < 0x0F) + else if ((modbus_msg->FuncCode & ~FC_ERR_VALUES_START) < 0x0F) { mb_func_size = 1; } @@ -317,6 +334,16 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef hmodbus->f.RX_Continue = 0; int expected_size = 0; //-----INFO ABOUT DATA/MESSAGE------- +#ifdef MODBUS_PROTOCOL_TCP + modbus_msg->TransactionID =modbus_uart_buff[ind++]<<8; + modbus_msg->TransactionID |=modbus_uart_buff[ind++]; + + modbus_msg->ProtocolID =modbus_uart_buff[ind++]<<8; + modbus_msg->ProtocolID |=modbus_uart_buff[ind++]; + + modbus_msg->PDULength =modbus_uart_buff[ind++]<<8; + modbus_msg->PDULength |=modbus_uart_buff[ind++]; +#endif //-----------[first bits]------------ // get ID of message/user if(modbus_uart_buff[ind] != hmodbus->ID) @@ -330,33 +357,38 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef } // get func code - modbus_msg->Func_Code = modbus_uart_buff[ind++]; - if(modbus_msg->Func_Code & ERR_VALUES_START) // явная херня + modbus_msg->FuncCode = modbus_uart_buff[ind++]; + if(modbus_msg->FuncCode & FC_ERR_VALUES_START) // явная херня { MB_Diagnostics_SlaveNAKCnt(); modbus_msg->MbAddr = 0; return RS_SKIP; } - - if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identifications request + + if(0) {} +#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS + else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // if it device identifications request { modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++]; modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++]; modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++]; modbus_msg->ByteCnt = 0; } - else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC) +#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS +#ifdef MODBUS_ENABLE_DIAGNOSTICS + else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS) { - // Diagnostics: читаем 4 байта в DATA[0] и DATA[1] + // Diagnostics: читаем 4 байта в MbData[0] и MbData[1] // Sub-function - modbus_msg->DATA[0] = modbus_uart_buff[ind++] << 8; - modbus_msg->DATA[0] |= modbus_uart_buff[ind++]; + modbus_msg->MbData[0] = modbus_uart_buff[ind++] << 8; + modbus_msg->MbData[0] |= modbus_uart_buff[ind++]; // Data - modbus_msg->DATA[1] = modbus_uart_buff[ind++] << 8; - modbus_msg->DATA[1] |= modbus_uart_buff[ind++]; + modbus_msg->MbData[1] = modbus_uart_buff[ind++] << 8; + modbus_msg->MbData[1] |= modbus_uart_buff[ind++]; modbus_msg->Addr = 0; // не использует Addr modbus_msg->Qnt = 0; // не использует Qnt } +#endif //MODBUS_ENABLE_DIAGNOSTICS else // if its classic modbus request { // get address from CMD @@ -368,7 +400,7 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef modbus_msg->Qnt |= modbus_uart_buff[ind++]; } - if((hmodbus->pMessagePtr->Func_Code == 0x0F) || (hmodbus->pMessagePtr->Func_Code == 0x10)) + if((hmodbus->pMessagePtr->FuncCode == 0x0F) || (hmodbus->pMessagePtr->FuncCode == 0x10)) hmodbus->pMessagePtr->ByteCnt = modbus_uart_buff[ind++]; else hmodbus->pMessagePtr->ByteCnt = 0; @@ -395,11 +427,11 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef if (modbus_msg->ByteCnt > DATA_SIZE*2) { TrackerCnt_Err(hmodbus->rs_err); - modbus_msg->Func_Code |= ERR_VALUES_START; + modbus_msg->FuncCode |= FC_ERR_VALUES_START; MB_Diagnostics_CommunicationErrorCnt(); return RS_PARSE_MSG_ERR; } - uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; + uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData; for(int i = 0; i < modbus_msg->ByteCnt; i++) { // set data if (i%2 == 0) @@ -414,24 +446,22 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef //---------------CRC---------------- //----------[last 16 bits]---------- +#ifndef MODBUS_PROTOCOL_TCP // calc crc of received data uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); // get crc of received data - modbus_msg->MB_CRC = modbus_uart_buff[ind++]; - modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8; + modbus_msg->MbCRC = modbus_uart_buff[ind++]; + modbus_msg->MbCRC |= modbus_uart_buff[ind++] << 8; // compare crc - if (modbus_msg->MB_CRC != CRC_VALUE) + if (modbus_msg->MbCRC != CRC_VALUE) { MB_Diagnostics_CommunicationErrorCnt(); TrackerCnt_Err(hmodbus->rs_err); - modbus_msg->Func_Code |= ERR_VALUES_START; + modbus_msg->FuncCode |= FC_ERR_VALUES_START; } +#endif return RS_OK; } -#else // MODBUS_ENABLE_SLAVE -RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) {return RS_ERR;} -RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) {return RS_ERR;} -RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) {return RS_ERR;} -#endif \ No newline at end of file +#endif //MODBUS_ENABLE_SLAVE diff --git a/Src/rs_message.c b/Src/rs_message.c index a298b97..ed5d801 100644 --- a/Src/rs_message.c +++ b/Src/rs_message.c @@ -1,8 +1,8 @@ /** -****************************************************************************** +******************************************************************************* * @file rs_message.c * @brief Реализация протоколов обмена по RS/UART -****************************************************************************** +******************************************************************************* * @details Модуль реализует асинхронный обмен сообщениями через UART с использованием: - Прерываний по приему/передаче @@ -10,7 +10,7 @@ - Таймаутов через таймер - Двухстадийного приема (заголовок + данные) -@section Архитектура: +@section arch Архитектура: В режиме слейв: - Инициализация приема с сообщения с максимальным размером MSG_SIZE_MAX - При срабатывании прерывания IDLE - обработка полученного сообщения @@ -18,7 +18,7 @@ - Отправка запроса и переход в режим приема сообщения с максимальным размером MSG_SIZE_MAX - При срабатывании прерывания IDLE - обработка полученного ответа -@section Необходимые обработчики: +@section ithandler Необходимые обработчики: - RS_UART_Handler() в UARTx_IRQHandler вместо HAL_UART_IRQHandler() - RS_TIM_Handler() в TIMx_IRQHandler вместо HAL_TIM_IRQHandler() ******************************************************************************/ @@ -323,6 +323,7 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS) { return; } + RS_UART_Handler_ENTER(); //-------------CHECK IDLE FLAG FIRST------------- /* Проверяем флаг IDLE в первую очередь - это гарантирует обработку только после idle */ if(__HAL_UART_GET_FLAG(hRS->huart, UART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(hRS->huart, UART_IT_IDLE)) @@ -362,10 +363,10 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS) } else { + RS_Set_Free(hRS); // освобожднаем RS if(hRS->pCallback) { hRS->pCallback(hRS, hRS->pMessagePtr); // обрабатываем ответ - RS_Set_Free(hRS); // освобожднаем RS } } } @@ -419,6 +420,7 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS) // later, maybe, will be added specific handlers for err } + RS_UART_Handler_EXIT(); } @@ -434,10 +436,11 @@ void RS_TIM_Handler(RS_HandleTypeDef *hRS) { return; } + RS_TIM_Handler_ENTER(); + HAL_TIM_IRQHandler(hRS->htim); RS_Abort(hRS, ABORT_RS); - hRS->RS_STATUS = RS_TIMEOUT; @@ -447,15 +450,16 @@ void RS_TIM_Handler(RS_HandleTypeDef *hRS) if(hRS->sRS_Mode >= RS_MASTER_MODE_START) { // Мастер: коллбек и освобождение для нового запроса + RS_Set_Free(hRS); if(hRS->pCallback) { hRS->pCallback(hRS, hRS->pMessagePtr); // обрабатываем ответ } - RS_Set_Free(hRS); } else { // Слейв: перезапускаем прием RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); } + RS_TIM_Handler_EXIT(); } /** diff --git a/__modbus_config.h b/__modbus_config.h index 53aec6f..9f65c31 100644 --- a/__modbus_config.h +++ b/__modbus_config.h @@ -5,6 +5,7 @@ ****************************************************************************** @addtogroup MODBUS_CONFIGS Modbus configs @ingroup MODBUS +@brief Конфигурация библиотеки @{ ****************************************************************************** * @details @@ -32,7 +33,9 @@ #define MODBUS_PRODUCT_NAME "" #define MODBUS_MODEL_NAME "" #define MODBUS_USER_APPLICATION_NAME "" -#define MODBUS_NUMB_OF_USEROBJECTS 0 + +#define MODBUS_NUMB_OF_USEROBJECTS 0 ///< Количество пользовательских объектов +#define MODBUS_USEROBJECT_0_NAME "" ///< Строка пользовательского идентификатора 0. По аналогии можно определить строки до <=128 USEROBJECT // Периферия (опционально) #define mb_huart huart1 ///< Удобный дефайн для модбасовского uart @@ -51,6 +54,7 @@ #define MODBUS_ENABLE_DEVICE_IDENTIFICATIONS ///< Включить обработку идентификаторы устройства #define MODBUS_ENABLE_DIAGNOSTICS ///< Включить обработку диагностики модбас +//#define MODBUS_PROTOCOL_TCP ///< Включить TCP-протокол, иначе - RTU /** * @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей) @@ -64,4 +68,4 @@ -#endif //_MODBUS_CONFIG_H_ \ No newline at end of file +#endif //_MODBUS_CONFIG_H_ diff --git a/__modbus_data.c b/__modbus_data.c index 7f1b00b..1626ce8 100644 --- a/__modbus_data.c +++ b/__modbus_data.c @@ -29,11 +29,11 @@ * @param Qnt Количество запрашиваемых элементов. * @param R_ARR_ADDR Начальный адресс массива R_ARR. * @param R_ARR_NUMB Количество элементов в массиве R_ARR. - * @return ExceptionCode - ILLEGAL DATA ADRESS если адресс недействителен, и NO_ERRORS если все ок. + * @return ExceptionCode - ET_ILLEGAL_DATA_ADRESS если адресс недействителен, и ET_NO_ERRORS если все ок. * * @details Позволяет определить, принадлежит ли адресс Addr массиву R_ARR: * Если адресс Addr находится в диапазоне адрессов массива R_ARR, то возвращаем NO_ERROR. - * Если адресс Addr находится за пределами адрессов массива R_ARR - ILLEGAL_DATA_ADDRESSю. + * Если адресс Addr находится за пределами адрессов массива R_ARR - ET_ILLEGAL_DATA_ADDRESSю. */ MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB) { @@ -43,14 +43,14 @@ MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16 // if quantity too big return error if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB) { - return ILLEGAL_DATA_ADDRESS; // return exception code + return ET_ILLEGAL_DATA_ADDRESS; // return exception code } // if all ok - return no errors - return NO_ERRORS; + return ET_NO_ERRORS; } // if address isnt from this array return error else - return ILLEGAL_DATA_ADDRESS; // return exception code + return ET_ILLEGAL_DATA_ADDRESS; // return exception code } /** * @brief Define Address Origin for Input/Holding Registers @@ -58,7 +58,7 @@ MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16 * @param Addr Адрес начального регистра. * @param Qnt Количество запрашиваемых регистров. * @param WriteFlag Флаг регистр нужны для чтения или записи. - * @return ExceptionCode Код исключения если есть, и NO_ERRORS если нет. + * @return ExceptionCode Код исключения если есть, и ET_NO_ERRORS если нет. * * @details Определение адреса начального регистра. * @note WriteFlag пока не используется. @@ -68,41 +68,41 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u /* check quantity error */ if (Qnt > DATA_SIZE) { - return ILLEGAL_DATA_VALUE; // return exception code + return ET_ILLEGAL_DATA_VALUE; // return exception code } if(RegisterType == RegisterType_Holding) { // Default holding registers - if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == NO_ERRORS) + if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == ET_NO_ERRORS) { *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр } // if address doesnt match any array - return illegal data address response else { - return ILLEGAL_DATA_ADDRESS; + return ET_ILLEGAL_DATA_ADDRESS; } } else if(RegisterType == RegisterType_Input) { // Default input registers - if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == NO_ERRORS) + if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == ET_NO_ERRORS) { *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr - R_INPUT_ADDR); // указатель на выбранный по Addr регистр } // if address doesnt match any array - return illegal data address response else { - return ILLEGAL_DATA_ADDRESS; + return ET_ILLEGAL_DATA_ADDRESS; } } else { - return ILLEGAL_FUNCTION; + return ET_ILLEGAL_FUNCTION; } // if found requeried array return no err - return NO_ERRORS; // return no errors + return ET_NO_ERRORS; // return no errors } /** * @brief Define Address Origin for coils @@ -111,7 +111,7 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u * @param Qnt Количество запрашиваемых коилов. * @param start_shift Указатель на переменную содержащую сдвиг внутри регистра для начального коила. * @param WriteFlag Флаг коилы нужны для чтения или записи. - * @return ExceptionCode Код исключения если есть, и NO_ERRORS если нет. + * @return ExceptionCode Код исключения если есть, и ET_NO_ERRORS если нет. * * @details Определение адреса начального регистра запрашиваемых коилов. * @note WriteFlag используется для определния регистров GPIO: ODR или IDR. @@ -121,21 +121,21 @@ MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint /* check quantity error */ if (Qnt > 2000) { - return ILLEGAL_DATA_VALUE; // return exception code + return ET_ILLEGAL_DATA_VALUE; // return exception code } // Default coils - if(MB_Check_Address_For_Arr(Addr, Qnt, C_COILS_ADDR, C_COILS_QNT) == NO_ERRORS) + if(MB_Check_Address_For_Arr(Addr, Qnt, C_COILS_ADDR, C_COILS_QNT) == ET_NO_ERRORS) { *pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr - C_COILS_ADDR); // указатель на выбранный по Addr массив коилов } // if address doesnt match any array - return illegal data address response else { - return ILLEGAL_DATA_ADDRESS; + return ET_ILLEGAL_DATA_ADDRESS; } *start_shift = Addr % 16; // set shift to requested coil // if found requeried array return no err - return NO_ERRORS; // return no errors -} \ No newline at end of file + return ET_NO_ERRORS; // return no errors +} diff --git a/__modbus_data.h b/__modbus_data.h index cb6a321..848006b 100644 --- a/__modbus_data.h +++ b/__modbus_data.h @@ -3,7 +3,7 @@ * @file modbus_data.h * @brief Определения структур данных Modbus устройства ****************************************************************************** -@defgroup MODBUS_DATA Modbus Data Tools +@defgroup MODBUS_DATA Modbus Registers Map @ingroup MODBUS @brief Определение карты регистров и коилов ****************************************************************************** @@ -13,7 +13,7 @@ - Input Registers (R/O) - входные регистры - Coils (R/W) - дискретные выходы -@section Базовая настройка под устройство: +@section datinit Базовая настройка под устройство: 1. Настроить диапазоны адресов - @ref R_INPUT_ADDR и @ref R_INPUT_QNT для входных регистров - @ref R_HOLDING_ADDR и @ref R_HOLDING_QNT для регистров хранения @@ -24,7 +24,7 @@ - @ref MB_DataCoilsTypeDef -@section Расширенная настройка под устройство: +@section datexpert Расширенная настройка под устройство: 1. Добавить новый массив с нужными данными. 2. Добавить дефайны для определения его начального адреса и количества элементов 3. Добавить проверку адресов в MB_DefineRegistersAddress/MB_DefineCoilsAddress. @@ -36,14 +36,14 @@ uint16_t user_regs[16]; //... - else if(MB_Check_Address_For_Arr(Addr, Qnt, R_USER_ADDR, R_USER_QNT) == NO_ERRORS) + else if(MB_Check_Address_For_Arr(Addr, Qnt, R_USER_ADDR, R_USER_QNT) == ET_NO_ERRORS) { *pRegs = MB_Set_Register_Ptr(&user_regs, Addr-R_USER_ADDR); // ВАЖНО! // -R_USER_ADDR нужен чтобы взять адрес относительно начала массива } else { - return ILLEGAL_DATA_ADDRESS; + return ET_ILLEGAL_DATA_ADDRESS; } @endcode ******************************************************************************/ @@ -75,11 +75,11 @@ * @addtogroup MODBUS_DATA_RERISTERS_DEFINES Registers structures * @ingroup MODBUS_DATA * @brief Стуруктура регистров (входных и хранения) - @verbatim + @code Для массивов регистров: R__ADDR - модбас адресс первого регистра в массиве R__QNT - количество регистров в массиве - @endverbatim + @endcode * @{ */ @@ -111,12 +111,12 @@ typedef struct //MB_DataInRegsTypeDef * @addtogroup MODBUS_DATA_COILS_DEFINES Coils Structure * @ingroup MODBUS_DATA * @brief Структура коилов - @verbatim + @code Структура дефайна Для массивов коилов: C__ADDR - модбас адресс первого коила в массиве C__QNT - количество коилов в массиве (минимум 16) - @endverbatim + @endcode * @{ */ @@ -156,4 +156,4 @@ extern MB_DataStructureTypeDef MB_DATA; #endif //_MODBUS_DATA_H_ ///////////////////////////////////////////////////////////// -///////////////////////TEMP/OUTDATE/OTHER//////////////////// \ No newline at end of file +///////////////////////TEMP/OUTDATE/OTHER////////////////////