Коррекции по синтаксису и doxygen

This commit is contained in:
2025-11-06 19:37:29 +03:00
parent 0264ccd54e
commit 040a5ff654
25 changed files with 460 additions and 362 deletions

View File

@@ -1,15 +1,18 @@
/** /**
************************************************************************** *******************************************************************************
* @file __modbus_compat.h * @file __modbus_compat.h
* @brief Модуль для совместимости библиотеки MODBUS. * @brief Модуль для совместимости библиотеки MODBUS.
************************************************************************** *******************************************************************************
* @details Файл содержит API старых функций, а также заглушки для отключенных модулей: * @details Файл содержит API старых функций, а также заглушки для отключенных модулей:
*************************************************************************/ ******************************************************************************/
#include "modbus.h" #include "modbus_core.h"
/** @addtogroup MODBUS_LEGACY_API Legacy API /** @addtogroup MODBUS_LEGACY_API Legacy API
* @ingroup MODBUS_FUNCTIONS * @ingroup MODBUS_FUNCTIONS
* @brief Старые API функций, сохранённые для обратной совместимости.
* @note Не используйте эти функции в новом коде. Они могут быть удалены в будущих версиях.
* Вместо них используйте функции из основных групп MODBUS API.
* @{ * @{
*/ */

View File

@@ -1,20 +1,22 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus.h * @file modbus.h
* @brief Главный заголовочный файл Modbus библиотеки * @brief Главный заголовочный файл Modbus библиотеки
****************************************************************************** *******************************************************************************
@addtogroup MODBUS Modbus tools @addtogroup MODBUS Modbus tools
****************************************************************************** @brief Библиотека реализующая протокол Modbus
*******************************************************************************
@addtogroup MODBUS_FUNCTIONS Main API for Modbus Library @addtogroup MODBUS_FUNCTIONS Main API for Modbus Library
@ingroup MODBUS @ingroup MODBUS
@brief Публичные функции библиотеки
@{ @{
****************************************************************************** *******************************************************************************
* @details * @details
Объединяющий файл для подключения всей функциональности Modbus. Объединяющий файл для подключения всей функциональности Modbus.
Подключает все необходимые модули: Подключает все необходимые модули:
@section init Инструкция по подключению @section Start Инструкция по подключению
Для корректной работы надо: Для корректной работы надо:
- Подключить обработчики RS_UART_Handler(), RS_TIM_Handler(), в соответствубщие - Подключить обработчики RS_UART_Handler(), RS_TIM_Handler(), в соответствубщие
низкоуровневые прерывания UART_IRQHandler, TIM_IRQHandler вместо HAL'овского обработчика низкоуровневые прерывания UART_IRQHandler, TIM_IRQHandler вместо HAL'овского обработчика
@@ -23,20 +25,20 @@
- Инициализировать хендл мобдас. По умолчанию глобально создается hmodbus1 - Инициализировать хендл мобдас. По умолчанию глобально создается hmodbus1
- После для запуска Modbus: - После для запуска Modbus:
@verbatim @code
//----------------Слейв модбас----------------// //----------------Слейв модбас----------------//
#include "modbus.h" #include "modbus.h"
MODBUS_FirstInit(&hmodbus1, &huart1, &htim3); MODBUS_FirstInit(&hmodbus1, &huart1, &htim3);
MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE);
MODBUS_SlaveStart(&hmodbus1, NULL); MODBUS_SlaveStart(&hmodbus1, NULL);
@endverbatim @endcode
@verbatim @code
//----------------Мастер модбас----------------// //----------------Мастер модбас----------------//
#include "modbus.h" #include "modbus.h"
MODBUS_FirstInit(&hmodbus1, &huart1, &htim3); 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 штук // Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук
RS_MsgTypeDef msg = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10); RS_MsgTypeDef msg = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10);
MODBUS_MasterRequest(&hmodbus1, &msg, &callback_func); MODBUS_MasterRequest(&hmodbus1, &msg, &callback_func);
@@ -56,10 +58,10 @@
} }
} }
} }
@endverbatim @endcode
@section Подключаемые модули: @section modules Подключаемые модули:
- rs_message.h - работа с uart - rs_message.h - работа с uart
- modbus_core.h - базовые определения - modbus_core.h - базовые определения
- modbus_coils.h - работа с дискретными выходами - modbus_coils.h - работа с дискретными выходами
@@ -69,7 +71,7 @@
- modbus_diag.h - диагностика modbus - modbus_diag.h - диагностика modbus
@section Структура данных Modbus @section data Структура данных Modbus
#### Holding/Input Registers: #### Holding/Input Registers:
- Регистры — 16-битные слова. Доступ к регистрам осуществляется через указатель. - Регистры — 16-битные слова. Доступ к регистрам осуществляется через указатель.
@@ -108,11 +110,11 @@
#ifdef MODBUS_ENABLE_MASTER #ifdef MODBUS_ENABLE_MASTER
#define MODBUS_MODE_MASTER 1 #define MODBUS_MODE_MASTER 1 ///< Псевдо-enum: Режим мастер
#endif #endif
#ifdef MODBUS_ENABLE_SLAVE #ifdef MODBUS_ENABLE_SLAVE
#define MODBUS_MODE_SLAVE 0 #define MODBUS_MODE_SLAVE 0 ///< Псевдо-enum: Режим слейв
#endif #endif
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////

View File

@@ -1,23 +1,27 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_coils.h * @file modbus_coils.h
* @brief Работа с коилами Modbus * @brief Работа с коилами Modbus
****************************************************************************** *******************************************************************************
@addtogroup MODBUS_COILS Coils Tools @addtogroup MODBUS_COILS Coils Tools
@ingroup MODBUS_INTERNAL @ingroup MODBUS_INTERNAL
****************************************************************************** @brief Функции для работы с коилами
*******************************************************************************
* @details * @details
Модуль для доступа к coils внутри программы:
- Функции для доступа к coils по глобальным адресам
- Макросы для доступа к coils по локальным адресам
Модуль предоставляет функции и макросы для работы с битовыми данными: Модуль предоставляет функции и макросы для работы с битовыми данными:
- Чтение coils (0x01) Упаковка битов в байты - Чтение coils (0x01) Упаковка битов в байты
- Запись одиночного coil (0x05) Установка/сброс бита - Запись одиночного coil (0x05) Установка/сброс бита
- Запись множественных coils (0x0F) - распаковка байтов в биты - Запись множественных coils (0x0F) - распаковка байтов в биты
- Макросы для локального доступа к coils
@section Организация битовых данных: @section cbits Организация битовых данных:
Coils упакованы в 16-битные слова для эффективного использования памяти. Coils упакованы в 16-битные слова для эффективного использования памяти.
Биты нумеруются от младшего к старшему внутри каждого слова. Биты нумеруются от младшего к старшему внутри каждого слова.
@section Адресация: @section caddr Адресация:
- Глобальная - абсолютный адрес в пространстве Modbus - Глобальная - абсолютный адрес в пространстве Modbus
- Локальная - относительный адрес внутри массива coils - Локальная - относительный адрес внутри массива coils
- Макросы автоматически вычисляют смещения и маски - Макросы автоматически вычисляют смещения и маски
@@ -44,7 +48,7 @@ Coils упакованы в 16-битные слова для эффективн
/** /**
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS API for Data Access * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS API for Data Access
* @ingroup MODBUS_FUNCTIONS * @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 * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
@{ * @{
*/ */
/* Обработать функцию Read Coils (01 - 0x01) */ /* Обработать функцию Read Coils (01 - 0x01) */
uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg); uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg);

