From ecda27792cd074dafd1be78875194e1eb4727e87 Mon Sep 17 00:00:00 2001 From: Razvalyaev Date: Wed, 5 Nov 2025 00:08:41 +0300 Subject: [PATCH] release 0.3.1 doxygen + refactoring --- Inc/modbus.h | 6 +- Inc/modbus_coils.h | 66 ++++++++++++--------- Inc/modbus_core.h | 2 +- Inc/modbus_devid.h | 45 +++++++++----- Inc/modbus_diag.h | 43 +++++++++----- Inc/modbus_holdregs.h | 7 +-- Inc/modbus_inputregs.h | 8 +-- Inc/modbus_master.h | 23 +++++--- Inc/modbus_slave.h | 12 ++-- Inc/rs_message.h | 6 +- README.md | 42 ++++++++++++- Src/modbus.c | 2 +- Src/modbus_coils.c | 34 +++++++---- Src/modbus_devid.c | 36 +++++++++--- Src/modbus_diag.c | 12 +++- Src/modbus_holdregs.c | 4 +- Src/modbus_master.c | 130 ++++++++++++++++++++++------------------- Src/modbus_slave.c | 4 +- Src/rs_message.c | 4 +- __modbus_config.h | 12 ++-- __modbus_data.c | 1 - 21 files changed, 310 insertions(+), 189 deletions(-) diff --git a/Inc/modbus.h b/Inc/modbus.h index e9af0ac..3781189 100644 --- a/Inc/modbus.h +++ b/Inc/modbus.h @@ -14,7 +14,7 @@ Подключает все необходимые модули: -@section Инструкция по подключению +@section init Инструкция по подключению Для корректной работы надо: - Подключить обработчики RS_UART_Handler(), RS_TIM_Handler(), в соответствубщие низкоуровневые прерывания UART_IRQHandler, TIM_IRQHandler вместо HAL'овского обработчика @@ -48,7 +48,7 @@ @endverbatim -@section Подключаемые модули: +@section Подключаемые модули: - rs_message.h - работа с uart - modbus_core.h - базовые определения - modbus_coils.h - работа с дискретными выходами @@ -58,7 +58,7 @@ - modbus_diag.h - диагностика modbus -@section Структура данных Modbus +@section Структура данных Modbus #### Holding/Input Registers: - Регистры — 16-битные слова. Доступ к регистрам осуществляется через указатель. diff --git a/Inc/modbus_coils.h b/Inc/modbus_coils.h index 95f4a14..cecedd6 100644 --- a/Inc/modbus_coils.h +++ b/Inc/modbus_coils.h @@ -5,7 +5,6 @@ ****************************************************************************** @addtogroup MODBUS_COILS Coils Tools @ingroup MODBUS_INTERNAL -@{ ****************************************************************************** * @details Модуль предоставляет функции и макросы для работы с битовыми данными: @@ -14,11 +13,11 @@ - Запись множественных coils (0x0F) - распаковка байтов в биты - Макросы для локального доступа к coils -@section Организация битовых данных: +@section Организация битовых данных: Coils упакованы в 16-битные слова для эффективного использования памяти. Биты нумеруются от младшего к старшему внутри каждого слова. -@section Адресация: +@section Адресация: - Глобальная - абсолютный адрес в пространстве Modbus - Локальная - относительный адрес внутри массива coils - Макросы автоматически вычисляют смещения и маски @@ -31,16 +30,15 @@ Coils упакованы в 16-битные слова для эффективн ///////////////////////////////////////////////////////////////////// ////////////////////---MODBUS FUNCTION DEFINES---//////////////////// -/** @brief Structure for coils operation */ -typedef enum -{ - SET_COIL, - RESET_COIL, - TOOGLE_COIL, -}MB_CoilsOpTypeDef; + //-------------------------------------------------- +/** + * @addtogroup MODBUS_COILS + * @{ + */ + /** * @brief Макрос для установки указателя на регистр, содержащий запрашиваемый коил * @param _parr_ - массив коилов. @@ -77,17 +75,14 @@ typedef enum */ #define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) +/** MODBUS_COILS + * @} + */ + ///////////////////////////////////////////////////////////////////// /////////////////////////---FUNCTIONS---///////////////////////////// -/** -* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS API for Data Access -* @ingroup MODBUS_FUNCTIONS -* @brief Функции для доступа к данным модбас -@{ -*/ - /** * @addtogroup MODBUS_REQ_COILS_API API for Coils @@ -98,7 +93,7 @@ typedef enum * @code * // Пример: Запросили 10 coils с адреса 20, хотим узнать состояние coil 25 * int coil_state; - * if(MB_GetCoilState(&MODBUS_MSG, 25, &coil_state)) + * if(MB_RespGet_CoilState(&MODBUS_MSG, 25, &coil_state)) * { * printf("Coil 25 state: %s\n", coil_state ? "ON" : "OFF"); * } @@ -107,15 +102,16 @@ typedef enum * for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) * { * int state; - * if(MB_GetCoilState(&MODBUS_MSG, addr, &state)) + * if(MB_RespGet_CoilState(&MODBUS_MSG, addr, &state)) * { * printf("Coil %d: %s\n", addr, state ? "ON" : "OFF"); * } * } * @endcode + * @{ */ -int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state); +int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state); /** MODBUS_REQ_COILS_API * @} @@ -123,6 +119,22 @@ int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_sta + +/** + * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS API for Data Access + * @ingroup MODBUS_FUNCTIONS + * @brief Функции для доступа к данным модбас + * @{ + */ + +/** @brief Structure for coils operation */ +typedef enum +{ + SET_COIL, + RESET_COIL, + TOOGLE_COIL, +}MB_CoilsOpTypeDef; + /** * @brief Считать коил по локальному адресу. * @param _parr_ - массив коилов. @@ -131,7 +143,7 @@ int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_sta * * @details Позволяет обратиться к коилу по адресу относительно _arr_. */ -#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_)) +#define MB_Coil_Read_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_)) /** * @brief Выставить коил по локальному адресу. * @param _parr_ Указатель на массив коилов. @@ -139,7 +151,7 @@ int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_sta * * @details Позволяет обратиться к коилу по адресу относительно _arr_. */ -#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_) +#define MB_Coil_Set_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_) /** * @brief Сбросить коил по локальному адресу. * @param _parr_ Указатель на массив коилов. @@ -147,7 +159,7 @@ int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_sta * * @details Позволяет обратиться к коилу по адресу относительно _arr_. */ -#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_)) +#define MB_Coil_Reset_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_)) /** * @brief Переключить состояние коила по локальному адресу. * @param _parr_ Указатель на массив коилов. @@ -155,12 +167,12 @@ int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_sta * * @details Позволяет обратиться к коилу по адресу относительно _arr_. */ -#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_) +#define MB_Coil_Toogle_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_) /* Выставить/сбросить коил по глобальному адресу */ -MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal); +MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal); /* Считать коил по глобальному адресу */ -uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); +uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception); /** MODBUS_DATA_ACCESS_FUNCTIONS * @} @@ -176,7 +188,7 @@ uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg); /* Обработать функцию Write Single Coils (05 - 0x05) */ uint8_t MB_Process_Write_Single_Coil(RS_MsgTypeDef *modbus_msg); /* Обработать функцию Write Multiple Coils (15 - 0x0F) */ -uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg); +uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg); /** MODBUS_CMD_PROCESS_FUNCTIONS * @} diff --git a/Inc/modbus_core.h b/Inc/modbus_core.h index 6a34751..8997477 100644 --- a/Inc/modbus_core.h +++ b/Inc/modbus_core.h @@ -14,7 +14,7 @@ Константы размеров полей Вспомогательные макросы -@section Структура сообщения: +@section Структура сообщения: [ADDR][FUNC][DATA...][CRC] - Адрес: 1 байт - Функция: 1 байт diff --git a/Inc/modbus_devid.h b/Inc/modbus_devid.h index b1c8b2b..c6fe850 100644 --- a/Inc/modbus_devid.h +++ b/Inc/modbus_devid.h @@ -5,7 +5,6 @@ ****************************************************************************** @addtogroup MODBUS_DEVID Device Identifications Tools @ingroup MODBUS_INTERNAL -@{ ****************************************************************************** * @details Модуль реализации функции Read Device Identifications (0x2B): @@ -13,7 +12,7 @@ - Расширенная идентификация (URL, Model, User fields) - Поддержка потоковой передачи больших объектов -@section Объекты идентификации: +@section Объекты идентификации: - VendorName, ProductCode, Revision - обязательные - VendorUrl, ProductName, ModelName - опциональные - User objects - пользовательские поля @@ -27,6 +26,11 @@ ///////////////////////////////////////////////////////////////////// ///////////////---DEVICE IDENTIVICATIONS DEFINES---////////////////// +/** + * @addtogroup MODBUS_DEVID + * @{ + */ + /** @brief Структура для объекта (идентификатора устройства модбас) */ typedef struct { @@ -61,15 +65,20 @@ void MB_DeviceInentificationInit(void); * @brief Инициализация объектов * @details С помозью этого дефайна инициализируются объекты в @ref MB_DeviceInentificationInit */ -#define MB_ObjectInit(_p_obj_, _userstring_) (_p_obj_)->length = sizeof(_userstring_);\ - (_p_obj_)->name = _userstring_; - /** +#define MB_ObjectInit(_p_obj_, _userstring_) \ +(_p_obj_)->length = sizeof(_userstring_);\ +(_p_obj_)->name = _userstring_; +/** * @brief Инициализация пользовательских объектов * @details С помозью этого дефайна инициализируются пользовательские объекты в MB_DeviceInentificationInit */ #define MB_UserObjectInit(_pinfostruct_, _user_numb_) MB_ObjectInit(&(_pinfostruct_)->User[_user_numb_], MODBUS_USEROBJECT##_user_numb_##_NAME) + +/** MODBUS_DEVID +* @} +*/ ////////////////////---MODBUS MESSAGE DEFINES---///////////////////// @@ -80,14 +89,14 @@ void MB_DeviceInentificationInit(void); /** * @addtogroup MODBUS_REQ_DEFID_API API for Device Identifications * @ingroup MODBUS_REQUEST_MSG - * @brief Макросы для чтения идентификторов из ответа в режиме мастер + * @brief API для чтения идентификторов из ответа в режиме мастер * @details Примеры использования: * * @code * // Пример 1: Получить VendorName (ID = 0x00) * uint8_t length; * char vendor_name[64]; - * if(MB_FindObjectById(&MODBUS_MSG, 0x00, vendor_name, &length)) + * if(MB_RespGet_ObjectById(&MODBUS_MSG, 0x00, vendor_name, &length)) * { * // получено * } @@ -96,25 +105,26 @@ void MB_DeviceInentificationInit(void); * uint8_t obj_id, obj_length; * char obj_data[256]; * - * int obj_count = MB_GetNumberOfObjects(&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_GetObjectByIndex(&MODBUS_MSG, i, &obj_id, obj_data, &obj_length)) + * if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, i, &obj_id, obj_data, &obj_length)) * { * // получено * } * } * @endcode + * @{ */ /* Получить количество объектов в сообщении */ -int MB_GetNumberOfObjects(RS_MsgTypeDef *modbus_msg); +int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg); /* Найти объект по ID в сообщении */ -int MB_FindObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length); +int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length); /* Получить объект по индексу в сообщении */ -int MB_GetObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length); +int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length); /** MODBUS_REQ_DEFID_API @@ -122,12 +132,19 @@ int MB_GetObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, c */ +/** + * @addtogroup MODBUS_DEVID + * @{ + */ /* Записать Один Объект Идентификатора в массив данных */ void MB_WriteSingleObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj); /* Записать Массив Объектов Идентификатора в массив данных */ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj); +/** MODBUS_DEVID + * @} + */ //---------PROCESS MODBUS COMMAND FUNCTIONS--------- /** * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS @@ -142,7 +159,3 @@ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg); /////////////////////////---FUNCTIONS---///////////////////////////// #endif //__MODBUS_DEVID_H_ - -/** MODBUS_DEVID - * @} - */ \ No newline at end of file diff --git a/Inc/modbus_diag.h b/Inc/modbus_diag.h index b338c67..86d7ac4 100644 --- a/Inc/modbus_diag.h +++ b/Inc/modbus_diag.h @@ -5,7 +5,6 @@ ****************************************************************************** @addtogroup MODBUS_DIAG Diagnostics Tools @ingroup MODBUS_INTERNAL -@{ ****************************************************************************** * @details Модуль реализации Diagnostics (Serial Line only) (0x08): @@ -13,7 +12,7 @@ - Возможность выставить/сбросить любой бит в диагностическом регистре - Сбор статистики работы устройства - Управление режимами работы -******************************************************************************/ +****************************************** ************************************/ #ifndef __MODBUS_DIAG_H_ #define __MODBUS_DIAG_H_ #include "modbus_core.h" @@ -21,6 +20,11 @@ ///////////////////////////////////////////////////////////////////// /////////////////---DEVICE DIAGNOSTICS DEFINES---//////////////////// +/** + * @addtogroup MODBUS_DIAG + * @{ + */ + /** @brief Режимы работы устройства */ typedef enum { @@ -57,6 +61,10 @@ extern MB_DiagnosticsInfoTypeDef MB_DIAG; /* Инициализация диагностических счетчиков */ void MB_DiagnosticsInit(void); +/** MODBUS_DIAG + * @} + */ + /** * @addtogroup MODBUS_REQ_DIAG_API API for Diagnostics * @ingroup MODBUS_REQUEST_MSG @@ -64,17 +72,20 @@ void MB_DiagnosticsInit(void); * @details Примеры использования: * * @code - * Получить данные диагностики (значение счетчика) + * // Получить данные диагностики (значение счетчика) * uint16_t counter_value; - * if(MB_GetDiagnosticResponse(&MODBUS_MSG, &counter_value)) + * if(MB_RespGet_Diagnostic(&MODBUS_MSG, &counter_value)) * { * printf("Counter value: %d\n", counter_value); * } * @endcode + * @{ */ -int MB_GetDiagnosticResponse(RS_MsgTypeDef *modbus_msg, uint16_t *data); + +int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data); + /** MODBUS_REQ_DIAG_API - * @} + * @} */ @@ -95,6 +106,17 @@ int MB_Diagnostics_WriteBit(int bit_num, int bit_state); int MB_Diagnostics_GetBit(int bit_num); /* Получение текущего режима устройства */ MB_DeviceModeTypeDef MB_GetDeviceMode(void); + + +/* Функции для обновления счетчиков диагностики */ +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); /** MODBUS_CMD_PROCESS_FUNCTIONS * @} */ @@ -113,15 +135,6 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg); */ -/* Функции для обновления счетчиков диагностики */ -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); /////////////////////////---FUNCTIONS---///////////////////////////// diff --git a/Inc/modbus_holdregs.h b/Inc/modbus_holdregs.h index 3a4e253..bfe3b81 100644 --- a/Inc/modbus_holdregs.h +++ b/Inc/modbus_holdregs.h @@ -5,7 +5,6 @@ ****************************************************************************** @addtogroup MODBUS_INS Input Register Tools @ingroup MODBUS_INTERNAL -@{ ****************************************************************************** * @details Модуль обработки команд для регистров хранения (Holding Registers): @@ -13,7 +12,7 @@ - Запись одиночного регистра (0x06) - Запись множества регистров (0x10) -@section Регистры хранения: +@section Регистры хранения: - Read/Write доступ - 16-битные значения (uint16_t) ******************************************************************************/ @@ -42,7 +41,3 @@ uint8_t MB_Process_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg); /////////////////////////---FUNCTIONS---///////////////////////////// #endif //__MODBUS_HOLDREGS_H_ - -/** MODBUS_INS - * @} - */ \ No newline at end of file diff --git a/Inc/modbus_inputregs.h b/Inc/modbus_inputregs.h index 0aba2a6..9fa47e2 100644 --- a/Inc/modbus_inputregs.h +++ b/Inc/modbus_inputregs.h @@ -5,13 +5,12 @@ ****************************************************************************** @addtogroup MODBUS_HOLD Holding Registers Tools @ingroup MODBUS_INTERNAL -@{ ****************************************************************************** * @details Модуль обработки команд для входных регистров (Input Registers): - Чтение множества регистров (0x04) -@section Входные регистры: +@section Входные регистры: - Read-Only доступ - 16-битные значения ******************************************************************************/ @@ -25,7 +24,7 @@ //---------PROCESS MODBUS COMMAND FUNCTIONS--------- /** * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS Internal Process Functions - * @ingroup MODBUS_FUNCTIONS + * @ingroup MODBUS_INTERNAL * @brief Функции обработки запросов модбас @{ */ @@ -38,6 +37,3 @@ uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg); /////////////////////////---FUNCTIONS---///////////////////////////// #endif //__MODBUS_INPUTREGS_H_ -/** MODBUS_HOLD - * @} - */ \ No newline at end of file diff --git a/Inc/modbus_master.h b/Inc/modbus_master.h index 70505ac..1852593 100644 --- a/Inc/modbus_master.h +++ b/Inc/modbus_master.h @@ -5,7 +5,6 @@ ****************************************************************************** @addtogroup MODBUS_MASTER Modbus master funtions @ingroup MODBUS_CMD_PROCESS_FUNCTIONS -@{ ****************************************************************************** * @details Модуль реализации обработки UART сообщение в режиме мастер @@ -24,7 +23,7 @@ * @ingroup MODBUS_FUNCTIONS * @brief Макросы для создания запросов в режиме мастер * @details Примеры использования: - * + * @code * // Чтение 10 holding registers начиная с адреса 0 * RS_MsgTypeDef read_msg = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10); * @@ -36,6 +35,8 @@ * * // Идентификация устройства * RS_MsgTypeDef dev_id_msg = MB_REQUEST_READ_DEVICE_ID_BASIC(1); + * @endcode + * @{ */ //---------КЛАССИЧЕСКИЕ ДАННЫЕ----------- @@ -83,7 +84,7 @@ 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_GetRegisterValue(&MODBUS_MSG, 105, ®_value)) + * if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, ®_value)) * { * printf("Register 105 value: %d\n", reg_value); * } @@ -92,30 +93,34 @@ RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t obj * for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++) * { * uint16_t value; - * if(MB_GetRegisterValue(&MODBUS_MSG, addr, &value)) + * if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value)) * { * printf("Register %d: %d\n", addr, value); * } * } * @endcode + * @{ */ -int MB_GetRegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value); +int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value); /** MODBUS_REQ_REGS_API * @} */ +/** + * @addtogroup MODBUS_MASTER + * @{ + */ /* Сбор сообщения в буфер UART в режиме мастер (фрейм мастера из msg -> uart) */ RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff); /* Парс сообщения в режиме мастер (фрейм слейва из uart -> msg) */ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff); - -#endif //__MODBUS_MASTER_H_ - /** MODBUS_MASTER * @} - */ \ No newline at end of file + */ + +#endif //__MODBUS_MASTER_H_ diff --git a/Inc/modbus_slave.h b/Inc/modbus_slave.h index 810d7ef..89e18aa 100644 --- a/Inc/modbus_slave.h +++ b/Inc/modbus_slave.h @@ -5,7 +5,6 @@ ****************************************************************************** @addtogroup MODBUS_SLAVE Modbus slave funtions @ingroup MODBUS_CMD_PROCESS_FUNCTIONS -@{ ****************************************************************************** * @details Модуль реализации обработки UART сообщение в режиме слейв @@ -19,6 +18,10 @@ #ifdef MODBUS_ENABLE_SLAVE #define MODBUS_MODE_SLAVE 0 #endif +/** + * @addtogroup MODBUS_SLAVE + * @{ + */ /* Ответ на сообщение в режиме слейва */ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg); @@ -27,8 +30,7 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD /* Парс сообщения в режиме слейв (фрейм мастера из uart -> msg) */ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff); -#endif //__MODBUS_SLAVE_H_ - -/** MODBUS_MASTER +/** MODBUS_SLAVE * @} - */ \ No newline at end of file + */ +#endif //__MODBUS_SLAVE_H_ diff --git a/Inc/rs_message.h b/Inc/rs_message.h index 98b9ea5..6fcdc71 100644 --- a/Inc/rs_message.h +++ b/Inc/rs_message.h @@ -11,19 +11,19 @@ Универсальная библиотека для работы с последовательными протоколами (Modbus, Custom) через UART в режиме прерываний с поддержкой таймаутов. -@section Основные возможности: +@section Основные возможности: - Прием/передача в прерываниях - Обработка IDLE линии для определения конца фрейма - Таймауты приема через TIM - Гибкая настройка размера сообщений -@section Использование: +@section Использование: 1. Определить структуру сообщения и размеры буфера 2. Реализовать weak-функции обработки сообщений 3. Добавить вызовы RS_UART_Handler/RS_TIM_Handler в прерывания 4. Инициализировать через RS_Init() и запустить прием RS_Receive_IT() -@section Особенности: +@section Особенности: - Буфер: RS_Buffer[MSG_SIZE_MAX] Общий для приема/передачи - Состояния: отслеживается через флаги в RS_HandleTypeDef - Таймауты: контролируют максимальное время ожидания фрейма diff --git a/README.md b/README.md index 4406ec7..c1f356d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Инструкция по подключению релиза библиотеки `STM Modbus` -Данная библиотека подключается напрямую из Git, как субмодуль. Позволяя при желании обновлять её напрямую через pull. +Данная библиотека подключается напрямую из Git, как субмодуль. Позволяя при желании обновлять её напрямую через git. ## Структура библиотеки @@ -136,7 +136,7 @@ ProjectRoot/ MODBUS_MasterRequest(&hmodbus1, &msg, &callback_func); void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) { - // modbus_msg содержит ответ от устройства + // MB_RespGet_... Чтобы достать нужные данные из ответа } } ``` @@ -188,6 +188,8 @@ ProjectRoot/ 3.6. Доступ к данным в коде + + В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля ```c // Чтение входных регистров uint16_t temp = MB_DATA.InRegs.Temperature; @@ -205,6 +207,42 @@ ProjectRoot/ } ``` + В режиме мастера есть функции для получения информации из ответа `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); + } + ``` + 5. **Обновление библиотеки**: diff --git a/Src/modbus.c b/Src/modbus.c index a39cf08..72ba6eb 100644 --- a/Src/modbus.c +++ b/Src/modbus.c @@ -6,7 +6,7 @@ * @details Файл содержит реализацию функций работы с Modbus. -@section Функции и макросы +@section Функции и макросы ### Инициализация: - MODBUS_FirstInit() — Инициализация Modbus (подключение UART, TIM) diff --git a/Src/modbus_coils.c b/Src/modbus_coils.c index 8c629a9..529a5e1 100644 --- a/Src/modbus_coils.c +++ b/Src/modbus_coils.c @@ -23,7 +23,7 @@ * @details Позволяет обратиться к любому коилу по его глобальному адрессу. Вне зависимости от того как коилы размещены в памяти. */ -MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) +MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) { //---------CHECK FOR ERRORS---------- MB_ExceptionTypeDef Exception = NO_ERRORS; @@ -63,7 +63,7 @@ MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteV * @details Позволяет обратиться к любому коилу по его глобальному адрессу. Вне зависимости от того как коилы размещены в памяти. */ -uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) +uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) { //---------CHECK FOR ERRORS---------- MB_ExceptionTypeDef Exception_tmp; @@ -94,11 +94,17 @@ uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) * @param coil_state Указатель для состояния coil (1 - ON, 0 - OFF) * @return 1 - успех, 0 - ошибка или coil_addr вне диапазона запроса */ -int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state) +int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state) { if(modbus_msg == NULL || coil_state == NULL) return 0; + // Проверяем что ответ связан с коилами + if(modbus_msg->Func_Code != MB_R_COILS) + { + return 0; + } + // Проверяем что coil_addr в пределах запрошенного диапазона if(coil_addr < modbus_msg->Addr || coil_addr >= modbus_msg->Addr + modbus_msg->Qnt) return 0; @@ -108,15 +114,19 @@ int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_sta // Вычисляем байт и бит uint8_t byte_index = coil_index / 8; - uint8_t bit_index = coil_index % 8; + uint8_t data_index = coil_index / 16; + uint8_t bit_index = coil_index % 16; // Проверяем что байт существует в данных if(byte_index >= modbus_msg->ByteCnt) return 0; - // Получаем байт и проверяем бит - uint8_t coil_byte = modbus_msg->DATA[byte_index] & 0xFF; - *coil_state = (coil_byte >> bit_index) & 0x01; + // Получаем байт и проверяем бит + if(bit_index < 8) + *coil_state = (modbus_msg->DATA[data_index] >> (bit_index+8)) & 0x01; + else + *coil_state = (modbus_msg->DATA[data_index] >> bit_index) & 0x01; + return 1; } @@ -211,7 +221,7 @@ uint8_t MB_Process_Write_Single_Coil(RS_MsgTypeDef *modbus_msg) * @return fMessageHandled Статус о результате обработки комманды. * @details Обработка команды Write Multiple Coils. */ -uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) +uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) { //---------CHECK FOR ERRORS---------- if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8)) @@ -274,11 +284,11 @@ uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) #else //MODBUS_ENABLE_COILS -int MB_GetCoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state) {return 0;} -MB_ExceptionTypeDef MB_Write_Coil_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) {return ILLEGAL_FUNCTION;} -uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;} +int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state) {return 0;} +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_Write_Miltuple_Coils(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 diff --git a/Src/modbus_devid.c b/Src/modbus_devid.c index 9d08bfb..7218bee 100644 --- a/Src/modbus_devid.c +++ b/Src/modbus_devid.c @@ -9,7 +9,7 @@ - Поддержка потоковой передачи при большом количестве объектов - Автоматический расчет MoreFollows флагов -@section Потоковая передача: +@section Потоковая передача: При большом количестве объектов идентификация разбивается на несколько сообщений с установкой флага MoreFollows и указанием NextObjId для продолжения чтения в следующем запросе. @@ -26,8 +26,18 @@ MB_DeviceIdentificationsTypeDef MB_DEVID; ///< Глобальная струк * @param modbus_msg Указатель на структуру сообщения * @return int Количество объектов */ -int MB_GetNumberOfObjects(RS_MsgTypeDef *modbus_msg) +int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg) { + if(modbus_msg == NULL) + { + return 0; + } + // Проверяем что ответ связан с диагностикой + if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + { + return 0; + } + return modbus_msg->DevId.NumbOfObj; } @@ -39,11 +49,17 @@ int MB_GetNumberOfObjects(RS_MsgTypeDef *modbus_msg) * @param obj_length Указатель для длины объекта * @return int Найден ли объект (1 - да, 0 - нет) */ -int MB_FindObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length) +int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length) { if((modbus_msg == NULL) || (obj_data == NULL)) return 0; + // Проверяем что ответ связан с диагностикой + if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + { + return 0; + } + uint8_t *data = (uint8_t*)modbus_msg->DATA; unsigned ind = 0; @@ -84,11 +100,17 @@ int MB_FindObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, * @param obj_length Указатель для длины объекта * @return int Успешность получения (1 - получен, 0 - не найден) */ -int MB_GetObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length) +int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length) { if((modbus_msg == NULL) || (obj_data == NULL)) return 0; + // Проверяем что ответ связан с диагностикой + if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) + { + return 0; + } + if(index >= modbus_msg->DevId.NumbOfObj) return 0; @@ -652,9 +674,9 @@ void MB_DeviceInentificationInit(void) #else //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS /* Получить количество объектов в сообщении */ -int MB_GetNumberOfObjects(RS_MsgTypeDef *modbus_msg) {return 0;} -int MB_FindObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length) {return 0;} -int MB_GetObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length) {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;} 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;} diff --git a/Src/modbus_diag.c b/Src/modbus_diag.c index b0d656d..0d18122 100644 --- a/Src/modbus_diag.c +++ b/Src/modbus_diag.c @@ -42,11 +42,19 @@ void MB_DiagnosticsInit(void) * @param data Указатель куда положить данные * @return 1 - успех, 0 - ошибка */ -int MB_GetDiagnosticResponse(RS_MsgTypeDef *modbus_msg, uint16_t *data) +int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data) { if(modbus_msg == NULL || data == NULL) return 0; + // Проверяем что ответ связан с диагностикой + if(modbus_msg->Func_Code != MB_R_DIAGNOSTIC) + { + return 0; + } + + + *data = modbus_msg->DATA[1]; return 1; } @@ -311,7 +319,7 @@ MB_DeviceModeTypeDef MB_GetDeviceMode(void) #else //MODBUS_ENABLE_DIAGNOSTICS void MB_DiagnosticsInit(void) {} -int MB_GetDiagnosticResponse(RS_MsgTypeDef *modbus_msg, uint16_t *data) {return 0;} +int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data) {return 0;} 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;} diff --git a/Src/modbus_holdregs.c b/Src/modbus_holdregs.c index 64760b7..786552a 100644 --- a/Src/modbus_holdregs.c +++ b/Src/modbus_holdregs.c @@ -9,12 +9,12 @@ - Запись одиночного регистра (0x06) - прямая запись значения - Запись множественных регистров (0x10) - пакетная запись из буфера -@section Валидация данных: +@section Валидация данных: - Проверка соответствия количества байт и регистров Валидация адресов через MB_DefineRegistersAddress() - Обработка исключений при некорректных запросах -@section Echo-ответы: +@section Echo-ответы: При успешной записи формируется echo-ответ с теми же данными, что были в запросе (для функций 0x05, 0x06, 0x0F, 0x10). ******************************************************************************/ diff --git a/Src/modbus_master.c b/Src/modbus_master.c index 90cb7dd..d45b68a 100644 --- a/Src/modbus_master.c +++ b/Src/modbus_master.c @@ -6,7 +6,7 @@ * @details Файл содержит реализацию функций для работы Modbus в режиме мастера. -@section Функции и макросы +@section Функции и макросы - MB_Master_Collect_Message() — Сбор сообщения в режиме мастера - MB_Master_Parse_Message() — Парс сообщения в режиме мастера @@ -23,11 +23,19 @@ * @param reg_value Указатель для значения регистра * @return 1 - успех, 0 - ошибка или reg_addr вне диапазона запроса */ -int MB_GetRegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value) +int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value) { if(modbus_msg == NULL || reg_value == NULL) 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)) + { + return 0; + } + // Проверяем что reg_addr в пределах запрошенного диапазона if(reg_addr < modbus_msg->Addr || reg_addr >= modbus_msg->Addr + modbus_msg->Qnt) return 0; @@ -302,173 +310,173 @@ 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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_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}; - - // Calculate byte count and prepare data - uint8_t byte_count = (quantity + 7) / 8; - msg.ByteCnt = byte_count; - - // Copy coil data to message DATA array - for(int i = 0; i < byte_count; i++) { - if(i < DATA_SIZE) { - msg.DATA[i] = coils_data[i]; - } + RS_MsgTypeDef msg = {slave_addr, MB_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 + for(int i = 0; i < byte_count; i++) { + if(i < DATA_SIZE) { + msg.DATA[i] = coils_data[i]; } - - return msg; + } + + return msg; } /** @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}; - - msg.ByteCnt = quantity * 2; // Each register is 2 bytes - - // Copy register data to message DATA array - for(int i = 0; i < quantity && i < DATA_SIZE; i++) { - msg.DATA[i] = regs_data[i]; - } - - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_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 + for(int i = 0; i < quantity && i < DATA_SIZE; i++) { + msg.DATA[i] = regs_data[i]; + } + + return msg; } //---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ----------- 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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DIAGNOSTIC, {0}, 0, 0, 0, {sub_function, data}, 0, 0}; + return msg; } RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0000, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0000, 0x0000); } RS_MsgTypeDef MB_REQUEST_RESTART_COMMUNICATIONS(uint8_t slave_addr, uint16_t data) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0001, data); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0001, data); } RS_MsgTypeDef MB_REQUEST_RETURN_DIAGNOSTIC_REGISTER(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0002, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0002, 0x0000); } RS_MsgTypeDef MB_REQUEST_FORCE_LISTEN_ONLY_MODE(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0004, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0004, 0x0000); } RS_MsgTypeDef MB_REQUEST_CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000A, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000A, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_BUS_MESSAGE_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000B, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000B, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_BUS_COMMUNICATION_ERROR_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000C, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000C, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_EXCEPTION_ERROR_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000D, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000D, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_MESSAGE_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000E, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000E, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NO_RESPONSE_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000F, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x000F, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NAK_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0010, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0010, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_BUSY_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0011, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0011, 0x0000); } RS_MsgTypeDef MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(uint8_t slave_addr) { - return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0012, 0x0000); + return MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, 0x0012, 0x0000); } //---------ИДЕНТИФИКАТОРЫ МОДБАС----------- 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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {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}; - return msg; + RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; + return msg; } @@ -478,7 +486,7 @@ RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t obj #else RS_MsgTypeDef msg_dummy = {0}; -int MB_GetRegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value) {return 0;} +int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value) {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;} diff --git a/Src/modbus_slave.c b/Src/modbus_slave.c index 80311ba..982bc1a 100644 --- a/Src/modbus_slave.c +++ b/Src/modbus_slave.c @@ -6,7 +6,7 @@ * @details Файл содержит реализацию функций для работы Modbus в режиме слейва. -@section Функции и макросы +@section Функции и макросы - MB_Slave_Response() — Ответ на запрос - MB_Slave_Collect_Message() — Сбор сообщения в режиме слейва. @@ -78,7 +78,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod // Write Multiple Coils case MB_W_COILS: - hmodbus->f.MessageHandled = MB_Write_Miltuple_Coils(hmodbus->pMessagePtr); + hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Coils(hmodbus->pMessagePtr); if(hmodbus->f.MessageHandled) { hmodbus->f.DataUpdated = 1; diff --git a/Src/rs_message.c b/Src/rs_message.c index d186530..6572259 100644 --- a/Src/rs_message.c +++ b/Src/rs_message.c @@ -10,7 +10,7 @@ - Таймаутов через таймер - Двухстадийного приема (заголовок + данные) -@section Архитектура: +@section Архитектура: В режиме слейв: - Инициализация приема с сообщения с максимальным размером MSG_SIZE_MAX - При срабатывании прерывания IDLE - обработка полученного сообщения @@ -18,7 +18,7 @@ - Отправка запроса и переход в режим приема сообщения с максимальным размером MSG_SIZE_MAX - При срабатывании прерывания IDLE - обработка полученного ответа -@section Необходимые обработчики: +@section Необходимые обработчики: - RS_UART_Handler() в UARTx_IRQHandler вместо HAL_UART_IRQHandler() - RS_TIM_Handler() в TIMx_IRQHandler вместо HAL_TIM_IRQHandler() ******************************************************************************/ diff --git a/__modbus_config.h b/__modbus_config.h index caa8f3e..12ecb7f 100644 --- a/__modbus_config.h +++ b/__modbus_config.h @@ -19,8 +19,8 @@ #include "stm32f1xx_hal.h" // Общие параметры -#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства -#define MODBUS_TIMEOUT 5000 ///< максимальнйы тайтаут MB в тиках таймера +#define MODBUS_DEVICE_ID 1 ///< Адрес устройства в сети Modbus +#define MODBUS_TIMEOUT 5000 ///< Таймаут в тиках таймера // Строковые идентификаторы устройства #define MODBUS_VENDOR_NAME "NIO-12" @@ -34,19 +34,19 @@ // Периферия (опционально) #define mb_huart huart1 ///< Удобный дефайн для модбасовского uart -#define mb_htim htim2 ///< Удобный дефайн для модбасовского таймера +#define mb_htim htim3 ///< Удобный дефайн для модбасовского таймера //#define RS_EnableReceive() ///< Функция изменения направления передачи на ПРИЕМ для RS-485 //#define RS_EnableTransmit() ///< Функция изменения направления передачи на ПЕРЕДАЧУ для RS-485 // Модули modbus -#define MODBUS_ENABLE_SLAVE ///< Включить обработку МАСТЕР режима -//#define MODBUS_ENABLE_MASTER ///< Включить обработку СЛЕЙВ режима +#define MODBUS_ENABLE_SLAVE ///< Включить обработку СЛЕЙВ режима +#define MODBUS_ENABLE_MASTER ///< Включить обработку МАСТЕР режима #define MODBUS_ENABLE_COILS ///< Включить обработку коилов #define MODBUS_ENABLE_HOLDINGS ///< Включить обработку регистров хранения #define MODBUS_ENABLE_INPUTS ///< Включить обработку входных регистров -#define MODBUS_ENABLE_DEVICE_IDENTIFICATORS ///< Включить обработку идентификаторы устройства +#define MODBUS_ENABLE_DEVICE_IDENTIFICATIONS ///< Включить обработку идентификаторы устройства #define MODBUS_ENABLE_DIAGNOSTICS ///< Включить обработку диагностики модбас diff --git a/__modbus_data.c b/__modbus_data.c index 5537991..7f1b00b 100644 --- a/__modbus_data.c +++ b/__modbus_data.c @@ -23,7 +23,6 @@ #include "modbus_devid.h" - /** * @brief Check is address valid for certain array. * @param Addr Начальный адресс.