View File

@@ -1,12 +1,13 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_core.h * @file modbus_core.h
* @brief Ядро Modbus протокола - определения и структуры * @brief Ядро Modbus протокола - определения и структуры
****************************************************************************** *******************************************************************************
@addtogroup MODBUS_INTERNAL Modbus Internal Tools @addtogroup MODBUS_INTERNAL Modbus Internal Tools
@ingroup MODBUS @ingroup MODBUS
@brief Внутренние штуки библиотеки
@{ @{
****************************************************************************** *******************************************************************************
* @details * @details
Базовые определения для реализации Modbus RTU устройства: Базовые определения для реализации Modbus RTU устройства:
- Структуры сообщений Modbus - Структуры сообщений Modbus
@@ -14,7 +15,7 @@
Константы размеров полей Константы размеров полей
Вспомогательные макросы Вспомогательные макросы
@section Структура сообщения: @section msg Структура сообщения:
[ADDR][FUNC][DATA...][CRC] [ADDR][FUNC][DATA...][CRC]
- Адрес: 1 байт - Адрес: 1 байт
- Функция: 1 байт - Функция: 1 байт
@@ -28,12 +29,13 @@
#include "modbus_config.h" #include "modbus_config.h"
#include "modbus_data.h" #include "modbus_data.h"
#include "__crc_algs.h" #include "__crc_algs.h"
#include "__modbus_compat.h"
/** /**
* @addtogroup MODBUS_MESSAGE_DEFINES Modbus Message Tools * @addtogroup MODBUS_MESSAGE_DEFINES Modbus Message Tools
* @ingroup MODBUS * @ingroup MODBUS
* @brief Определения протокола модбас * @brief Определения протокола модбас
@{ * @{
*/ */
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@@ -93,7 +95,7 @@ typedef enum //MB_FunctonTypeDef
/* COMMANDS */ /* COMMANDS */
// reading // reading
FC_R_COILS = 0x01, ///< Чтение битовых ячеек FC_R_COILS = 0x01, ///< Чтение битовых ячеек
//FC_R_DISC_IN = 0x02, ///< Чтение дискретных входов FC_R_DISC_IN = 0x02, ///< Чтение дискретных входов
#ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS #ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
FC_R_HOLD_REGS = 0x03, ///< Чтение входных регистров FC_R_HOLD_REGS = 0x03, ///< Чтение входных регистров
FC_R_IN_REGS = 0x04, ///< Чтение регистров хранения FC_R_IN_REGS = 0x04, ///< Чтение регистров хранения
@@ -114,7 +116,7 @@ typedef enum //MB_FunctonTypeDef
/* ERRORS */ /* ERRORS */
// error reading // error reading
FC_ERR_R_COILS = FC_R_COILS + FC_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_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_IN_REGS = FC_R_IN_REGS + FC_ERR_VALUES_START, ///< Ошибка чтения регистров хранения
FC_ERR_R_HOLD_REGS = FC_R_HOLD_REGS + FC_ERR_VALUES_START, ///< Ошибка чтения входных регистров FC_ERR_R_HOLD_REGS = FC_R_HOLD_REGS + FC_ERR_VALUES_START, ///< Ошибка чтения входных регистров
@@ -124,8 +126,8 @@ typedef enum //MB_FunctonTypeDef
FC_ERR_W_COILS = FC_W_COILS + FC_ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек FC_ERR_W_COILS = FC_W_COILS + FC_ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
FC_ERR_W_HOLD_REGS = FC_W_HOLD_REGS + FC_ERR_VALUES_START, ///< Ошибка записи нескольких регистров FC_ERR_W_HOLD_REGS = FC_W_HOLD_REGS + FC_ERR_VALUES_START, ///< Ошибка записи нескольких регистров
FC_ERR_R_DIAGNOSTIC = FC_R_DIAGNOSTICS + FC_ERR_VALUES_START, ///< Ошибка чтения диагностической информации устройства FC_ERR_R_DIAGNOSTIC = FC_R_DIAGNOSTICS + FC_ERR_VALUES_START, ///< Ошибка чтения диагностической информации устройства
MB_FC_ERR_R_DEVICE_INFO = FC_R_DEVICE_ID + FC_ERR_VALUES_START, ///< Ошибка чтения информации об устройстве FC_ERR_R_DEVICE_INFO = FC_R_DEVICE_ID + FC_ERR_VALUES_START, ///< Ошибка чтения информации об устройстве
}MB_FunctonTypeDef; }MB_FunctonTypeDef;
/** @brief Enum for MEI func codes */ /** @brief Enum for MEI func codes */
@@ -217,7 +219,7 @@ extern RS_MsgTypeDef MODBUS_MSG;
* @param _parr_ - массив коилов. * @param _parr_ - массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_. * @param _coil_ - Номер коила от начала массива _arr_.
* @note Используется вместе с @ref MB_Set_Coil_Mask * @note Используется вместе с @ref MB_Set_Coil_Mask
@verbatim Пояснение выражений @code Пояснение выражений
- (_coil_/16) - индекс регистра, в котором содержится коил по адресу _coil_ - (_coil_/16) - индекс регистра, в котором содержится коил по адресу _coil_
Визуальный пример: 30 коил будет в 30/16 = 1 регистре (индексация с 0) Визуальный пример: 30 коил будет в 30/16 = 1 регистре (индексация с 0)
@@ -225,14 +227,14 @@ extern RS_MsgTypeDef MODBUS_MSG;
|register[0]----| |register[1]----| |register[0]----| |register[1]----|
|skip this------| |get this-------| |skip this------| |get this-------|
|shift to 14 bit| |shift to 14 bit|
@endverbatim @endcode
*/ */
#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16)) #define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16))
/** /**
* @brief Макрос для установки маски, чтобы выделить запрашиваемый коил из регистра * @brief Макрос для установки маски, чтобы выделить запрашиваемый коил из регистра
* @param _coil_ - Номер коила от начала массива _arr_. * @param _coil_ - Номер коила от начала массива _arr_.
* @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr * @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr
@verbatim Пояснение выражений @code Пояснение выражений
- (16*(_coil_/16) - сколько коилов нужно пропустить. прим. (16*30/16) - первые 16 коилов находятся вне регистра - (16*(_coil_/16) - сколько коилов нужно пропустить. прим. (16*30/16) - первые 16 коилов находятся вне регистра
- _coil_-(16*(_coil_/16)) - сдвинуть бит на место запрашиваемого коила в регистре - _coil_-(16*(_coil_/16)) - сдвинуть бит на место запрашиваемого коила в регистре
@@ -244,7 +246,7 @@ extern RS_MsgTypeDef MODBUS_MSG;
|register[0]----| |register[1]----| |register[0]----| |register[1]----|
|skip this------| |get this-------| |skip this------| |get this-------|
|shift to 14 bit| |shift to 14 bit|
@endverbatim @endcode
*/ */
#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) #define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) ))
@@ -289,7 +291,7 @@ extern RS_MsgTypeDef MODBUS_MSG;
/** /**
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
@{ * @{
*/ */
/* Реализация этих функций лежит в modbus_data.c */ /* Реализация этих функций лежит в modbus_data.c */

View File

@@ -1,18 +1,19 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_devid.h * @file modbus_devid.h
* @brief Идентификаторы устройства Modbus * @brief Идентификаторы устройства Modbus
****************************************************************************** *******************************************************************************
@addtogroup MODBUS_DEVID Device Identifications Tools @addtogroup MODBUS_DEVID Device Identifications Tools
@ingroup MODBUS_INTERNAL @ingroup MODBUS_INTERNAL
****************************************************************************** @brief Функции для работы с идентификаторами устройства
*******************************************************************************
* @details * @details
Модуль реализации функции Read Device Identifications (0x2B): Модуль реализации функции Read Device Identifications (0x2B):
- Базовая идентификация (Vendor, Product, Revision) - Базовая идентификация (Vendor, Product, Revision)
- Расширенная идентификация (URL, Model, User fields) - Расширенная идентификация (URL, Model, User fields)
- Поддержка потоковой передачи больших объектов - Поддержка потоковой передачи больших объектов
@section Объекты идентификации: @section devobj Объекты идентификации:
- VendorName, ProductCode, Revision - обязательные - VendorName, ProductCode, Revision - обязательные
- VendorUrl, ProductName, ModelName - опциональные - VendorUrl, ProductName, ModelName - опциональные
- User objects - пользовательские поля - User objects - пользовательские поля
@@ -108,7 +109,7 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj);
/** /**
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
@{ * @{
*/ */
/* Обработать функцию Read Device Identifications (43/14 - 0x2B/0E) */ /* Обработать функцию Read Device Identifications (43/14 - 0x2B/0E) */

View File

@@ -1,18 +1,19 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_diag.h * @file modbus_diag.h
* @brief Диагностика устройства Modbus * @brief Диагностика устройства Modbus
****************************************************************************** *******************************************************************************
@addtogroup MODBUS_DIAG Diagnostics Tools @addtogroup MODBUS_DIAG Diagnostics Tools
@ingroup MODBUS_INTERNAL @ingroup MODBUS_INTERNAL
****************************************************************************** @brief Функции для работы с диагностикой
*******************************************************************************
* @details * @details
Модуль реализации Diagnostics (Serial Line only) (0x08): Модуль реализации Diagnostics (Serial Line only) (0x08):
- Полная поддержка всех подфункций диагностики - Полная поддержка всех подфункций диагностики
- Возможность выставить/сбросить любой бит в диагностическом регистре - Возможность выставить/сбросить любой бит в диагностическом регистре
- Сбор статистики работы устройства - Сбор статистики работы устройства
- Управление режимами работы - Управление режимами работы
****************************************** ************************************/ ******************************************************************************/
#ifndef __MODBUS_DIAG_H_ #ifndef __MODBUS_DIAG_H_
#define __MODBUS_DIAG_H_ #define __MODBUS_DIAG_H_
#include "modbus_core.h" #include "modbus_core.h"
@@ -100,7 +101,7 @@ void MB_Diagnostics_SlaveBusyCnt(void);
/** /**
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
@{ * @{
*/ */
/* Обработка команды диагностики (0x08) */ /* Обработка команды диагностики (0x08) */

View File

@@ -1,18 +1,22 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_holdregs.h * @file modbus_holdregs.h
* @brief Работа с регистрами хранения Modbus * @brief Работа с регистрами хранения Modbus
****************************************************************************** *******************************************************************************
@addtogroup MODBUS_INS Input Register Tools @addtogroup MODBUS_INS Input Register Tools
@ingroup MODBUS_INTERNAL @ingroup MODBUS_INTERNAL
****************************************************************************** @brief Функции для работы с входными регистрами
*******************************************************************************
* @details * @details
Модуль для доступа к регистрам внутри программы:
- Функции для доступа к регистрам хранения по глобальным адресам
Модуль обработки команд для регистров хранения (Holding Registers): Модуль обработки команд для регистров хранения (Holding Registers):
- Чтение множества регистров (0x03) - Чтение множества регистров (0x03)
- Запись одиночного регистра (0x06) - Запись одиночного регистра (0x06)
- Запись множества регистров (0x10) - Запись множества регистров (0x10)
@section Регистры хранения: @section hold Регистры хранения:
- Read/Write доступ - Read/Write доступ
- 16-битные значения (uint16_t) - 16-битные значения (uint16_t)
******************************************************************************/ ******************************************************************************/
@@ -41,7 +45,7 @@ uint16_t MB_Holding_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception);
/** /**
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
@{ * @{
*/ */
/* Обработать функцию Read Holding Registers (03 - 0x03) */ /* Обработать функцию Read Holding Registers (03 - 0x03) */
uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg); uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg);

View File

@@ -1,16 +1,20 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_inputregs.h * @file modbus_inputregs.h
* @brief Работа с входными регистрами Modbus * @brief Работа с входными регистрами Modbus
****************************************************************************** *******************************************************************************
@addtogroup MODBUS_HOLD Holding Registers Tools @addtogroup MODBUS_HOLD Holding Registers Tools
@ingroup MODBUS_INTERNAL @ingroup MODBUS_INTERNAL
****************************************************************************** @brief Функции для работы с регистрами хранения
*******************************************************************************
* @details * @details
Модуль для доступа к регистрам внутри программы:
- Функции для доступа к входным регистрам по глобальным адресам
Модуль обработки команд для входных регистров (Input Registers): Модуль обработки команд для входных регистров (Input Registers):
- Чтение множества регистров (0x04) - Чтение множества регистров (0x04)
@section Входные регистры: @section in Входные регистры:
- Read-Only доступ - Read-Only доступ
- 16-битные значения - 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 * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS Internal Process Functions
* @ingroup MODBUS_INTERNAL * @ingroup MODBUS_INTERNAL
* @brief Функции обработки запросов модбас * @brief Функции обработки запросов модбас
@{ * @{
*/ */
/* Обработать функцию Read Input Registers (04 - 0x04) */ /* Обработать функцию Read Input Registers (04 - 0x04) */
uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg); uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg);

View File

@@ -1,13 +1,14 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_master.h * @file modbus_master.h
* @brief Главный заголовочный файл Modbus библиотеки * @brief Главный заголовочный файл Modbus библиотеки
****************************************************************************** *******************************************************************************
@addtogroup MODBUS_MASTER Modbus master funtions @addtogroup MODBUS_MASTER Modbus master funtions
@ingroup MODBUS_CMD_PROCESS_FUNCTIONS @ingroup MODBUS_CMD_PROCESS_FUNCTIONS
****************************************************************************** @brief Функции для работы в режиме Master
*******************************************************************************
* @details * @details
Модуль реализации обработки UART сообщение в режиме мастер Модуль реализации Modbus в режиме мастер
******************************************************************************/ ******************************************************************************/
#ifndef __MODBUS_MASTER_H_ #ifndef __MODBUS_MASTER_H_
#define __MODBUS_MASTER_H_ #define __MODBUS_MASTER_H_
@@ -17,7 +18,7 @@
/** /**
* @addtogroup MODBUS_REQUEST_MSG API for Master Requests * @addtogroup MODBUS_REQUEST_MSG API for Master Requests
* @ingroup MODBUS_FUNCTIONS * @ingroup MODBUS_FUNCTIONS
* @brief Макросы для создания запросов в режиме мастер * @brief API для формирования фрейма-запроса в режиме мастер
* @details Примеры использования: * @details Примеры использования:
* @code * @code
* // Чтение 10 holding registers начиная с адреса 0 * // Чтение 10 holding registers начиная с адреса 0
@@ -80,24 +81,20 @@ RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t obj
* @code * @code
* // Пример: Запросили 10 регистров с адреса 100, хотим получить значение регистра 105 * // Пример: Запросили 10 регистров с адреса 100, хотим получить значение регистра 105
* uint16_t reg_value; * uint16_t reg_value;
* if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, &reg_value)) * if(MB_RespGet_RegisterValue(modbus_msg, 105, &reg_value))
* { * {
* printf("Register 105 value: %d\n", reg_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 reg_value[125];
* { * MB_RespGet_RegisterAll(modbus_msg)
* uint16_t value;
* if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value))
* {
* printf("Register %d: %d\n", addr, value);
* }
* }
* @endcode * @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); 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 * @code
* // Пример: Запросили 10 coils с адреса 20, хотим узнать состояние coil 25 * // Пример: Запросили 10 coils с адреса 20, хотим узнать состояние coil 25
* int coil_state; * 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"); * 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++) * for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++)
* { * {
* int state; * 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"); * 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 * @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); int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state);
/** MODBUS_REQ_COILS_API /** 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) * // Пример 1: Получить VendorName (ID = 0x00)
* uint8_t length; * uint8_t length;
* char vendor_name[64]; * 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; * uint8_t obj_id, obj_length;
* char obj_data[256]; * 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); * printf("Total objects: %d\n", obj_count);
* *
* for(int i = 0; i < obj_count; i++) * 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 * @code
* // Получить данные диагностики (значение счетчика) * // Получить данные диагностики (значение счетчика)
* uint16_t counter_value; * 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); * 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); int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data);
/** MODBUS_REQ_DIAG_API /** MODBUS_REQ_DIAG_API

View File

@@ -1,13 +1,14 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_slave.h * @file modbus_slave.h
* @brief Главный заголовочный файл Modbus библиотеки * @brief Главный заголовочный файл Modbus библиотеки
****************************************************************************** *******************************************************************************
@addtogroup MODBUS_SLAVE Modbus slave funtions @addtogroup MODBUS_SLAVE Modbus slave funtions
@ingroup MODBUS_CMD_PROCESS_FUNCTIONS @ingroup MODBUS_CMD_PROCESS_FUNCTIONS
****************************************************************************** @brief Функции для работы в режиме Slave
*******************************************************************************
* @details * @details
Модуль реализации обработки UART сообщение в режиме слейв Модуль реализации Modbus в режиме слейв
******************************************************************************/ ******************************************************************************/
#ifndef __MODBUS_SLAVE_H_ #ifndef __MODBUS_SLAVE_H_
#define __MODBUS_SLAVE_H_ #define __MODBUS_SLAVE_H_

View File

@@ -1,29 +1,29 @@
/** /**
****************************************************************************** *******************************************************************************
* @file rs_message.h * @file rs_message.h
* @brief Библиотека обмена сообщениями по RS-интерфейсу * @brief Библиотека обмена сообщениями по RS-интерфейсу
****************************************************************************** *******************************************************************************
@defgroup RS_TOOLS RS Tools @defgroup RS_TOOLS RS Tools
@brief Всякое для работы по UART/RS @brief Всякое для работы по UART/RS
@{ @{
****************************************************************************** *******************************************************************************
* @details * @details
Универсальная библиотека для работы с последовательными протоколами (Modbus, Custom) Универсальная библиотека для работы с последовательными протоколами (Modbus, Custom)
через UART в режиме прерываний с поддержкой таймаутов. через UART в режиме прерываний с поддержкой таймаутов.
@section Основные возможности: @section posibility Основные возможности:
- Прием/передача в прерываниях - Прием/передача в прерываниях
- Обработка IDLE линии для определения конца фрейма - Обработка IDLE линии для определения конца фрейма
- Таймауты приема через TIM - Таймауты приема через TIM
- Гибкая настройка размера сообщений - Гибкая настройка размера сообщений
@section Использование: @section usage Использование:
1. Определить структуру сообщения и размеры буфера 1. Определить структуру сообщения и размеры буфера
2. Реализовать weak-функции обработки сообщений 2. Реализовать weak-функции обработки сообщений
3. Добавить вызовы RS_UART_Handler/RS_TIM_Handler в прерывания 3. Добавить вызовы RS_UART_Handler/RS_TIM_Handler в прерывания
4. Инициализировать через RS_Init() и запустить прием RS_Receive_IT() 4. Инициализировать через RS_Init() и запустить прием RS_Receive_IT()
@section Особенности: @section features Особенности:
- Буфер: RS_Buffer[MSG_SIZE_MAX] Общий для приема/передачи - Буфер: RS_Buffer[MSG_SIZE_MAX] Общий для приема/передачи
- Состояния: отслеживается через флаги в RS_HandleTypeDef - Состояния: отслеживается через флаги в RS_HandleTypeDef
- Таймауты: контролируют максимальное время ожидания фрейма - Таймауты: контролируют максимальное время ожидания фрейма
@@ -89,6 +89,7 @@
/** /**
* @addtogroup RS_DEBUG Tools for debug RS/UART/TIM * @addtogroup RS_DEBUG Tools for debug RS/UART/TIM
* @ingroup RS_TOOLS * @ingroup RS_TOOLS
* @brief Дефайны для отладки периферии
* @{ * @{
*/ */

413
README.md
View File

@@ -6,40 +6,40 @@
*Note: Файлы начинающиеся с `__` и которых **нет** в этом дереве являются **внутренними/непротестированными/недокументированными*** *Note: Файлы начинающиеся с `__` и которых **нет** в этом дереве являются **внутренними/непротестированными/недокументированными***
``` ```
Modbus/ Иерархия модулей: Modbus/ Иерархия модулей:
│ inc/ modbus │ inc/ modbus
│ ├── modbus.h # Главный заголовочный файл modbus_slave │ ├── modbus.h # Главный заголовочный файл modbus_slave
│ ├── modbus_core.h # Базовые определения и структуры modbus_master │ ├── modbus_core.h # Базовые определения и структуры modbus_master
│ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils │ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils
│ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs │ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs
│ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs │ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs
│ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid │ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid
│ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag │ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag
├── src/ └── rs_message ├── src/ └── rs_message
│ ├── modbus.c # Основная логика Modbus │ ├── modbus.c # Основная логика Modbus
│ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро) │ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро)
│ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config │ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config
│ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data │ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data
│ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs │ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs
│ ├── modbus_inputregs.c # Реализация входных регистров │ ├── modbus_inputregs.c # Реализация входных регистров
│ ├── modbus_devid.c # Реализация идентификации устройства │ ├── modbus_devid.c # Реализация идентификации устройства
│ ├── modbus_data.c # Функции доступа к данным │ ├── modbus_data.c # Функции доступа к данным
│ └── rs_message.c # Реализация драйвера RS │ └── rs_message.c # Реализация драйвера RS
├── __modbus_config.h # Конфигурация Modbus (надо заменить) ├── __modbus_config.h # Конфигурация Modbus (надо заменить)
├── __modbus_data.h # Структуры данных (надо заменить) ├── __modbus_data.h # Структуры данных (надо заменить)
└── __modbus_data.c # Функции доступа (надо заменить) └── __modbus_data.c # Функции доступа (надо заменить)
``` ```
## Инструкция по подключению ## Инструкция по подключению
1. **Склонируйте субмодуль** в ваш проект: ### 1. **Склонируйте субмодуль** в ваш проект:
```bash ```bash
git submodule add https://git.arktika.cyou/set506/STM32_Modbus path/to/Modbus git submodule add https://git.arktika.cyou/set506/STM32_Modbus path/to/Modbus
git submodule update --init --recursive git submodule update --init --recursive
``` ```
2. **Скопируйте файлы конфигурации** в отдельную папку в вашем проекте (вне субмодуля) и удалите `__` из имени файлов: ### 2. **Скопируйте файлы конфигурации** в отдельную папку в вашем проекте (вне субмодуля) и удалите `__` из имени файлов:
``` ```
ProjectRoot/ ProjectRoot/
@@ -47,219 +47,210 @@ ProjectRoot/
│ ├── modbus_config.h # скопировать из __modbus_config.h │ ├── modbus_config.h # скопировать из __modbus_config.h
│ ├── modbus_data.h # скопировать из __modbus_data.h │ ├── modbus_data.h # скопировать из __modbus_data.h
│ └── modbus_data.c # скопировать из __modbus_data.c │ └── modbus_data.c # скопировать из __modbus_data.c
└── Modbus/ # Субмодуль └── Modbus/ # Субмодуль
``` ```
3. **Настройте конфигурацию** под ваш проект: ### 3. **Настройте конфигурацию** под ваш проект:
#### 3.1. Настройка периферии
3.1. Настройка периферии
- **UART**: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1 - **UART**: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1
- **TIM**: Настройте таймер для генерации прерываний (например, 1ms tick) - **TIM**: Настройте таймер для генерации прерываний (например, 1ms tick)
- **Включите прерывания** для UART и TIM - **Включите прерывания** для UART и TIM
3.2. Подключение обработчиков прерываний #### 3.2. Подключение обработчиков прерываний
Подключите обработчики прерываний **UART** и **TIM** в свои IRQ обработчики ***вместо*** HAL-обработчиков: Подключите обработчики прерываний **UART** и **TIM** в свои IRQ обработчики ***вместо*** HAL-обработчиков:
```c ```c
#include "modbus.h" #include "modbus.h"
void USARTx_IRQHandler(void) void USARTx_IRQHandler(void)
{ {
RS_UART_Handler(&hmodbus1); RS_UART_Handler(&hmodbus1);
return; return;
HAL_UART_IRQHandler(&huart); HAL_UART_IRQHandler(&huart);
} }
void TIMx_IRQHandler(void) void TIMx_IRQHandler(void)
{ {
RS_TIM_Handler(&hmodbus1); RS_TIM_Handler(&hmodbus1);
return; return;
HAL_TIM_IRQHandler(&htim); HAL_TIM_IRQHandler(&htim);
} }
``` ```
#### 3.3. В `modbus_config.h` укажите параметры устройства
3.3. В `modbus_config.h` укажите параметры устройства #### 3.4. Инициализация в коде
Чтобы настроить Slave-режим `main()` после инициализации HAL:
3.4. Инициализация в коде ```c
#include "modbus.h"
Чтобы настроить Slave-режим `main()` после инициализации HAL:
```c int main(void)
#include "modbus.h" {
// Инициализация 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) ```c
{ #include "modbus.h"
// Инициализация HAL // Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук
HAL_Init(); RS_MsgTypeDef read_hold_cmd = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10);
SystemClock_Config(); // коллбек, вызовется при получении ответа от слейва
MX_GPIO_Init(); read_hold[10];
MX_USART1_UART_Init(); void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
MX_TIM3_Init(); {
// MB_RespGet_... Чтобы достать нужные данные из ответа
// Инициализация Modbus if(hmodbus->RS_STATUS == RS_OK)
MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim); {
MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE); for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++)
{
// Запуск приема Modbus uint16_t value;
MODBUS_SlaveStart(&hmodbus1, NULL); if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value))
{
while (1) 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 В `modbus_data.h` настройте регистры и coils под ваше устройство:
#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);
} **Input Registers (только чтение)**
``` ```c
3.5. Настройка карты данных 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 (только чтение)** #define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров
```c #define R_HOLDING_QNT 3 // Количество Holding регистров
typedef struct ```
{ **Coils (1-битные)**
uint16_t Temperature; // Адрес 0 ```c
uint16_t Humidity; // Адрес 1 typedef struct
uint16_t Pressure; // Адрес 2 {
uint16_t Voltage; // Адрес 3 unsigned Relay1 : 1; // Адрес 0
} MB_DataInRegsTypeDef; 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 C_COILS_ADDR 0 // Начальный адрес Coils
#define R_INPUT_QNT 4 // Количество Input регистров #define C_COILS_QNT 4 // Количество Coils
``` ```
#### 3.6. Доступ к данным в коде
**Holding Registers (чтение/запись)** В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля
```c ```c
typedef struct // Чтение входных регистров
{ uint16_t temp = MB_DATA.InRegs.Temperature;
uint16_t SetpointTemp; // Адрес 0
uint16_t SetpointHumidity; // Адрес 1
uint16_t ControlMode; // Адрес 2
} MB_DataHoldRegsTypeDef;
#define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров // Запись в регистры хранения
#define R_HOLDING_QNT 3 // Количество Holding регистров MB_DATA.HoldRegs.SetpointTemp = 2500;
```
**Coils (1-битные)** // Управление coils
```c MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить Relay1
typedef struct MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить Relay2
{
unsigned Relay1 : 1; // Адрес 0
unsigned Relay2 : 1; // Адрес 1
unsigned Pump : 1; // Адрес 2
unsigned Heater : 1; // Адрес 3
unsigned reserved : 12; // Резерв (выравнивание до 16 бит)
} MB_DataCoilsTypeDef;
#define C_COILS_ADDR 0 // Начальный адрес Coils // Чтение coil
#define C_COILS_QNT 4 // Количество Coils if (MB_Coil_Read_Local(&MB_DATA.Coils, 2)) {
``` // Pump включен
}
```
В режиме мастера есть функции для получения информации из ответа `MB_RespGet_...()`
```c
// Чтение регистров: Получить запрошенные регистры
uint16_t value;
if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, &reg_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. Доступ к данным в коде uint8_t obj_id, obj_length;
char obj_data[64];
if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, 0x00, &obj_id, obj_data, &obj_length))
В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля {
```c printf("First object - ID: 0x%02X, Data: %s\n", obj_id, obj_data);
// Чтение входных регистров }
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, &reg_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. **Обновление библиотеки**: ### 5. **Обновление библиотеки**:
После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся: После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся:
```bash ```bash

View File

@@ -1,8 +1,7 @@
/** /**
************************************************************************** *******************************************************************************
* @file __modbus_compat.c * @file __modbus_compat.c
* @brief Модуль для совместимости библиотеки MODBUS. * @brief Модуль для совместимости библиотеки MODBUS.
************************************************************************** *******************************************************************************
* @details Файл содержит API старых функций, а также заглушки для отключенных модулей:
******************************************************************************/ ******************************************************************************/
#include "modbus.h" #include "modbus.h"

View File

@@ -1,12 +1,12 @@
/** /**
************************************************************************** *******************************************************************************
* @file modbus.c * @file modbus.c
* @brief Модуль для реализации MODBUS. * @brief Модуль для реализации MODBUS.
************************************************************************** *******************************************************************************
* @details * @details
Файл содержит реализацию функций работы с Modbus. Файл содержит реализацию функций работы с Modbus.
@section Функции и макросы @section mbapi Функции и макросы
### Инициализация: ### Инициализация:
- MODBUS_FirstInit() — Инициализация Modbus (подключение UART, TIM) - MODBUS_FirstInit() — Инициализация Modbus (подключение UART, TIM)
@@ -164,9 +164,15 @@ HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef
return HAL_ERROR; return HAL_ERROR;
} }
//-------------------------------------------------------------------
//-----------------------------INTERNAL------------------------------
/**
* @brief Дефолтный коллбек для мастера.
* @param hmodbus Указатель на хендлер RS
* @param modbus_msg Указатель на структуру сообщения
* @details В этот коллбек попадут все запросы, с NULL-коллбеком
*/
static void MB_DefaultCallback(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) static void MB_DefaultCallback(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
{ {
__NOP(); __NOP();

View File

@@ -1,14 +1,22 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_coils.c * @file modbus_coils.c
* @brief Реализация работы с коилами Modbus * @brief Реализация работы с коилами Modbus
****************************************************************************** *******************************************************************************
* @details * @details
Модуль для доступа к coils внутри программы:
- Функции для доступа к coils по глобальным адресам
- Макросы для доступа к coils по локальным адресам
Модуль обработки команд для coils (битовых данных): Модуль обработки команд для coils (битовых данных):
- Чтение coils (0x01) - упаковка битов в байты для передачи - Чтение coils (0x01) - упаковка битов в байты для передачи
- Запись одиночного coil (0x05) - установка/сброс бита - Запись одиночного coil (0x05) - установка/сброс бита
- Запись множественных coils (0x0F) - распаковка битов из байтов - Запись множественных coils (0x0F) - распаковка битов из байтов
@section cvalid Валидация данных:
- Проверка соответствия количества байт и регистров
- Валидация адресов через MB_DefineRegistersAddress()
- Обработка исключений при некорректных запросах
******************************************************************************/ ******************************************************************************/
#include "modbus_coils.h" #include "modbus_coils.h"

View File

@@ -1,8 +1,8 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_core.c * @file modbus_core.c
* @brief Базовая реализация ядра Modbus * @brief Базовая реализация ядра Modbus
****************************************************************************** *******************************************************************************
* @details * @details
В текущей реализации этот файл служит заглушкой для будущего расширения В текущей реализации этот файл служит заглушкой для будущего расширения
функциональности ядра Modbus протокола. функциональности ядра Modbus протокола.

View File

@@ -1,15 +1,15 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_devid.c * @file modbus_devid.c
* @brief Реализация идентификаторов устройства Modbus * @brief Реализация идентификаторов устройства Modbus
****************************************************************************** *******************************************************************************
* @details * @details
Модуль обработки запросов идентификации устройства через MEI-тип 0x0E: Модуль обработки запросов идентификации устройства через MEI-тип 0x0E:
- Формирование иерархии объектов идентификации - Формирование иерархии объектов идентификации
- Поддержка потоковой передачи при большом количестве объектов - Поддержка потоковой передачи при большом количестве объектов
- Автоматический расчет MoreFollows флагов - Автоматический расчет MoreFollows флагов
@section Потоковая передача: @section stream Потоковая передача:
При большом количестве объектов идентификация разбивается на несколько При большом количестве объектов идентификация разбивается на несколько
сообщений с установкой флага MoreFollows и указанием NextObjId для сообщений с установкой флага MoreFollows и указанием NextObjId для
продолжения чтения в следующем запросе. продолжения чтения в следующем запросе.

View File

@@ -1,8 +1,8 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_diag.c * @file modbus_diag.c
* @brief Реализация диагностики устройства Modbus * @brief Реализация диагностики устройства Modbus
****************************************************************************** *******************************************************************************
* @details * @details
Модуль обработки запросов диагностической информации (0x08): Модуль обработки запросов диагностической информации (0x08):
- Полная поддержка всех подфункций диагностики согласно спецификации Modbus - Полная поддержка всех подфункций диагностики согласно спецификации Modbus

View File

@@ -1,22 +1,21 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_holdregs.c * @file modbus_holdregs.c
* @brief Реализация работы с регистрами хранения Modbus * @brief Реализация работы с регистрами хранения Modbus
****************************************************************************** *******************************************************************************
* @details * @details
Модуль для доступа к регистрам внутри программы:
- Функции для доступа к регистрам хранения по глобальным адресам
Модуль обработки команд для holding registers (регистров хранения): Модуль обработки команд для holding registers (регистров хранения):
- Чтение множественных регистров (0x03) - копирование данных в буфер ответа - Чтение множественных регистров (0x03) - копирование данных в буфер ответа
- Запись одиночного регистра (0x06) - прямая запись значения - Запись одиночного регистра (0x06) - прямая запись значения
- Запись множественных регистров (0x10) - пакетная запись из буфера - Запись множественных регистров (0x10) - пакетная запись из буфера
@section Валидация данных: @section hvalid Валидация данных:
- Проверка соответствия количества байт и регистров - Проверка соответствия количества байт и регистров
Валидация адресов через MB_DefineRegistersAddress() - Валидация адресов через MB_DefineRegistersAddress()
- Обработка исключений при некорректных запросах - Обработка исключений при некорректных запросах
@section Echo-ответы:
При успешной записи формируется echo-ответ с теми же данными,
что были в запросе (для функций 0x05, 0x06, 0x0F, 0x10).
******************************************************************************/ ******************************************************************************/
#include "modbus_inputregs.h" #include "modbus_inputregs.h"

View File

@@ -1,13 +1,18 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_inputregs.c * @file modbus_inputregs.c
* @brief Реализация работы с входными регистрами Modbus * @brief Реализация работы с входными регистрами Modbus
****************************************************************************** *******************************************************************************
* @details * @details
Модуль для доступа к регистрам внутри программы:
- Функции для доступа к входным регистрам по глобальным адресам
Модуль обработки команды чтения input registers (0x04): Модуль обработки команды чтения input registers (0x04):
- Чтение множественных входных регистров
Копирование данных из структур устройства в буфер ответа @section ivalid Валидация данных:
- Поддержка знаковых и беззнаковых значений - Проверка соответствия количества байт и регистров
- Валидация адресов через MB_DefineRegistersAddress()
- Обработка исключений при некорректных запросах
******************************************************************************/ ******************************************************************************/
#include "modbus_inputregs.h" #include "modbus_inputregs.h"

View File

@@ -1,12 +1,22 @@
/** /**
************************************************************************** *******************************************************************************
* @file modbus_master.c * @file modbus_master.c
* @brief Модуль для реализации мастера MODBUS. * @brief Модуль для реализации мастера MODBUS.
************************************************************************** *******************************************************************************
* @details * @details
Файл содержит реализацию функций для работы Modbus в режиме мастера. Файл содержит реализацию функций для работы 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_Collect_Message() — Сбор сообщения в режиме мастера
- MB_Master_Parse_Message() — Парс сообщения в режиме мастера - MB_Master_Parse_Message() — Парс сообщения в режиме мастера
@@ -16,8 +26,35 @@
#ifdef MODBUS_ENABLE_MASTER #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, &reg_arr[i]))
{
read_cnt++;
}
i++;
}
return read_cnt;
}
/**
* @brief Получить значение регистра в ответе по его адресу
* @param modbus_msg Указатель на структуру сообщения * @param modbus_msg Указатель на структуру сообщения
* @param reg_addr Адрес регистра, значение которого нужно получить * @param reg_addr Адрес регистра, значение которого нужно получить
* @param reg_value Указатель для значения регистра * @param reg_value Указатель для значения регистра
@@ -55,6 +92,31 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1
/**
* @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 в ответе по его адресу * @brief Получить состояние coil в ответе по его адресу
* @param modbus_msg Указатель на структуру сообщения * @param modbus_msg Указатель на структуру сообщения
@@ -93,7 +155,7 @@ int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coi
if(bit_index < 8) if(bit_index < 8)
*coil_state = (modbus_msg->MbData[data_index] >> (bit_index+8)) & 0x01; *coil_state = (modbus_msg->MbData[data_index] >> (bit_index+8)) & 0x01;
else else
*coil_state = ((modbus_msg->MbData[data_index]&0xFF) >> bit_index-8) & 0x01; *coil_state = ((modbus_msg->MbData[data_index]&0xFF) >> (bit_index-8)) & 0x01;
return 1; return 1;
@@ -250,6 +312,10 @@ int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data)
} }
//-------------------------------------------------------------------
//-----------------------------INTERNAL------------------------------
/** /**
* @brief Определить размер модбас запроса (МАСТЕР версия). * @brief Определить размер модбас запроса (МАСТЕР версия).
* @param hRS Указатель на хендлер RS. * @param hRS Указатель на хендлер RS.

View File

@@ -1,12 +1,12 @@
/** /**
************************************************************************** *******************************************************************************
* @file modbus_slave.c * @file modbus_slave.c
* @brief Модуль для реализации слейв MODBUS. * @brief Модуль для реализации слейв MODBUS.
************************************************************************** *******************************************************************************
* @details * @details
Файл содержит реализацию функций для работы Modbus в режиме слейва. Файл содержит реализацию функций для работы Modbus в режиме слейва.
@section Функции и макросы @section slave Функции и макросы
- MB_Slave_Response() — Ответ на запрос - MB_Slave_Response() — Ответ на запрос
- MB_Slave_Collect_Message() — Сбор сообщения в режиме слейва. - MB_Slave_Collect_Message() — Сбор сообщения в режиме слейва.

View File

@@ -1,8 +1,8 @@
/** /**
****************************************************************************** *******************************************************************************
* @file rs_message.c * @file rs_message.c
* @brief Реализация протоколов обмена по RS/UART * @brief Реализация протоколов обмена по RS/UART
****************************************************************************** *******************************************************************************
* @details * @details
Модуль реализует асинхронный обмен сообщениями через UART с использованием: Модуль реализует асинхронный обмен сообщениями через UART с использованием:
- Прерываний по приему/передаче - Прерываний по приему/передаче
@@ -10,7 +10,7 @@
- Таймаутов через таймер - Таймаутов через таймер
- Двухстадийного приема (заголовок + данные) - Двухстадийного приема (заголовок + данные)
@section Архитектура: @section arch Архитектура:
В режиме слейв: В режиме слейв:
- Инициализация приема с сообщения с максимальным размером MSG_SIZE_MAX - Инициализация приема с сообщения с максимальным размером MSG_SIZE_MAX
- При срабатывании прерывания IDLE - обработка полученного сообщения - При срабатывании прерывания IDLE - обработка полученного сообщения
@@ -18,7 +18,7 @@
- Отправка запроса и переход в режим приема сообщения с максимальным размером MSG_SIZE_MAX - Отправка запроса и переход в режим приема сообщения с максимальным размером MSG_SIZE_MAX
- При срабатывании прерывания IDLE - обработка полученного ответа - При срабатывании прерывания IDLE - обработка полученного ответа
@section Необходимые обработчики: @section ithandler Необходимые обработчики:
- RS_UART_Handler() в UARTx_IRQHandler вместо HAL_UART_IRQHandler() - RS_UART_Handler() в UARTx_IRQHandler вместо HAL_UART_IRQHandler()
- RS_TIM_Handler() в TIMx_IRQHandler вместо HAL_TIM_IRQHandler() - RS_TIM_Handler() в TIMx_IRQHandler вместо HAL_TIM_IRQHandler()
******************************************************************************/ ******************************************************************************/

View File

@@ -5,6 +5,7 @@
****************************************************************************** ******************************************************************************
@addtogroup MODBUS_CONFIGS Modbus configs @addtogroup MODBUS_CONFIGS Modbus configs
@ingroup MODBUS @ingroup MODBUS
@brief Конфигурация библиотеки
@{ @{
****************************************************************************** ******************************************************************************
* @details * @details

View File

@@ -3,7 +3,7 @@
* @file modbus_data.h * @file modbus_data.h
* @brief Определения структур данных Modbus устройства * @brief Определения структур данных Modbus устройства
****************************************************************************** ******************************************************************************
@defgroup MODBUS_DATA Modbus Data Tools @defgroup MODBUS_DATA Modbus Registers Map
@ingroup MODBUS @ingroup MODBUS
@brief Определение карты регистров и коилов @brief Определение карты регистров и коилов
****************************************************************************** ******************************************************************************
@@ -13,7 +13,7 @@
- Input Registers (R/O) - входные регистры - Input Registers (R/O) - входные регистры
- Coils (R/W) - дискретные выходы - Coils (R/W) - дискретные выходы
@section Базовая настройка под устройство: @section datinit Базовая настройка под устройство:
1. Настроить диапазоны адресов 1. Настроить диапазоны адресов
- @ref R_INPUT_ADDR и @ref R_INPUT_QNT для входных регистров - @ref R_INPUT_ADDR и @ref R_INPUT_QNT для входных регистров
- @ref R_HOLDING_ADDR и @ref R_HOLDING_QNT для регистров хранения - @ref R_HOLDING_ADDR и @ref R_HOLDING_QNT для регистров хранения
@@ -24,7 +24,7 @@
- @ref MB_DataCoilsTypeDef - @ref MB_DataCoilsTypeDef
@section Расширенная настройка под устройство: @section datexpert Расширенная настройка под устройство:
1. Добавить новый массив с нужными данными. 1. Добавить новый массив с нужными данными.
2. Добавить дефайны для определения его начального адреса и количества элементов 2. Добавить дефайны для определения его начального адреса и количества элементов
3. Добавить проверку адресов в MB_DefineRegistersAddress/MB_DefineCoilsAddress. 3. Добавить проверку адресов в MB_DefineRegistersAddress/MB_DefineCoilsAddress.
@@ -75,11 +75,11 @@
* @addtogroup MODBUS_DATA_RERISTERS_DEFINES Registers structures * @addtogroup MODBUS_DATA_RERISTERS_DEFINES Registers structures
* @ingroup MODBUS_DATA * @ingroup MODBUS_DATA
* @brief Стуруктура регистров (входных и хранения) * @brief Стуруктура регистров (входных и хранения)
@verbatim @code
Для массивов регистров: Для массивов регистров:
R_<NAME_ARRAY>_ADDR - модбас адресс первого регистра в массиве R_<NAME_ARRAY>_ADDR - модбас адресс первого регистра в массиве
R_<NAME_ARRAY>_QNT - количество регистров в массиве R_<NAME_ARRAY>_QNT - количество регистров в массиве
@endverbatim @endcode
* @{ * @{
*/ */
@@ -111,12 +111,12 @@ typedef struct //MB_DataInRegsTypeDef
* @addtogroup MODBUS_DATA_COILS_DEFINES Coils Structure * @addtogroup MODBUS_DATA_COILS_DEFINES Coils Structure
* @ingroup MODBUS_DATA * @ingroup MODBUS_DATA
* @brief Структура коилов * @brief Структура коилов
@verbatim @code
Структура дефайна Структура дефайна
Для массивов коилов: Для массивов коилов:
C_<NAME_ARRAY>_ADDR - модбас адресс первого коила в массиве C_<NAME_ARRAY>_ADDR - модбас адресс первого коила в массиве
C_<NAME_ARRAY>_QNT - количество коилов в массиве (минимум 16) C_<NAME_ARRAY>_QNT - количество коилов в массиве (минимум 16)
@endverbatim @endcode
* @{ * @{
*/ */