release 0.4 (*API CHANGED)

*Не совсем апи, но поменялись enum в modbus_core.h:
- MB_ExceptionTypeDef
- MB_FunctonTypeDef

Необходимо обновить modbus_data.c:
NO_ERRORS 		->	NO_ERRORS
ILLEGAL_FUNCTION	->	ET_ILLEGAL_FUNCTION
ILLEGAL_DATA_ADDRESS 	-> 	ET_ILLEGAL_DATA_ADDRESS
ILLEGAL_DATA_ADDRESS	->	ET_ILLEGAL_DATA_ADDRESS

- множественные правки докумнтации
- множественный рефакторинг
This commit is contained in:
2025-11-06 21:33:08 +03:00
parent 3d106f18ef
commit c648a605f5
26 changed files with 1187 additions and 926 deletions

118
Inc/__modbus_compat.h Normal file
View File

@@ -0,0 +1,118 @@
/**
*******************************************************************************
* @file __modbus_compat.h
* @brief Модуль для совместимости библиотеки MODBUS.
*******************************************************************************
* @details Файл содержит API старых функций, а также заглушки для отключенных модулей:
******************************************************************************/
#include "modbus_core.h"
/** @addtogroup MODBUS_LEGACY_API Legacy API
* @ingroup MODBUS_FUNCTIONS
* @brief Старые API функций, сохранённые для обратной совместимости.
* @note Не используйте эти функции в новом коде. Они могут быть удалены в будущих версиях.
* Вместо них используйте функции из основных групп MODBUS API.
* @{
*/
/** MODBUS_LEGACY_API
* @}
*/
/** @cond Заглушки отключенных модулей */
#ifndef MODBUS_ENABLE_COILS
#define MB_Coil_Write_Global(Addr, WriteVal) ET_ILLEGAL_FUNCTION
#define MB_Coil_Read_Global(Addr, Exception) 0
#define MB_Process_Read_Coils(modbus_msg) 0
#define MB_Process_Write_Single_Coil(modbus_msg) 0
#define MB_Process_Write_Miltuple_Coils(modbus_msg) 0
#endif
#ifndef MODBUS_ENABLE_HOLDINGS
#define MB_Holding_Write_Global(Addr, WriteVal) ET_ILLEGAL_FUNCTION
#define MB_Holding_Read_Global(Addr, Exception) 0
#define MB_Process_Read_Hold_Regs(modbus_msg) 0
#define MB_Process_Write_Single_Reg(modbus_msg) 0
#define MB_Process_Write_Miltuple_Regs(modbus_msg) 0
#endif
#ifndef MODBUS_ENABLE_INPUTS
#define MB_Input_Write_Global(Addr, WriteVal) ET_ILLEGAL_FUNCTION
#define MB_Input_Read_Global(Addr, Exception) 0
#define MB_Process_Read_Input_Regs(modbus_msg) 0
#endif
#ifndef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#define MB_WriteSingleObjectToMessage(mbdata, ind, obj)
#define MB_WriteObjectsToMessage(modbus_msg, maxidofobj)
#define MB_Process_Read_Device_Identifications(modbus_msg) 0
#define MB_DeviceInentificationInit()
#endif
#ifndef MODBUS_ENABLE_DIAGNOSTICS
#define MB_DiagnosticsInit()
#define MB_Diagnostics_WriteBit(bit_num, bit_state) 0
#define MB_Diagnostics_GetBit(bit_num) 0
#define MB_Process_Diagnostics(modbus_msg) 0
#define MB_Diagnostics_BusMessageCnt()
#define MB_Diagnostics_CommunicationErrorCnt()
#define MB_Diagnostics_ExceptionErrorCnt()
#define MB_Diagnostics_CharacterOverrunCnt()
#define MB_Diagnostics_SlaveMessageCnt()
#define MB_Diagnostics_SlaveNoResponseCnt()
#define MB_Diagnostics_SlaveNAKCnt()
#define MB_Diagnostics_SlaveBusyCnt()
#define MB_GetDeviceMode() MODBUS_NORMAL_MODE
#endif
#ifndef MODBUS_ENABLE_MASTER
#define MB_RespGet_RegisterValue(modbus_msg, reg_addr, reg_value) 0
#define MB_RespGet_CoilState(modbus_msg, coil_addr, coil_state) 0
#define MB_RespGet_NumberOfObjects(modbus_msg) 0
#define MB_RespGet_ObjectById(modbus_msg, obj_id, obj_data, obj_length) 0
#define MB_RespGet_ObjectByIndex(modbus_msg, index, obj_id, obj_data, obj_length) 0
#define MB_RespGet_Diagnostic(modbus_msg, data) 0
#define MB_REQUEST_READ_COILS(slave_addr, start_addr, quantity) {0}
#define MB_REQUEST_READ_DISCRETE_INPUTS(slave_addr, start_addr, quantity) {0}
#define MB_REQUEST_READ_HOLDING_REGS(slave_addr, start_addr, quantity) {0}
#define MB_REQUEST_READ_INPUT_REGS(slave_addr, start_addr, quantity) {0}
#define MB_REQUEST_WRITE_SINGLE_COIL(slave_addr, coil_addr, value) {0}
#define MB_REQUEST_WRITE_SINGLE_REG(slave_addr, reg_addr, value) {0}
#define MB_REQUEST_WRITE_MULTIPLE_COILS(slave_addr, start_addr, quantity, coils_data) {0}
#define MB_REQUEST_WRITE_MULTIPLE_REGS(slave_addr, start_addr, quantity, regs_data) {0}
#define MB_REQUEST_DIAGNOSTIC_QUERY(slave_addr, sub_function, data) {0}
#define MB_REQUEST_RETURN_QUERY_DATA(slave_addr) {0}
#define MB_REQUEST_RESTART_COMMUNICATIONS(slave_addr, data) {0}
#define MB_REQUEST_RETURN_DIAGNOSTIC_REGISTER(slave_addr) {0}
#define MB_REQUEST_FORCE_LISTEN_ONLY_MODE(slave_addr) {0}
#define MB_REQUEST_CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER(slave_addr) {0}
#define MB_REQUEST_RETURN_BUS_MESSAGE_COUNT(slave_addr) {0}
#define MB_REQUEST_RETURN_BUS_COMMUNICATION_ERROR_COUNT(slave_addr) {0}
#define MB_REQUEST_RETURN_SLAVE_EXCEPTION_ERROR_COUNT(slave_addr) {0}
#define MB_REQUEST_RETURN_SLAVE_MESSAGE_COUNT(slave_addr) {0}
#define MB_REQUEST_RETURN_SLAVE_NO_RESPONSE_COUNT(slave_addr) {0}
#define MB_REQUEST_RETURN_SLAVE_NAK_COUNT(slave_addr) {0}
#define MB_REQUEST_RETURN_SLAVE_BUSY_COUNT(slave_addr) {0}
#define MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(slave_addr) {0}
#define MB_REQUEST_READ_DEVICE_ID_BASIC(slave_addr) {0}
#define MB_REQUEST_READ_DEVICE_ID_REGULAR(slave_addr) {0}
#define MB_REQUEST_READ_DEVICE_ID_EXTENDED(slave_addr) {0}
#define MB_REQUEST_READ_DEVICE_ID_SPECIFIC(slave_addr, object_id) {0}
#define MB_Master_Collect_Message(hmodbus, modbus_msg, modbus_uart_buff) RS_ERR
#define MB_Master_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff) RS_ERR
#endif
#ifndef MODBUS_ENABLE_SLAVE
#define MB_Slave_Response(hmodbus, modbus_msg) RS_ERR
#define MB_Slave_Collect_Message(hmodbus, modbus_msg, modbus_uart_buff) RS_ERR
#define MB_Slave_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff) RS_ERR
#endif
/** @endcond */

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, 1, 1000, 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-битные слова. Доступ к регистрам осуществляется через указатель.
@@ -84,21 +86,35 @@
#define __MODBUS_H_ #define __MODBUS_H_
#include "rs_message.h" #include "rs_message.h"
#ifdef MODBUS_ENABLE_MASTER
#include "modbus_master.h" #include "modbus_master.h"
#endif
#ifdef MODBUS_ENABLE_SLAVE
#include "modbus_slave.h" #include "modbus_slave.h"
#endif
#ifdef MODBUS_ENABLE_COILS
#include "modbus_coils.h" #include "modbus_coils.h"
#endif
#ifdef MODBUS_ENABLE_HOLDINGS
#include "modbus_holdregs.h" #include "modbus_holdregs.h"
#endif
#ifdef MODBUS_ENABLE_INPUTS
#include "modbus_inputregs.h" #include "modbus_inputregs.h"
#endif
#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#include "modbus_devid.h" #include "modbus_devid.h"
#endif
#ifdef MODBUS_ENABLE_DIAGNOSTICS
#include "modbus_diag.h" #include "modbus_diag.h"
#endif
#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
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@@ -125,3 +141,4 @@ HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef
/** MODBUS_FUNCTIONS /** MODBUS_FUNCTIONS
* @} * @}
*/ */

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,28 +29,37 @@
#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 Определения протокола модбас
@{ * @{
*/ */
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
////////////////////---MODBUS MESSAGE DEFINES---///////////////////// ////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
//-------------DEFINES FOR STRUCTURE---------------- //-------------DEFINES FOR STRUCTURE----------------
/* defines for structure of modbus message */ /* defines for structure of modbus message */
#define MbAddr_SIZE 1 ///< size of (MbAddr) #define TransactionID_size 2 ///< size of (Transaction ID)
#define Func_Code_SIZE 1 ///< size of (Func_Code) #define ProtocolID_size 2 ///< size of (Protocol ID)
#define Addr_SIZE 2 ///< size of (Addr) #define PDULength_size 2 ///< size of (PDU Length)
#define Qnt_SIZE 2 ///< size of (Qnt) #define MbAddr_SIZE 1 ///< size of (Slave Addr)
#define ByteCnt_SIZE 1 ///< size of (ByteCnt) #define Func_Code_SIZE 1 ///< size of (Function Code)
#define Addr_SIZE 2 ///< size of (Address)
#define Qnt_SIZE 2 ///< size of (Quantity)
#define ByteCnt_SIZE 1 ///< size of (Byte Count)
#define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE) #define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE)
#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes #define CRC_SIZE 2 ///< size of (MbCRC) in bytes
/** @brief Size of whole message */ #ifndef MODBUS_PROTOCOL_TCP
/** @brief Size of whole RTU message */
#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE) #define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE)
#else
/** @brief Size of whole TCP message */
#define INFO_SIZE_MAX (TransactionID_size+ProtocolID_size+PDULength_size+MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE)
#endif
/** @brief Size of first part of message that will be received /** @brief Size of first part of message that will be received
first receive info part of message, than defines size of rest message*/ first receive info part of message, than defines size of rest message*/
@@ -58,100 +68,104 @@ first receive info part of message, than defines size of rest message*/
/** @brief Size of buffer: max size of whole message */ /** @brief Size of buffer: max size of whole message */
#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message #define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message
/** @brief Structure for modbus exception codes */ /**
* @brief Enum for modbus exception codes
* @details Prefix ET for Error Type
*/
typedef enum //MB_ExceptionTypeDef typedef enum //MB_ExceptionTypeDef
{ {
// reading // reading
NO_ERRORS = 0x00, ///< no errors ET_NO_ERRORS = 0x00, ///< no errors
ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан ET_ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан
ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен ET_ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен
ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной ET_ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной
SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие ET_SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие
// ACKNOWLEDGE = 0x05, ///< idk // ET_ACKNOWLEDGE = 0x05, ///< idk
// SLAVE_DEVICE_BUSY = 0x06, ///< idk // ET_SLAVE_DEVICE_BUSY = 0x06, ///< idk
// MEMORY_PARITY_ERROR = 0x08, ///< idk // ET_MEMORY_PARITY_ERROR = 0x08, ///< idk
}MB_ExceptionTypeDef; }MB_ExceptionTypeDef;
#define ERR_VALUES_START 0x80U ///< from this value starts error func codes #define FC_ERR_VALUES_START 0x80U ///< from this value starts error func codes
/** @brief Structure for modbus func codes */ /**
* @brief Enum for modbus func codes
* @details Prefix FC for Function Code
*/
typedef enum //MB_FunctonTypeDef typedef enum //MB_FunctonTypeDef
{ {
/* COMMANDS */ /* COMMANDS */
// reading // reading
MB_R_COILS = 0x01, ///< Чтение битовых ячеек FC_R_COILS = 0x01, ///< Чтение битовых ячеек
MB_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
MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров FC_R_HOLD_REGS = 0x03, ///< Чтение входных регистров
MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения FC_R_IN_REGS = 0x04, ///< Чтение регистров хранения
#else #else
MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров FC_R_HOLD_REGS = 0x04, ///< Чтение входных регистров
MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения FC_R_IN_REGS = 0x03, ///< Чтение регистров хранения
#endif #endif
// writting // writting
MB_W_COIL = 0x05, ///< Запись битовой ячейки FC_W_COIL = 0x05, ///< Запись битовой ячейки
MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра FC_W_HOLD_REG = 0x06, ///< Запись одиночного регистра
MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек FC_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров FC_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
MB_R_DIAGNOSTIC = 0x08, ///< Чтение диагностической информации устройства FC_R_DIAGNOSTICS = 0x08, ///< Чтение диагностической информации устройства
MB_R_DEVICE_INFO = 0x2B, ///< Чтение информации об устройстве FC_R_DEVICE_ID = 0x2B, ///< Чтение информации об устройстве
/* ERRORS */ /* ERRORS */
// error reading // error reading
MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек FC_ERR_R_COILS = FC_R_COILS + FC_ERR_VALUES_START, ///< Ошибка чтения битовых ячеек
MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов FC_ERR_R_DISC_IN = FC_R_DISC_IN + FC_ERR_VALUES_START, ///< Ошибка чтения дискретных входов
MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения FC_ERR_R_IN_REGS = FC_R_IN_REGS + FC_ERR_VALUES_START, ///< Ошибка чтения регистров хранения
MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров FC_ERR_R_HOLD_REGS = FC_R_HOLD_REGS + FC_ERR_VALUES_START, ///< Ошибка чтения входных регистров
// error writting // error writting
MB_ERR_W_COIL = MB_W_COIL + ERR_VALUES_START, ///< Ошибка записи битовой ячейки FC_ERR_W_COIL = FC_W_COIL + FC_ERR_VALUES_START, ///< Ошибка записи битовой ячейки
MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра FC_ERR_W_HOLD_REG = FC_W_HOLD_REG + FC_ERR_VALUES_START, ///< Ошибка записи одиночного регистра
MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек FC_ERR_W_COILS = FC_W_COILS + FC_ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров FC_ERR_W_HOLD_REGS = FC_W_HOLD_REGS + FC_ERR_VALUES_START, ///< Ошибка записи нескольких регистров
MB_ERR_R_DIAGNOSTIC = MB_R_DIAGNOSTIC + ERR_VALUES_START, ///< Ошибка чтения диагностической информации устройства FC_ERR_R_DIAGNOSTIC = FC_R_DIAGNOSTICS + FC_ERR_VALUES_START, ///< Ошибка чтения диагностической информации устройства
MB_ERR_R_DEVICE_INFO = MB_R_DEVICE_INFO + ERR_VALUES_START, ///< Ошибка чтения информации об устройстве FC_ERR_R_DEVICE_INFO = FC_R_DEVICE_ID + FC_ERR_VALUES_START, ///< Ошибка чтения информации об устройстве
}MB_FunctonTypeDef; }MB_FunctonTypeDef;
/** @brief Structure for MEI func codes */ /** @brief Enum for MEI func codes */
typedef enum //MB_FunctonTypeDef typedef enum //MB_FunctonTypeDef
{ {
MEI_DEVICE_IDENTIFICATIONS = 0x0E, MEI_DEVICE_IDENTIFICATIONS = 0x0E,
}MB_MEITypeDef; }MB_MEITypeDef;
/** @brief Structure for comformity */ /**
* @brief Enum for Read Device Id codes
* @details Prefix RID for Read ID
*/
typedef enum //MB_FunctonTypeDef typedef enum //MB_FunctonTypeDef
{ {
MB_BASIC_IDENTIFICATIONS = 0x01, /*!< @brief Basic Device Identifications. RID_BASIC_IDENTIFICATIONS = 0x01, /*!< @brief Basic Device Identifications.
@details All objects of this category are mandatory: @details All objects of this category are mandatory:
VendorName,Product code, and revision number */ VendorName, Product code, and revision number */
MB_REGULAR_IDENTIFICATIONS = 0x02, /*!< @brief Regular Device Identifications. RID_REGULAR_IDENTIFICATIONS = 0x02, /*!< @brief Regular Device Identifications.
@details The device provides additional and optional @details The device provides additional and optional
identifications and description data objects */ identifications and description data objects */
MB_EXTENDED_IDENTIFICATIONS = 0x03, /*!< @brief Extended Device Identifications. RID_EXTENDED_IDENTIFICATIONS = 0x03, /*!< @brief Extended Device Identifications.
@details The device provides additional and optional @details The device provides additional and optional
identifications and description private data about the physical identifications and description private data about the physical
device itself. All of these data are device dependent. */ device itself. All of these data are device dependent. */
MB_SPEDIFIC_IDENTIFICATIONS = 0x04, /*!< @brief Specific Device Identifications. RID_SPEDIFIC_IDENTIFICATIONS = 0x04, /*!< @brief Specific Device Identifications.
@details The device provides one specific identifications object. */ @details The device provides one specific identifications object. */
/* ERRORS */ }MB_ReadDevId;
MB_ERR_BASIC_IDENTIFICATIONS = MB_BASIC_IDENTIFICATIONS + ERR_VALUES_START,
MB_ERR_REGULAR_IDENTIFICATIONS = MB_REGULAR_IDENTIFICATIONS + ERR_VALUES_START,
MB_ERR_EXTENDED_IDENTIFICATIONS = MB_REGULAR_IDENTIFICATIONS + ERR_VALUES_START,
MB_ERR_SPEDIFIC_IDENTIFICATIONS = MB_REGULAR_IDENTIFICATIONS + ERR_VALUES_START,
}MB_ConformityTypeDef;
/** @brief Structure for decive identifications message type */ /** @brief Structure for device identifications message type */
typedef struct typedef struct
{ {
MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identifications Interface MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identifications Interface
MB_ConformityTypeDef ReadDevId; MB_ReadDevId ReadDevId;
MB_ConformityTypeDef Conformity; uint8_t Conformity; ///< Identification conformity level of the device and type of supported access @ref MODBUS_DEVICE_CONFORMITY
uint8_t MoreFollows; uint8_t MoreFollows;
uint8_t NextObjId; uint8_t NextObjId;
uint8_t NumbOfObj; uint8_t NumbOfObj;
@@ -161,17 +175,23 @@ typedef struct
/** @brief Structure for modbus messsage */ /** @brief Structure for modbus messsage */
typedef struct // RS_MsgTypeDef typedef struct // RS_MsgTypeDef
{ {
#ifdef MODBUS_PROTOCOL_TCP
uint16_t TransactionID; ///< Modbus TCP: ID Transaction
uint16_t ProtocolID; ///< Modbus TCP: ID Protocol
uint16_t PDULength; ///< Modbus TCP: PDU Length
#endif
uint8_t MbAddr; ///< Modbus Slave Address uint8_t MbAddr; ///< Modbus Slave Address
MB_FunctonTypeDef Func_Code; ///< Modbus Function Code MB_FunctonTypeDef FuncCode; ///< Modbus Function Code
MB_DevIdMsgTypeDef DevId; ///< Read Device Identifications Header struct MB_DevIdMsgTypeDef DevId; ///< Read Device Identifications Header struct
uint16_t Addr; ///< Modbus Address of data uint16_t Addr; ///< Modbus Address of data
uint16_t Qnt; ///< Quantity of modbus data uint16_t Qnt; ///< Quantity of modbus data
uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive
uint16_t DATA[DATA_SIZE]; ///< Modbus Data uint16_t MbData[DATA_SIZE]; ///< Modbus Data
MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command
uint16_t MB_CRC; ///< Modbus CRC uint16_t MbCRC; ///< Modbus CRC
}RS_MsgTypeDef; }RS_MsgTypeDef;
//-------------------------------------------------- //--------------------------------------------------
extern RS_MsgTypeDef MODBUS_MSG; extern RS_MsgTypeDef MODBUS_MSG;
@@ -199,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)
@@ -207,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)) - сдвинуть бит на место запрашиваемого коила в регистре
@@ -226,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)) ))
@@ -271,7 +291,7 @@ extern RS_MsgTypeDef MODBUS_MSG;
/** /**
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
@{ * @{
*/ */
/* Реализация этих функций лежит в modbus_data.c */ /* Реализация этих функций лежит в modbus_data.c */
@@ -285,6 +305,9 @@ MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint
/** MODBUS_CMD_PROCESS_FUNCTIONS /** MODBUS_CMD_PROCESS_FUNCTIONS
* @} * @}
*/ */
/////////////////////////---FUNCTIONS---///////////////////////////// /////////////////////////---FUNCTIONS---/////////////////////////////
#endif //__MODBUS_CORE_H_ #endif //__MODBUS_CORE_H_
/** MODBUS_INTERNAL /** MODBUS_INTERNAL

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 - пользовательские поля
@@ -31,6 +32,12 @@
* @{ * @{
*/ */
#if MODBUS_NUMB_OF_USEROBJECTS > 0
#define MODBUS_DEVICE_CONFORMITY 0x83
#else
#define MODBUS_DEVICE_CONFORMITY 0x82
#endif
/** @brief Структура для объекта (идентификатора устройства модбас) */ /** @brief Структура для объекта (идентификатора устройства модбас) */
typedef struct typedef struct
{ {
@@ -102,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) */
@@ -113,3 +120,4 @@ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg);
/////////////////////////---FUNCTIONS---///////////////////////////// /////////////////////////---FUNCTIONS---/////////////////////////////
#endif //__MODBUS_DEVID_H_ #endif //__MODBUS_DEVID_H_

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) */
@@ -120,3 +121,4 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg);
/** MODBUS_DIAG /** MODBUS_DIAG
* @} * @}
*/ */

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
- Таймауты: контролируют максимальное время ожидания фрейма - Таймауты: контролируют максимальное время ожидания фрейма
@@ -76,42 +76,6 @@
#define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1) #define RS_Is_TX_Busy(_hRS_) (_hRS_->f.TX_Busy == 1)
#ifndef printf_rs_err
#define printf_rs_err(...)
#endif
#ifndef printf_rs
#define printf_rs(...)
#endif
#ifndef __MYLIBS_CONFIG_H_
// дефайны из mylibs include
static int dummy;
#define TrackerTypeDef(num_user_vars) void *
#define num_of_usercnts(_user_) 0
#define assert_tracecnt(_cntstruct_, _uservarnumb_) 0
#define if_assert_usertracker(_cntstruct_, _uservarnumb_) if(0)
#define tern_assert_usertracker(_cntstruct_, _uservarnumb_) 0
#define TrackerGet_Ok(_cntstruct_) dummy
#define TrackerGet_Err(_cntstruct_) dummy
#define TrackerGet_Warn(_cntstruct_) dummy
#define TrackerGet_User(_cntstruct_, _uservarnumb_) dummy
#define TrackerCnt_Ok(_cntstruct_)
#define TrackerCnt_Err(_cntstruct_)
#define TrackerCnt_Warn(_cntstruct_)
#define TrackerCnt_User(_cntstruct_, _uservarnumb_)
#define TrackerWrite_User(_cntstruct_, _uservarnumb_, _val_)
#define TrackerClear_All(_cntstruct_)
#define TrackerClear_Ok(_cntstruct_)
#define TrackerClear_Err(_cntstruct_)
#define TrackerClear_Warn(_cntstruct_)
#define TrackerClear_User(_cntstruct_)
#define TrackerClear_UserAll(_cntstruct_)
#else
#include "mylibs_include.h"
#endif
#ifndef RS_USER_VARS_NUMB #ifndef RS_USER_VARS_NUMB
#define RS_USER_VARS_NUMB 0 #define RS_USER_VARS_NUMB 0
#endif #endif
@@ -122,6 +86,65 @@ static int dummy;
/** @endcond */ /** @endcond */
/**
* @addtogroup RS_DEBUG Tools for debug RS/UART/TIM
* @ingroup RS_TOOLS
* @brief Дефайны для отладки периферии
* @{
*/
#ifndef RS_USER_VARS_NUMB
#define RS_USER_VARS_NUMB 0 ///< Количество переменных в @ref TrackerTypeDef
#endif
/**
* @brief Тип структуры для счетчиков-переменных
* @param num_user_vars Есть возмоность добавления num_user_vars количества пользовательскиъх переменных
*/
#define TrackerTypeDef(num_user_vars) void *
/** @brief Инкрементировать переменную - успешных событий */
#define TrackerCnt_Ok(_cntstruct_)
/** @brief Инкрементировать переменную - ошибок */
#define TrackerCnt_Err(_cntstruct_)
/** @brief Инкрементировать переменную - предупреждений */
#define TrackerCnt_Warn(_cntstruct_)
#ifndef printf_rs
/** @brief Printf обычных событий RS/UART/TIM */
#define printf_rs(...)
#endif
#ifndef printf_rs_err
/** @brief Printf ошибок RS/UART/TIM */
#define printf_rs_err(...)
#endif
#ifndef RS_TIM_Handler_ENTER
/** @brief Действия при заходе в прерывания таймера */
#define RS_TIM_Handler_ENTER()
#endif
#ifndef RS_TIM_Handler_EXIT
/** @brief Действия при выходе из прерывания таймера */
#define RS_TIM_Handler_EXIT()
#endif
#ifndef RS_UART_Handler_ENTER
/** @brief Действия при заходе в прерывания UART */
#define RS_UART_Handler_ENTER()
#endif
#ifndef RS_UART_Handler_EXIT
/** @brief Действия при выходе из прерывания UART */
#define RS_UART_Handler_EXIT()
#endif
/** RS_TOOLS
* @}
*/
// направление передачи rs485 // направление передачи rs485
#ifndef RS_EnableReceive #ifndef RS_EnableReceive
#define RS_EnableReceive() ///< Функция изменения направления передачи на ПРИЕМ для RS-485 #define RS_EnableReceive() ///< Функция изменения направления передачи на ПРИЕМ для RS-485

207
README.md
View File

@@ -32,14 +32,14 @@ Modbus/ Иерархия модулей:
## Инструкция по подключению ## Инструкция по подключению
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/
@@ -50,47 +50,45 @@ ProjectRoot/
└── 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. Инициализация в коде
3.4. Инициализация в коде
Чтобы настроить Slave-режим `main()` после инициализации HAL: Чтобы настроить Slave-режим `main()` после инициализации HAL:
```c ```c
#include "modbus.h" #include "modbus.h"
int main(void) int main(void)
{ {
// Инициализация HAL // Инициализация HAL
HAL_Init(); HAL_Init();
SystemClock_Config(); SystemClock_Config();
@@ -109,19 +107,18 @@ ProjectRoot/
{ {
// Основной цикл // Основной цикл
} }
} }
``` ```
Чтобы настроить Master-режим `main()` после инициализации HAL: Чтобы настроить Master-режим `main()` после инициализации HAL:
```c ```c
#include "modbus.h" #include "modbus.h"
// Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук // Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук
RS_MsgTypeDef read_hold_cmd = MB_MASTER_READ_HOLDING_REGS(1, 0, 10); RS_MsgTypeDef read_hold_cmd = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10);
// коллбек, вызовется при получении ответа от слейва // коллбек, вызовется при получении ответа от слейва
read_hold[10]; read_hold[10];
void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
{ {
// MB_RespGet_... Чтобы достать нужные данные из ответа // MB_RespGet_... Чтобы достать нужные данные из ответа
if(hmodbus->RS_STATUS == RS_OK) if(hmodbus->RS_STATUS == RS_OK)
{ {
@@ -134,9 +131,9 @@ ProjectRoot/
} }
} }
} }
} }
int main(void) int main(void)
{ {
// Инициализация HAL // Инициализация HAL
HAL_Init(); HAL_Init();
SystemClock_Config(); SystemClock_Config();
@@ -151,115 +148,109 @@ ProjectRoot/
// Запрос по Modbus // Запрос по Modbus
MODBUS_MasterRequest(&hmodbus1, &read_hold_cmd, &callback_func); MODBUS_MasterRequest(&hmodbus1, &read_hold_cmd, &callback_func);
} }
``` ```
3.5. Настройка карты данных #### 3.5. Настройка карты данных
В `modbus_data.h` настройте регистры и coils под ваше устройство: В `modbus_data.h` настройте регистры и coils под ваше устройство:
**Input Registers (только чтение)** **Input Registers (только чтение)**
```c ```c
typedef struct typedef struct
{ {
uint16_t Temperature; // Адрес 0 uint16_t Temperature; // Адрес 0
uint16_t Humidity; // Адрес 1 uint16_t Humidity; // Адрес 1
uint16_t Pressure; // Адрес 2 uint16_t Pressure; // Адрес 2
uint16_t Voltage; // Адрес 3 uint16_t Voltage; // Адрес 3
} MB_DataInRegsTypeDef; } MB_DataInRegsTypeDef;
#define R_INPUT_ADDR 0 // Начальный адрес Input регистров
#define R_INPUT_QNT 4 // Количество Input регистров
```
#define R_INPUT_ADDR 0 // Начальный адрес Input регистров
#define R_INPUT_QNT 4 // Количество Input регистров
```
**Holding Registers (чтение/запись)** **Holding Registers (чтение/запись)**
```c ```c
typedef struct typedef struct
{ {
uint16_t SetpointTemp; // Адрес 0 uint16_t SetpointTemp; // Адрес 0
uint16_t SetpointHumidity; // Адрес 1 uint16_t SetpointHumidity; // Адрес 1
uint16_t ControlMode; // Адрес 2 uint16_t ControlMode; // Адрес 2
} MB_DataHoldRegsTypeDef; } MB_DataHoldRegsTypeDef;
#define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров
#define R_HOLDING_QNT 3 // Количество Holding регистров
```
#define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров
#define R_HOLDING_QNT 3 // Количество Holding регистров
```
**Coils (1-битные)** **Coils (1-битные)**
```c ```c
typedef struct typedef struct
{ {
unsigned Relay1 : 1; // Адрес 0 unsigned Relay1 : 1; // Адрес 0
unsigned Relay2 : 1; // Адрес 1 unsigned Relay2 : 1; // Адрес 1
unsigned Pump : 1; // Адрес 2 unsigned Pump : 1; // Адрес 2
unsigned Heater : 1; // Адрес 3 unsigned Heater : 1; // Адрес 3
unsigned reserved : 12; // Резерв (выравнивание до 16 бит) unsigned reserved : 12; // Резерв (выравнивание до 16 бит)
} MB_DataCoilsTypeDef; } MB_DataCoilsTypeDef;
#define C_COILS_ADDR 0 // Начальный адрес Coils
#define C_COILS_QNT 4 // Количество Coils
```
3.6. Доступ к данным в коде
#define C_COILS_ADDR 0 // Начальный адрес Coils
#define C_COILS_QNT 4 // Количество Coils
```
#### 3.6. Доступ к данным в коде
В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля
```c ```c
// Чтение входных регистров // Чтение входных регистров
uint16_t temp = MB_DATA.InRegs.Temperature; uint16_t temp = MB_DATA.InRegs.Temperature;
// Запись в регистры хранения // Запись в регистры хранения
MB_DATA.HoldRegs.SetpointTemp = 2500; MB_DATA.HoldRegs.SetpointTemp = 2500;
// Управление coils // Управление coils
MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить Relay1 MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить Relay1
MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить Relay2 MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить Relay2
// Чтение coil // Чтение coil
if (MB_Coil_Read_Local(&MB_DATA.Coils, 2)) { if (MB_Coil_Read_Local(&MB_DATA.Coils, 2)) {
// Pump включен // Pump включен
} }
``` ```
В режиме мастера есть функции для получения информации из ответа `MB_RespGet_...()` В режиме мастера есть функции для получения информации из ответа `MB_RespGet_...()`
```c ```c
// Чтение регистров: Получить запрошенные регистры // Чтение регистров: Получить запрошенные регистры
uint16_t value; uint16_t 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);
} }
// Чтение коилов: Получить запрошенные коилы // Чтение коилов: Получить запрошенные коилы
int state; int 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");
} }
// Чтение диагностики: Получить запрошенныую диагностику // Чтение диагностики: Получить запрошенныую диагностику
uint16_t counter_value; uint16_t counter_value;
if(MB_RespGet_DiagnosticResponse(&MODBUS_MSG, &counter_value)) if(MB_RespGet_DiagnosticResponse(&MODBUS_MSG, &counter_value))
{ {
printf("Counter value: %d\n", counter_value); printf("Counter value: %d\n", counter_value);
} }
// Чтение идентификаторов: Получить запрошенные идентификаторы // Чтение идентификаторов: Получить запрошенные идентификаторы
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))
{ {
printf("Vendor Name: %s (length: %d)\n", vendor_name, length); printf("Vendor Name: %s (length: %d)\n", vendor_name, length);
} }
uint8_t obj_id, obj_length; uint8_t obj_id, obj_length;
char obj_data[64]; char obj_data[64];
if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, 0x00, &obj_id, obj_data, &obj_length)) 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); printf("First object - ID: 0x%02X, Data: %s\n", obj_id, obj_data);
} }
``` ```
5. **Обновление библиотеки**: ### 5. **Обновление библиотеки**:
После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся: После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся:
```bash ```bash

7
Src/__modbus_compat.c Normal file
View File

@@ -0,0 +1,7 @@
/**
*******************************************************************************
* @file __modbus_compat.c
* @brief Модуль для совместимости библиотеки MODBUS.
*******************************************************************************
******************************************************************************/
#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"
@@ -18,7 +26,7 @@
* @brief Выставить/сбросить коил по глобальному адресу. * @brief Выставить/сбросить коил по глобальному адресу.
* @param Addr Адрес коила. * @param Addr Адрес коила.
* @param WriteVal Что записать в коил: 0 или 1. * @param WriteVal Что записать в коил: 0 или 1.
* @return ExceptionCode Код исключения если коила по адресу не существует, и NO_ERRORS если все ок. * @return ExceptionCode Код исключения если коила по адресу не существует, и ET_NO_ERRORS если все ок.
* *
* @details Позволяет обратиться к любому коилу по его глобальному адрессу. * @details Позволяет обратиться к любому коилу по его глобальному адрессу.
Вне зависимости от того как коилы размещены в памяти. Вне зависимости от того как коилы размещены в памяти.
@@ -26,13 +34,13 @@
MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal)
{ {
//---------CHECK FOR ERRORS---------- //---------CHECK FOR ERRORS----------
MB_ExceptionTypeDef Exception = NO_ERRORS; MB_ExceptionTypeDef Exception = ET_NO_ERRORS;
uint16_t *coils; uint16_t *coils;
uint16_t start_shift = 0; // shift in coils register uint16_t start_shift = 0; // shift in coils register
//------------WRITE COIL------------- //------------WRITE COIL-------------
Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 1); Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 1);
if(Exception == NO_ERRORS) if(Exception == ET_NO_ERRORS)
{ {
switch(WriteVal) switch(WriteVal)
{ {
@@ -75,7 +83,7 @@ uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception)
//------------READ COIL-------------- //------------READ COIL--------------
*Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 0); *Exception = MB_DefineCoilsAddress(&coils, Addr, 1, &start_shift, 0);
if(*Exception == NO_ERRORS) if(*Exception == ET_NO_ERRORS)
{ {
return ((*coils)&(1<<start_shift)); return ((*coils)&(1<<start_shift));
} }
@@ -99,7 +107,7 @@ uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg)
uint16_t start_shift = 0; // shift in coils register uint16_t start_shift = 0; // shift in coils register
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0); modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 0);
if(modbus_msg->Except_Code != NO_ERRORS) if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0; return 0;
//-----------READING COIL------------ //-----------READING COIL------------
@@ -127,14 +135,14 @@ uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg)
shift = 0; // set shift to zero for the next step shift = 0; // set shift to zero for the next step
//-----------READ COILS-------------- //-----------READ COILS--------------
modbus_msg->DATA[ind] = (*(coils+ind)&mask_for_coils) >> start_shift; modbus_msg->MbData[ind] = (*(coils+ind)&mask_for_coils) >> start_shift;
if(ind > 0) if(ind > 0)
modbus_msg->DATA[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift; modbus_msg->MbData[ind-1] |= ((*(coils+ind)&mask_for_coils) << 16) >> start_shift;
} }
// т.к. DATA 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты // т.к. MbData 16-битная, для 8-битной передачи, надо поменять местами верхний и нижний байты
for(; ind >= 0; --ind) for(; ind >= 0; --ind)
modbus_msg->DATA[ind] = ByteSwap16(modbus_msg->DATA[ind]); modbus_msg->MbData[ind] = ByteSwap16(modbus_msg->MbData[ind]);
return 1; return 1;
} }
@@ -150,14 +158,14 @@ uint8_t MB_Process_Write_Single_Coil(RS_MsgTypeDef *modbus_msg)
//---------CHECK FOR ERRORS---------- //---------CHECK FOR ERRORS----------
if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00)) if ((modbus_msg->Qnt != 0x0000) && (modbus_msg->Qnt != 0xFF00))
{ {
modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE;
return 0; return 0;
} }
// define position of coil // define position of coil
uint16_t *coils; uint16_t *coils;
uint16_t start_shift = 0; // shift in coils register uint16_t start_shift = 0; // shift in coils register
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1); modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, 0, &start_shift, 1);
if(modbus_msg->Except_Code != NO_ERRORS) if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0; return 0;
@@ -181,14 +189,14 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg)
//---------CHECK FOR ERRORS---------- //---------CHECK FOR ERRORS----------
if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8)) if (modbus_msg->ByteCnt != Divide_Up(modbus_msg->Qnt, 8))
{ // if quantity too large OR if quantity and bytes count arent match { // if quantity too large OR if quantity and bytes count arent match
modbus_msg->Except_Code = ILLEGAL_DATA_VALUE; modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE;
return 0; return 0;
} }
// define position of coil // define position of coil
uint16_t *coils; // pointer to coils uint16_t *coils; // pointer to coils
uint16_t start_shift = 0; // shift in coils register uint16_t start_shift = 0; // shift in coils register
modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1); modbus_msg->Except_Code = MB_DefineCoilsAddress(&coils, modbus_msg->Addr, modbus_msg->Qnt, &start_shift, 1);
if(modbus_msg->Except_Code != NO_ERRORS) if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0; return 0;
//----------WRITTING COILS----------- //----------WRITTING COILS-----------
@@ -218,10 +226,10 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg)
// get current coils // get current coils
temp_reg = *(coils+ind); temp_reg = *(coils+ind);
// set coils // set coils
setted_coils = ByteSwap16(modbus_msg->DATA[ind]) << start_shift; setted_coils = ByteSwap16(modbus_msg->MbData[ind]) << start_shift;
if(ind > 0) if(ind > 0)
{ {
setted_coils |= ((ByteSwap16(modbus_msg->DATA[ind-1]) << start_shift) >> 16); setted_coils |= ((ByteSwap16(modbus_msg->MbData[ind-1]) << start_shift) >> 16);
} }
// write coils // write coils
@@ -236,13 +244,5 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg)
return 1; return 1;
} }
#else //MODBUS_ENABLE_COILS
#endif //MODBUS_ENABLE_COILS
MB_ExceptionTypeDef MB_Coil_Write_Global(uint16_t Addr, MB_CoilsOpTypeDef WriteVal) {return ILLEGAL_FUNCTION;}
uint16_t MB_Coil_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;}
uint8_t MB_Process_Read_Coils(RS_MsgTypeDef *modbus_msg) {return 0;}
uint8_t MB_Process_Write_Single_Coil(RS_MsgTypeDef *modbus_msg) {return 0;}
uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg) {return 0;}
#endif

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 для
продолжения чтения в следующем запросе. продолжения чтения в следующем запросе.
@@ -47,11 +47,16 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
{ {
MB_DeviceObjectTypeDef *obj = (MB_DeviceObjectTypeDef *)&MB_DEVID; MB_DeviceObjectTypeDef *obj = (MB_DeviceObjectTypeDef *)&MB_DEVID;
unsigned objidtmp = modbus_msg->DevId.NextObjId; unsigned objidtmp = modbus_msg->DevId.NextObjId;
modbus_msg->Except_Code = ET_NO_ERRORS;
/* Define number of object in one message */ /* Define number of object in one message */
unsigned lastobjid = 0; unsigned lastobjid = 0;
for(int i = 0; i < DATA_SIZE*2;) for(int i = 0; i < DATA_SIZE*2;)
{ {
/* Если объект за пределами допутимого - выходим из цикла */
if(objidtmp >= 0xFF + MODBUS_NUMB_OF_USEROBJECTS)
break;
i += 2; i += 2;
i += obj[objidtmp].length; i += obj[objidtmp].length;
/* Если все еще помещается в массив переходим на следующий объект */ /* Если все еще помещается в массив переходим на следующий объект */
@@ -59,6 +64,7 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
{ {
objidtmp++; objidtmp++;
} }
/* Если объекты для записи закончились - выходим из цикла*/ /* Если объекты для записи закончились - выходим из цикла*/
if(objidtmp > maxidofobj) if(objidtmp > maxidofobj)
break; break;
@@ -67,7 +73,7 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
/* Fill message with objects data */ /* Fill message with objects data */
char *mbdata = (char *)&modbus_msg->DATA; char *mbdata = (char *)&modbus_msg->MbData;
unsigned ind = 0; unsigned ind = 0;
unsigned objid = modbus_msg->DevId.NextObjId; unsigned objid = modbus_msg->DevId.NextObjId;
for(; objid <= lastobjid; objid++) for(; objid <= lastobjid; objid++)
@@ -76,6 +82,9 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
MB_WriteSingleObjectToMessage(mbdata, &ind, &obj[objid]); MB_WriteSingleObjectToMessage(mbdata, &ind, &obj[objid]);
} }
objid--; objid--;
if(modbus_msg->ByteCnt != 0)
{
modbus_msg->ByteCnt = ind; modbus_msg->ByteCnt = ind;
modbus_msg->DevId.NextObjId = lastobjid+1; modbus_msg->DevId.NextObjId = lastobjid+1;
if(objid == maxidofobj) if(objid == maxidofobj)
@@ -86,6 +95,11 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
{ {
modbus_msg->DevId.MoreFollows = 0xFF; modbus_msg->DevId.MoreFollows = 0xFF;
} }
}
else
{
modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE;
}
} }
@@ -97,9 +111,11 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
*/ */
uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg) uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg)
{ {
modbus_msg->DevId.Conformity = MODBUS_DEVICE_CONFORMITY;
switch(modbus_msg->DevId.ReadDevId) switch(modbus_msg->DevId.ReadDevId)
{ {
case MB_BASIC_IDENTIFICATIONS: case RID_BASIC_IDENTIFICATIONS:
if (modbus_msg->DevId.NextObjId == 0) if (modbus_msg->DevId.NextObjId == 0)
{ {
modbus_msg->DevId.NextObjId = 0; modbus_msg->DevId.NextObjId = 0;
@@ -109,7 +125,7 @@ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg)
modbus_msg->DevId.NumbOfObj = 3; modbus_msg->DevId.NumbOfObj = 3;
break; break;
case MB_REGULAR_IDENTIFICATIONS: case RID_REGULAR_IDENTIFICATIONS:
if (modbus_msg->DevId.NextObjId == 0) if (modbus_msg->DevId.NextObjId == 0)
{ {
modbus_msg->DevId.NextObjId = 3; modbus_msg->DevId.NextObjId = 3;
@@ -119,10 +135,11 @@ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg)
modbus_msg->DevId.NumbOfObj = 4; modbus_msg->DevId.NumbOfObj = 4;
break; break;
case MB_EXTENDED_IDENTIFICATIONS: case RID_EXTENDED_IDENTIFICATIONS:
if(MODBUS_NUMB_OF_USEROBJECTS <= 0 || MODBUS_NUMB_OF_USEROBJECTS > 128) if(MODBUS_NUMB_OF_USEROBJECTS <= 0 || MODBUS_NUMB_OF_USEROBJECTS > 128)
{ {
return 0; modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE;
break;
} }
if (modbus_msg->DevId.NextObjId == 0) if (modbus_msg->DevId.NextObjId == 0)
@@ -134,14 +151,22 @@ uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg)
modbus_msg->DevId.NumbOfObj = MODBUS_NUMB_OF_USEROBJECTS; modbus_msg->DevId.NumbOfObj = MODBUS_NUMB_OF_USEROBJECTS;
break; break;
case MB_SPEDIFIC_IDENTIFICATIONS: case RID_SPEDIFIC_IDENTIFICATIONS:
MB_WriteObjectsToMessage(modbus_msg, modbus_msg->DevId.NextObjId); MB_WriteObjectsToMessage(modbus_msg, modbus_msg->DevId.NextObjId);
modbus_msg->DevId.NumbOfObj = 1; modbus_msg->DevId.NumbOfObj = 1;
break; break;
default: default:
return 0; return 0;
} }
if(modbus_msg->Except_Code != ET_NO_ERRORS)
{
return 0;
}
else
{
return 1; return 1;
}
} }
@@ -158,400 +183,391 @@ void MB_DeviceInentificationInit(void)
MB_ObjectInit(&MB_DEVID.ProductName, MODBUS_PRODUCT_NAME); MB_ObjectInit(&MB_DEVID.ProductName, MODBUS_PRODUCT_NAME);
MB_ObjectInit(&MB_DEVID.ModelName, MODBUS_MODEL_NAME); MB_ObjectInit(&MB_DEVID.ModelName, MODBUS_MODEL_NAME);
#ifdef MODBUS_USEROBJECT_0_NAME #if defined(MODBUS_USEROBJECT_0_NAME) && MODBUS_NUMB_OF_USEROBJECTS>0
MB_ObjectInit(&MB_DEVID.User[0], MODBUS_USEROBJECT_0_NAME); MB_ObjectInit(&MB_DEVID.User[0], MODBUS_USEROBJECT_0_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_1_NAME #if defined(MODBUS_USEROBJECT_1_NAME) && MODBUS_NUMB_OF_USEROBJECTS>1
MB_ObjectInit(&MB_DEVID.User[1], MODBUS_USEROBJECT_1_NAME); MB_ObjectInit(&MB_DEVID.User[1], MODBUS_USEROBJECT_1_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_2_NAME #if defined(MODBUS_USEROBJECT_2_NAME) && MODBUS_NUMB_OF_USEROBJECTS>2
MB_ObjectInit(&MB_DEVID.User[2], MODBUS_USEROBJECT_2_NAME); MB_ObjectInit(&MB_DEVID.User[2], MODBUS_USEROBJECT_2_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_3_NAME #if defined(MODBUS_USEROBJECT_3_NAME) && MODBUS_NUMB_OF_USEROBJECTS>3
MB_ObjectInit(&MB_DEVID.User[3], MODBUS_USEROBJECT_3_NAME); MB_ObjectInit(&MB_DEVID.User[3], MODBUS_USEROBJECT_3_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_4_NAME #if defined(MODBUS_USEROBJECT_4_NAME) && MODBUS_NUMB_OF_USEROBJECTS>4
MB_ObjectInit(&MB_DEVID.User[4], MODBUS_USEROBJECT_4_NAME); MB_ObjectInit(&MB_DEVID.User[4], MODBUS_USEROBJECT_4_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_5_NAME #if defined(MODBUS_USEROBJECT_5_NAME) && MODBUS_NUMB_OF_USEROBJECTS>5
MB_ObjectInit(&MB_DEVID.User[5], MODBUS_USEROBJECT_5_NAME); MB_ObjectInit(&MB_DEVID.User[5], MODBUS_USEROBJECT_5_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_6_NAME #if defined(MODBUS_USEROBJECT_6_NAME) && MODBUS_NUMB_OF_USEROBJECTS>6
MB_ObjectInit(&MB_DEVID.User[6], MODBUS_USEROBJECT_6_NAME); MB_ObjectInit(&MB_DEVID.User[6], MODBUS_USEROBJECT_6_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_7_NAME #if defined(MODBUS_USEROBJECT_7_NAME) && MODBUS_NUMB_OF_USEROBJECTS>7
MB_ObjectInit(&MB_DEVID.User[7], MODBUS_USEROBJECT_7_NAME); MB_ObjectInit(&MB_DEVID.User[7], MODBUS_USEROBJECT_7_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_8_NAME #if defined(MODBUS_USEROBJECT_8_NAME) && MODBUS_NUMB_OF_USEROBJECTS>8
MB_ObjectInit(&MB_DEVID.User[8], MODBUS_USEROBJECT_8_NAME); MB_ObjectInit(&MB_DEVID.User[8], MODBUS_USEROBJECT_8_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_9_NAME #if defined(MODBUS_USEROBJECT_9_NAME) && MODBUS_NUMB_OF_USEROBJECTS>9
MB_ObjectInit(&MB_DEVID.User[9], MODBUS_USEROBJECT_9_NAME); MB_ObjectInit(&MB_DEVID.User[9], MODBUS_USEROBJECT_9_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_10_NAME #if defined(MODBUS_USEROBJECT_10_NAME) && MODBUS_NUMB_OF_USEROBJECTS>10
MB_ObjectInit(&MB_DEVID.User[10], MODBUS_USEROBJECT_10_NAME); MB_ObjectInit(&MB_DEVID.User[10], MODBUS_USEROBJECT_10_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_11_NAME #if defined(MODBUS_USEROBJECT_11_NAME) && MODBUS_NUMB_OF_USEROBJECTS>11
MB_ObjectInit(&MB_DEVID.User[11], MODBUS_USEROBJECT_11_NAME); MB_ObjectInit(&MB_DEVID.User[11], MODBUS_USEROBJECT_11_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_12_NAME #if defined(MODBUS_USEROBJECT_12_NAME) && MODBUS_NUMB_OF_USEROBJECTS>12
MB_ObjectInit(&MB_DEVID.User[12], MODBUS_USEROBJECT_12_NAME); MB_ObjectInit(&MB_DEVID.User[12], MODBUS_USEROBJECT_12_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_13_NAME #if defined(MODBUS_USEROBJECT_13_NAME) && MODBUS_NUMB_OF_USEROBJECTS>13
MB_ObjectInit(&MB_DEVID.User[13], MODBUS_USEROBJECT_13_NAME); MB_ObjectInit(&MB_DEVID.User[13], MODBUS_USEROBJECT_13_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_14_NAME #if defined(MODBUS_USEROBJECT_14_NAME) && MODBUS_NUMB_OF_USEROBJECTS>14
MB_ObjectInit(&MB_DEVID.User[14], MODBUS_USEROBJECT_14_NAME); MB_ObjectInit(&MB_DEVID.User[14], MODBUS_USEROBJECT_14_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_15_NAME #if defined(MODBUS_USEROBJECT_15_NAME) && MODBUS_NUMB_OF_USEROBJECTS>15
MB_ObjectInit(&MB_DEVID.User[15], MODBUS_USEROBJECT_15_NAME); MB_ObjectInit(&MB_DEVID.User[15], MODBUS_USEROBJECT_15_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_16_NAME #if defined(MODBUS_USEROBJECT_16_NAME) && MODBUS_NUMB_OF_USEROBJECTS>16
MB_ObjectInit(&MB_DEVID.User[16], MODBUS_USEROBJECT_16_NAME); MB_ObjectInit(&MB_DEVID.User[16], MODBUS_USEROBJECT_16_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_17_NAME #if defined(MODBUS_USEROBJECT_17_NAME) && MODBUS_NUMB_OF_USEROBJECTS>17
MB_ObjectInit(&MB_DEVID.User[17], MODBUS_USEROBJECT_17_NAME); MB_ObjectInit(&MB_DEVID.User[17], MODBUS_USEROBJECT_17_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_18_NAME #if defined(MODBUS_USEROBJECT_18_NAME) && MODBUS_NUMB_OF_USEROBJECTS>18
MB_ObjectInit(&MB_DEVID.User[18], MODBUS_USEROBJECT_18_NAME); MB_ObjectInit(&MB_DEVID.User[18], MODBUS_USEROBJECT_18_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_19_NAME #if defined(MODBUS_USEROBJECT_19_NAME) && MODBUS_NUMB_OF_USEROBJECTS>19
MB_ObjectInit(&MB_DEVID.User[19], MODBUS_USEROBJECT_19_NAME); MB_ObjectInit(&MB_DEVID.User[19], MODBUS_USEROBJECT_19_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_20_NAME #if defined(MODBUS_USEROBJECT_20_NAME) && MODBUS_NUMB_OF_USEROBJECTS>20
MB_ObjectInit(&MB_DEVID.User[20], MODBUS_USEROBJECT_20_NAME); MB_ObjectInit(&MB_DEVID.User[20], MODBUS_USEROBJECT_20_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_21_NAME #if defined(MODBUS_USEROBJECT_21_NAME) && MODBUS_NUMB_OF_USEROBJECTS>21
MB_ObjectInit(&MB_DEVID.User[21], MODBUS_USEROBJECT_21_NAME); MB_ObjectInit(&MB_DEVID.User[21], MODBUS_USEROBJECT_21_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_22_NAME #if defined(MODBUS_USEROBJECT_22_NAME) && MODBUS_NUMB_OF_USEROBJECTS>22
MB_ObjectInit(&MB_DEVID.User[22], MODBUS_USEROBJECT_22_NAME); MB_ObjectInit(&MB_DEVID.User[22], MODBUS_USEROBJECT_22_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_23_NAME #if defined(MODBUS_USEROBJECT_23_NAME) && MODBUS_NUMB_OF_USEROBJECTS>23
MB_ObjectInit(&MB_DEVID.User[23], MODBUS_USEROBJECT_23_NAME); MB_ObjectInit(&MB_DEVID.User[23], MODBUS_USEROBJECT_23_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_24_NAME #if defined(MODBUS_USEROBJECT_24_NAME) && MODBUS_NUMB_OF_USEROBJECTS>24
MB_ObjectInit(&MB_DEVID.User[24], MODBUS_USEROBJECT_24_NAME); MB_ObjectInit(&MB_DEVID.User[24], MODBUS_USEROBJECT_24_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_25_NAME #if defined(MODBUS_USEROBJECT_25_NAME) && MODBUS_NUMB_OF_USEROBJECTS>25
MB_ObjectInit(&MB_DEVID.User[25], MODBUS_USEROBJECT_25_NAME); MB_ObjectInit(&MB_DEVID.User[25], MODBUS_USEROBJECT_25_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_26_NAME #if defined(MODBUS_USEROBJECT_26_NAME) && MODBUS_NUMB_OF_USEROBJECTS>26
MB_ObjectInit(&MB_DEVID.User[26], MODBUS_USEROBJECT_26_NAME); MB_ObjectInit(&MB_DEVID.User[26], MODBUS_USEROBJECT_26_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_27_NAME #if defined(MODBUS_USEROBJECT_27_NAME) && MODBUS_NUMB_OF_USEROBJECTS>27
MB_ObjectInit(&MB_DEVID.User[27], MODBUS_USEROBJECT_27_NAME); MB_ObjectInit(&MB_DEVID.User[27], MODBUS_USEROBJECT_27_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_28_NAME #if defined(MODBUS_USEROBJECT_28_NAME) && MODBUS_NUMB_OF_USEROBJECTS>28
MB_ObjectInit(&MB_DEVID.User[28], MODBUS_USEROBJECT_28_NAME); MB_ObjectInit(&MB_DEVID.User[28], MODBUS_USEROBJECT_28_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_29_NAME #if defined(MODBUS_USEROBJECT_29_NAME) && MODBUS_NUMB_OF_USEROBJECTS>29
MB_ObjectInit(&MB_DEVID.User[29], MODBUS_USEROBJECT_29_NAME); MB_ObjectInit(&MB_DEVID.User[29], MODBUS_USEROBJECT_29_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_30_NAME #if defined(MODBUS_USEROBJECT_30_NAME) && MODBUS_NUMB_OF_USEROBJECTS>30
MB_ObjectInit(&MB_DEVID.User[30], MODBUS_USEROBJECT_30_NAME); MB_ObjectInit(&MB_DEVID.User[30], MODBUS_USEROBJECT_30_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_31_NAME #if defined(MODBUS_USEROBJECT_31_NAME) && MODBUS_NUMB_OF_USEROBJECTS>31
MB_ObjectInit(&MB_DEVID.User[31], MODBUS_USEROBJECT_31_NAME); MB_ObjectInit(&MB_DEVID.User[31], MODBUS_USEROBJECT_31_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_32_NAME #if defined(MODBUS_USEROBJECT_32_NAME) && MODBUS_NUMB_OF_USEROBJECTS>32
MB_ObjectInit(&MB_DEVID.User[32], MODBUS_USEROBJECT_32_NAME); MB_ObjectInit(&MB_DEVID.User[32], MODBUS_USEROBJECT_32_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_33_NAME #if defined(MODBUS_USEROBJECT_33_NAME) && MODBUS_NUMB_OF_USEROBJECTS>33
MB_ObjectInit(&MB_DEVID.User[33], MODBUS_USEROBJECT_33_NAME); MB_ObjectInit(&MB_DEVID.User[33], MODBUS_USEROBJECT_33_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_34_NAME #if defined(MODBUS_USEROBJECT_34_NAME) && MODBUS_NUMB_OF_USEROBJECTS>34
MB_ObjectInit(&MB_DEVID.User[34], MODBUS_USEROBJECT_34_NAME); MB_ObjectInit(&MB_DEVID.User[34], MODBUS_USEROBJECT_34_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_35_NAME #if defined(MODBUS_USEROBJECT_35_NAME) && MODBUS_NUMB_OF_USEROBJECTS>35
MB_ObjectInit(&MB_DEVID.User[35], MODBUS_USEROBJECT_35_NAME); MB_ObjectInit(&MB_DEVID.User[35], MODBUS_USEROBJECT_35_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_36_NAME #if defined(MODBUS_USEROBJECT_36_NAME) && MODBUS_NUMB_OF_USEROBJECTS>36
MB_ObjectInit(&MB_DEVID.User[36], MODBUS_USEROBJECT_36_NAME); MB_ObjectInit(&MB_DEVID.User[36], MODBUS_USEROBJECT_36_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_37_NAME #if defined(MODBUS_USEROBJECT_37_NAME) && MODBUS_NUMB_OF_USEROBJECTS>37
MB_ObjectInit(&MB_DEVID.User[37], MODBUS_USEROBJECT_37_NAME); MB_ObjectInit(&MB_DEVID.User[37], MODBUS_USEROBJECT_37_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_38_NAME #if defined(MODBUS_USEROBJECT_38_NAME) && MODBUS_NUMB_OF_USEROBJECTS>38
MB_ObjectInit(&MB_DEVID.User[38], MODBUS_USEROBJECT_38_NAME); MB_ObjectInit(&MB_DEVID.User[38], MODBUS_USEROBJECT_38_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_39_NAME #if defined(MODBUS_USEROBJECT_39_NAME) && MODBUS_NUMB_OF_USEROBJECTS>39
MB_ObjectInit(&MB_DEVID.User[39], MODBUS_USEROBJECT_39_NAME); MB_ObjectInit(&MB_DEVID.User[39], MODBUS_USEROBJECT_39_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_40_NAME #if defined(MODBUS_USEROBJECT_40_NAME) && MODBUS_NUMB_OF_USEROBJECTS>40
MB_ObjectInit(&MB_DEVID.User[40], MODBUS_USEROBJECT_40_NAME); MB_ObjectInit(&MB_DEVID.User[40], MODBUS_USEROBJECT_40_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_41_NAME #if defined(MODBUS_USEROBJECT_41_NAME) && MODBUS_NUMB_OF_USEROBJECTS>41
MB_ObjectInit(&MB_DEVID.User[41], MODBUS_USEROBJECT_41_NAME); MB_ObjectInit(&MB_DEVID.User[41], MODBUS_USEROBJECT_41_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_42_NAME #if defined(MODBUS_USEROBJECT_42_NAME) && MODBUS_NUMB_OF_USEROBJECTS>42
MB_ObjectInit(&MB_DEVID.User[42], MODBUS_USEROBJECT_42_NAME); MB_ObjectInit(&MB_DEVID.User[42], MODBUS_USEROBJECT_42_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_43_NAME #if defined(MODBUS_USEROBJECT_43_NAME) && MODBUS_NUMB_OF_USEROBJECTS>43
MB_ObjectInit(&MB_DEVID.User[43], MODBUS_USEROBJECT_43_NAME); MB_ObjectInit(&MB_DEVID.User[43], MODBUS_USEROBJECT_43_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_44_NAME #if defined(MODBUS_USEROBJECT_44_NAME) && MODBUS_NUMB_OF_USEROBJECTS>44
MB_ObjectInit(&MB_DEVID.User[44], MODBUS_USEROBJECT_44_NAME); MB_ObjectInit(&MB_DEVID.User[44], MODBUS_USEROBJECT_44_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_45_NAME #if defined(MODBUS_USEROBJECT_45_NAME) && MODBUS_NUMB_OF_USEROBJECTS>45
MB_ObjectInit(&MB_DEVID.User[45], MODBUS_USEROBJECT_45_NAME); MB_ObjectInit(&MB_DEVID.User[45], MODBUS_USEROBJECT_45_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_46_NAME #if defined(MODBUS_USEROBJECT_46_NAME) && MODBUS_NUMB_OF_USEROBJECTS>46
MB_ObjectInit(&MB_DEVID.User[46], MODBUS_USEROBJECT_46_NAME); MB_ObjectInit(&MB_DEVID.User[46], MODBUS_USEROBJECT_46_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_47_NAME #if defined(MODBUS_USEROBJECT_47_NAME) && MODBUS_NUMB_OF_USEROBJECTS>47
MB_ObjectInit(&MB_DEVID.User[47], MODBUS_USEROBJECT_47_NAME); MB_ObjectInit(&MB_DEVID.User[47], MODBUS_USEROBJECT_47_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_48_NAME #if defined(MODBUS_USEROBJECT_48_NAME) && MODBUS_NUMB_OF_USEROBJECTS>48
MB_ObjectInit(&MB_DEVID.User[48], MODBUS_USEROBJECT_48_NAME); MB_ObjectInit(&MB_DEVID.User[48], MODBUS_USEROBJECT_48_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_49_NAME #if defined(MODBUS_USEROBJECT_49_NAME) && MODBUS_NUMB_OF_USEROBJECTS>49
MB_ObjectInit(&MB_DEVID.User[49], MODBUS_USEROBJECT_49_NAME); MB_ObjectInit(&MB_DEVID.User[49], MODBUS_USEROBJECT_49_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_50_NAME #if defined(MODBUS_USEROBJECT_50_NAME) && MODBUS_NUMB_OF_USEROBJECTS>50
MB_ObjectInit(&MB_DEVID.User[50], MODBUS_USEROBJECT_50_NAME); MB_ObjectInit(&MB_DEVID.User[50], MODBUS_USEROBJECT_50_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_51_NAME #if defined(MODBUS_USEROBJECT_51_NAME) && MODBUS_NUMB_OF_USEROBJECTS>51
MB_ObjectInit(&MB_DEVID.User[51], MODBUS_USEROBJECT_51_NAME); MB_ObjectInit(&MB_DEVID.User[51], MODBUS_USEROBJECT_51_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_52_NAME #if defined(MODBUS_USEROBJECT_52_NAME) && MODBUS_NUMB_OF_USEROBJECTS>52
MB_ObjectInit(&MB_DEVID.User[52], MODBUS_USEROBJECT_52_NAME); MB_ObjectInit(&MB_DEVID.User[52], MODBUS_USEROBJECT_52_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_53_NAME #if defined(MODBUS_USEROBJECT_53_NAME) && MODBUS_NUMB_OF_USEROBJECTS>53
MB_ObjectInit(&MB_DEVID.User[53], MODBUS_USEROBJECT_53_NAME); MB_ObjectInit(&MB_DEVID.User[53], MODBUS_USEROBJECT_53_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_54_NAME #if defined(MODBUS_USEROBJECT_54_NAME) && MODBUS_NUMB_OF_USEROBJECTS>54
MB_ObjectInit(&MB_DEVID.User[54], MODBUS_USEROBJECT_54_NAME); MB_ObjectInit(&MB_DEVID.User[54], MODBUS_USEROBJECT_54_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_55_NAME #if defined(MODBUS_USEROBJECT_55_NAME) && MODBUS_NUMB_OF_USEROBJECTS>55
MB_ObjectInit(&MB_DEVID.User[55], MODBUS_USEROBJECT_55_NAME); MB_ObjectInit(&MB_DEVID.User[55], MODBUS_USEROBJECT_55_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_56_NAME #if defined(MODBUS_USEROBJECT_56_NAME) && MODBUS_NUMB_OF_USEROBJECTS>56
MB_ObjectInit(&MB_DEVID.User[56], MODBUS_USEROBJECT_56_NAME); MB_ObjectInit(&MB_DEVID.User[56], MODBUS_USEROBJECT_56_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_57_NAME #if defined(MODBUS_USEROBJECT_57_NAME) && MODBUS_NUMB_OF_USEROBJECTS>57
MB_ObjectInit(&MB_DEVID.User[57], MODBUS_USEROBJECT_57_NAME); MB_ObjectInit(&MB_DEVID.User[57], MODBUS_USEROBJECT_57_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_58_NAME #if defined(MODBUS_USEROBJECT_58_NAME) && MODBUS_NUMB_OF_USEROBJECTS>58
MB_ObjectInit(&MB_DEVID.User[58], MODBUS_USEROBJECT_58_NAME); MB_ObjectInit(&MB_DEVID.User[58], MODBUS_USEROBJECT_58_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_59_NAME #if defined(MODBUS_USEROBJECT_59_NAME) && MODBUS_NUMB_OF_USEROBJECTS>59
MB_ObjectInit(&MB_DEVID.User[59], MODBUS_USEROBJECT_59_NAME); MB_ObjectInit(&MB_DEVID.User[59], MODBUS_USEROBJECT_59_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_60_NAME #if defined(MODBUS_USEROBJECT_60_NAME) && MODBUS_NUMB_OF_USEROBJECTS>60
MB_ObjectInit(&MB_DEVID.User[60], MODBUS_USEROBJECT_60_NAME); MB_ObjectInit(&MB_DEVID.User[60], MODBUS_USEROBJECT_60_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_61_NAME #if defined(MODBUS_USEROBJECT_61_NAME) && MODBUS_NUMB_OF_USEROBJECTS>61
MB_ObjectInit(&MB_DEVID.User[61], MODBUS_USEROBJECT_61_NAME); MB_ObjectInit(&MB_DEVID.User[61], MODBUS_USEROBJECT_61_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_62_NAME #if defined(MODBUS_USEROBJECT_62_NAME) && MODBUS_NUMB_OF_USEROBJECTS>62
MB_ObjectInit(&MB_DEVID.User[62], MODBUS_USEROBJECT_62_NAME); MB_ObjectInit(&MB_DEVID.User[62], MODBUS_USEROBJECT_62_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_63_NAME #if defined(MODBUS_USEROBJECT_63_NAME) && MODBUS_NUMB_OF_USEROBJECTS>63
MB_ObjectInit(&MB_DEVID.User[63], MODBUS_USEROBJECT_63_NAME); MB_ObjectInit(&MB_DEVID.User[63], MODBUS_USEROBJECT_63_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_64_NAME #if defined(MODBUS_USEROBJECT_64_NAME) && MODBUS_NUMB_OF_USEROBJECTS>64
MB_ObjectInit(&MB_DEVID.User[64], MODBUS_USEROBJECT_64_NAME); MB_ObjectInit(&MB_DEVID.User[64], MODBUS_USEROBJECT_64_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_65_NAME #if defined(MODBUS_USEROBJECT_65_NAME) && MODBUS_NUMB_OF_USEROBJECTS>65
MB_ObjectInit(&MB_DEVID.User[65], MODBUS_USEROBJECT_65_NAME); MB_ObjectInit(&MB_DEVID.User[65], MODBUS_USEROBJECT_65_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_66_NAME #if defined(MODBUS_USEROBJECT_66_NAME) && MODBUS_NUMB_OF_USEROBJECTS>66
MB_ObjectInit(&MB_DEVID.User[66], MODBUS_USEROBJECT_66_NAME); MB_ObjectInit(&MB_DEVID.User[66], MODBUS_USEROBJECT_66_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_67_NAME #if defined(MODBUS_USEROBJECT_67_NAME) && MODBUS_NUMB_OF_USEROBJECTS>67
MB_ObjectInit(&MB_DEVID.User[67], MODBUS_USEROBJECT_67_NAME); MB_ObjectInit(&MB_DEVID.User[67], MODBUS_USEROBJECT_67_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_68_NAME #if defined(MODBUS_USEROBJECT_68_NAME) && MODBUS_NUMB_OF_USEROBJECTS>68
MB_ObjectInit(&MB_DEVID.User[68], MODBUS_USEROBJECT_68_NAME); MB_ObjectInit(&MB_DEVID.User[68], MODBUS_USEROBJECT_68_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_69_NAME #if defined(MODBUS_USEROBJECT_69_NAME) && MODBUS_NUMB_OF_USEROBJECTS>69
MB_ObjectInit(&MB_DEVID.User[69], MODBUS_USEROBJECT_69_NAME); MB_ObjectInit(&MB_DEVID.User[69], MODBUS_USEROBJECT_69_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_70_NAME #if defined(MODBUS_USEROBJECT_70_NAME) && MODBUS_NUMB_OF_USEROBJECTS>70
MB_ObjectInit(&MB_DEVID.User[70], MODBUS_USEROBJECT_70_NAME); MB_ObjectInit(&MB_DEVID.User[70], MODBUS_USEROBJECT_70_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_71_NAME #if defined(MODBUS_USEROBJECT_71_NAME) && MODBUS_NUMB_OF_USEROBJECTS>71
MB_ObjectInit(&MB_DEVID.User[71], MODBUS_USEROBJECT_71_NAME); MB_ObjectInit(&MB_DEVID.User[71], MODBUS_USEROBJECT_71_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_72_NAME #if defined(MODBUS_USEROBJECT_72_NAME) && MODBUS_NUMB_OF_USEROBJECTS>72
MB_ObjectInit(&MB_DEVID.User[72], MODBUS_USEROBJECT_72_NAME); MB_ObjectInit(&MB_DEVID.User[72], MODBUS_USEROBJECT_72_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_73_NAME #if defined(MODBUS_USEROBJECT_73_NAME) && MODBUS_NUMB_OF_USEROBJECTS>73
MB_ObjectInit(&MB_DEVID.User[73], MODBUS_USEROBJECT_73_NAME); MB_ObjectInit(&MB_DEVID.User[73], MODBUS_USEROBJECT_73_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_74_NAME #if defined(MODBUS_USEROBJECT_74_NAME) && MODBUS_NUMB_OF_USEROBJECTS>74
MB_ObjectInit(&MB_DEVID.User[74], MODBUS_USEROBJECT_74_NAME); MB_ObjectInit(&MB_DEVID.User[74], MODBUS_USEROBJECT_74_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_75_NAME #if defined(MODBUS_USEROBJECT_75_NAME) && MODBUS_NUMB_OF_USEROBJECTS>75
MB_ObjectInit(&MB_DEVID.User[75], MODBUS_USEROBJECT_75_NAME); MB_ObjectInit(&MB_DEVID.User[75], MODBUS_USEROBJECT_75_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_76_NAME #if defined(MODBUS_USEROBJECT_76_NAME) && MODBUS_NUMB_OF_USEROBJECTS>76
MB_ObjectInit(&MB_DEVID.User[76], MODBUS_USEROBJECT_76_NAME); MB_ObjectInit(&MB_DEVID.User[76], MODBUS_USEROBJECT_76_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_77_NAME #if defined(MODBUS_USEROBJECT_77_NAME) && MODBUS_NUMB_OF_USEROBJECTS>77
MB_ObjectInit(&MB_DEVID.User[77], MODBUS_USEROBJECT_77_NAME); MB_ObjectInit(&MB_DEVID.User[77], MODBUS_USEROBJECT_77_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_78_NAME #if defined(MODBUS_USEROBJECT_78_NAME) && MODBUS_NUMB_OF_USEROBJECTS>78
MB_ObjectInit(&MB_DEVID.User[78], MODBUS_USEROBJECT_78_NAME); MB_ObjectInit(&MB_DEVID.User[78], MODBUS_USEROBJECT_78_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_79_NAME #if defined(MODBUS_USEROBJECT_79_NAME) && MODBUS_NUMB_OF_USEROBJECTS>79
MB_ObjectInit(&MB_DEVID.User[79], MODBUS_USEROBJECT_79_NAME); MB_ObjectInit(&MB_DEVID.User[79], MODBUS_USEROBJECT_79_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_80_NAME #if defined(MODBUS_USEROBJECT_80_NAME) && MODBUS_NUMB_OF_USEROBJECTS>80
MB_ObjectInit(&MB_DEVID.User[80], MODBUS_USEROBJECT_80_NAME); MB_ObjectInit(&MB_DEVID.User[80], MODBUS_USEROBJECT_80_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_81_NAME #if defined(MODBUS_USEROBJECT_81_NAME) && MODBUS_NUMB_OF_USEROBJECTS>81
MB_ObjectInit(&MB_DEVID.User[81], MODBUS_USEROBJECT_81_NAME); MB_ObjectInit(&MB_DEVID.User[81], MODBUS_USEROBJECT_81_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_82_NAME #if defined(MODBUS_USEROBJECT_82_NAME) && MODBUS_NUMB_OF_USEROBJECTS>82
MB_ObjectInit(&MB_DEVID.User[82], MODBUS_USEROBJECT_82_NAME); MB_ObjectInit(&MB_DEVID.User[82], MODBUS_USEROBJECT_82_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_83_NAME #if defined(MODBUS_USEROBJECT_83_NAME) && MODBUS_NUMB_OF_USEROBJECTS>83
MB_ObjectInit(&MB_DEVID.User[83], MODBUS_USEROBJECT_83_NAME); MB_ObjectInit(&MB_DEVID.User[83], MODBUS_USEROBJECT_83_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_84_NAME #if defined(MODBUS_USEROBJECT_84_NAME) && MODBUS_NUMB_OF_USEROBJECTS>84
MB_ObjectInit(&MB_DEVID.User[84], MODBUS_USEROBJECT_84_NAME); MB_ObjectInit(&MB_DEVID.User[84], MODBUS_USEROBJECT_84_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_85_NAME #if defined(MODBUS_USEROBJECT_85_NAME) && MODBUS_NUMB_OF_USEROBJECTS>85
MB_ObjectInit(&MB_DEVID.User[85], MODBUS_USEROBJECT_85_NAME); MB_ObjectInit(&MB_DEVID.User[85], MODBUS_USEROBJECT_85_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_86_NAME #if defined(MODBUS_USEROBJECT_86_NAME) && MODBUS_NUMB_OF_USEROBJECTS>86
MB_ObjectInit(&MB_DEVID.User[86], MODBUS_USEROBJECT_86_NAME); MB_ObjectInit(&MB_DEVID.User[86], MODBUS_USEROBJECT_86_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_87_NAME #if defined(MODBUS_USEROBJECT_87_NAME) && MODBUS_NUMB_OF_USEROBJECTS>87
MB_ObjectInit(&MB_DEVID.User[87], MODBUS_USEROBJECT_87_NAME); MB_ObjectInit(&MB_DEVID.User[87], MODBUS_USEROBJECT_87_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_88_NAME #if defined(MODBUS_USEROBJECT_88_NAME) && MODBUS_NUMB_OF_USEROBJECTS>88
MB_ObjectInit(&MB_DEVID.User[88], MODBUS_USEROBJECT_88_NAME); MB_ObjectInit(&MB_DEVID.User[88], MODBUS_USEROBJECT_88_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_89_NAME #if defined(MODBUS_USEROBJECT_89_NAME) && MODBUS_NUMB_OF_USEROBJECTS>89
MB_ObjectInit(&MB_DEVID.User[89], MODBUS_USEROBJECT_89_NAME); MB_ObjectInit(&MB_DEVID.User[89], MODBUS_USEROBJECT_89_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_90_NAME #if defined(MODBUS_USEROBJECT_90_NAME) && MODBUS_NUMB_OF_USEROBJECTS>90
MB_ObjectInit(&MB_DEVID.User[90], MODBUS_USEROBJECT_90_NAME); MB_ObjectInit(&MB_DEVID.User[90], MODBUS_USEROBJECT_90_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_91_NAME #if defined(MODBUS_USEROBJECT_91_NAME) && MODBUS_NUMB_OF_USEROBJECTS>91
MB_ObjectInit(&MB_DEVID.User[91], MODBUS_USEROBJECT_91_NAME); MB_ObjectInit(&MB_DEVID.User[91], MODBUS_USEROBJECT_91_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_92_NAME #if defined(MODBUS_USEROBJECT_92_NAME) && MODBUS_NUMB_OF_USEROBJECTS>92
MB_ObjectInit(&MB_DEVID.User[92], MODBUS_USEROBJECT_92_NAME); MB_ObjectInit(&MB_DEVID.User[92], MODBUS_USEROBJECT_92_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_93_NAME #if defined(MODBUS_USEROBJECT_93_NAME) && MODBUS_NUMB_OF_USEROBJECTS>93
MB_ObjectInit(&MB_DEVID.User[93], MODBUS_USEROBJECT_93_NAME); MB_ObjectInit(&MB_DEVID.User[93], MODBUS_USEROBJECT_93_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_94_NAME #if defined(MODBUS_USEROBJECT_94_NAME) && MODBUS_NUMB_OF_USEROBJECTS>94
MB_ObjectInit(&MB_DEVID.User[94], MODBUS_USEROBJECT_94_NAME); MB_ObjectInit(&MB_DEVID.User[94], MODBUS_USEROBJECT_94_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_95_NAME #if defined(MODBUS_USEROBJECT_95_NAME) && MODBUS_NUMB_OF_USEROBJECTS>95
MB_ObjectInit(&MB_DEVID.User[95], MODBUS_USEROBJECT_95_NAME); MB_ObjectInit(&MB_DEVID.User[95], MODBUS_USEROBJECT_95_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_96_NAME #if defined(MODBUS_USEROBJECT_96_NAME) && MODBUS_NUMB_OF_USEROBJECTS>96
MB_ObjectInit(&MB_DEVID.User[96], MODBUS_USEROBJECT_96_NAME); MB_ObjectInit(&MB_DEVID.User[96], MODBUS_USEROBJECT_96_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_97_NAME #if defined(MODBUS_USEROBJECT_97_NAME) && MODBUS_NUMB_OF_USEROBJECTS>97
MB_ObjectInit(&MB_DEVID.User[97], MODBUS_USEROBJECT_97_NAME); MB_ObjectInit(&MB_DEVID.User[97], MODBUS_USEROBJECT_97_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_98_NAME #if defined(MODBUS_USEROBJECT_98_NAME) && MODBUS_NUMB_OF_USEROBJECTS>98
MB_ObjectInit(&MB_DEVID.User[98], MODBUS_USEROBJECT_98_NAME); MB_ObjectInit(&MB_DEVID.User[98], MODBUS_USEROBJECT_98_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_99_NAME #if defined(MODBUS_USEROBJECT_99_NAME) && MODBUS_NUMB_OF_USEROBJECTS>99
MB_ObjectInit(&MB_DEVID.User[99], MODBUS_USEROBJECT_99_NAME); MB_ObjectInit(&MB_DEVID.User[99], MODBUS_USEROBJECT_99_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_100_NAME #if defined(MODBUS_USEROBJECT_100_NAME) && MODBUS_NUMB_OF_USEROBJECTS>100
MB_ObjectInit(&MB_DEVID.User[100], MODBUS_USEROBJECT_100_NAME); MB_ObjectInit(&MB_DEVID.User[100], MODBUS_USEROBJECT_100_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_101_NAME #if defined(MODBUS_USEROBJECT_101_NAME) && MODBUS_NUMB_OF_USEROBJECTS>101
MB_ObjectInit(&MB_DEVID.User[101], MODBUS_USEROBJECT_101_NAME); MB_ObjectInit(&MB_DEVID.User[101], MODBUS_USEROBJECT_101_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_102_NAME #if defined(MODBUS_USEROBJECT_102_NAME) && MODBUS_NUMB_OF_USEROBJECTS>102
MB_ObjectInit(&MB_DEVID.User[102], MODBUS_USEROBJECT_102_NAME); MB_ObjectInit(&MB_DEVID.User[102], MODBUS_USEROBJECT_102_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_103_NAME #if defined(MODBUS_USEROBJECT_103_NAME) && MODBUS_NUMB_OF_USEROBJECTS>103
MB_ObjectInit(&MB_DEVID.User[103], MODBUS_USEROBJECT_103_NAME); MB_ObjectInit(&MB_DEVID.User[103], MODBUS_USEROBJECT_103_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_104_NAME #if defined(MODBUS_USEROBJECT_104_NAME) && MODBUS_NUMB_OF_USEROBJECTS>104
MB_ObjectInit(&MB_DEVID.User[104], MODBUS_USEROBJECT_104_NAME); MB_ObjectInit(&MB_DEVID.User[104], MODBUS_USEROBJECT_104_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_105_NAME #if defined(MODBUS_USEROBJECT_105_NAME) && MODBUS_NUMB_OF_USEROBJECTS>105
MB_ObjectInit(&MB_DEVID.User[105], MODBUS_USEROBJECT_105_NAME); MB_ObjectInit(&MB_DEVID.User[105], MODBUS_USEROBJECT_105_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_106_NAME #if defined(MODBUS_USEROBJECT_106_NAME) && MODBUS_NUMB_OF_USEROBJECTS>106
MB_ObjectInit(&MB_DEVID.User[106], MODBUS_USEROBJECT_106_NAME); MB_ObjectInit(&MB_DEVID.User[106], MODBUS_USEROBJECT_106_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_107_NAME #if defined(MODBUS_USEROBJECT_107_NAME) && MODBUS_NUMB_OF_USEROBJECTS>107
MB_ObjectInit(&MB_DEVID.User[107], MODBUS_USEROBJECT_107_NAME); MB_ObjectInit(&MB_DEVID.User[107], MODBUS_USEROBJECT_107_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_108_NAME #if defined(MODBUS_USEROBJECT_108_NAME) && MODBUS_NUMB_OF_USEROBJECTS>108
MB_ObjectInit(&MB_DEVID.User[108], MODBUS_USEROBJECT_108_NAME); MB_ObjectInit(&MB_DEVID.User[108], MODBUS_USEROBJECT_108_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_109_NAME #if defined(MODBUS_USEROBJECT_109_NAME) && MODBUS_NUMB_OF_USEROBJECTS>109
MB_ObjectInit(&MB_DEVID.User[109], MODBUS_USEROBJECT_109_NAME); MB_ObjectInit(&MB_DEVID.User[109], MODBUS_USEROBJECT_109_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_110_NAME #if defined(MODBUS_USEROBJECT_110_NAME) && MODBUS_NUMB_OF_USEROBJECTS>110
MB_ObjectInit(&MB_DEVID.User[110], MODBUS_USEROBJECT_110_NAME); MB_ObjectInit(&MB_DEVID.User[110], MODBUS_USEROBJECT_110_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_111_NAME #if defined(MODBUS_USEROBJECT_111_NAME) && MODBUS_NUMB_OF_USEROBJECTS>111
MB_ObjectInit(&MB_DEVID.User[111], MODBUS_USEROBJECT_111_NAME); MB_ObjectInit(&MB_DEVID.User[111], MODBUS_USEROBJECT_111_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_112_NAME #if defined(MODBUS_USEROBJECT_112_NAME) && MODBUS_NUMB_OF_USEROBJECTS>112
MB_ObjectInit(&MB_DEVID.User[112], MODBUS_USEROBJECT_112_NAME); MB_ObjectInit(&MB_DEVID.User[112], MODBUS_USEROBJECT_112_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_113_NAME #if defined(MODBUS_USEROBJECT_113_NAME) && MODBUS_NUMB_OF_USEROBJECTS>113
MB_ObjectInit(&MB_DEVID.User[113], MODBUS_USEROBJECT_113_NAME); MB_ObjectInit(&MB_DEVID.User[113], MODBUS_USEROBJECT_113_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_114_NAME #if defined(MODBUS_USEROBJECT_114_NAME) && MODBUS_NUMB_OF_USEROBJECTS>114
MB_ObjectInit(&MB_DEVID.User[114], MODBUS_USEROBJECT_114_NAME); MB_ObjectInit(&MB_DEVID.User[114], MODBUS_USEROBJECT_114_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_115_NAME #if defined(MODBUS_USEROBJECT_115_NAME) && MODBUS_NUMB_OF_USEROBJECTS>115
MB_ObjectInit(&MB_DEVID.User[115], MODBUS_USEROBJECT_115_NAME); MB_ObjectInit(&MB_DEVID.User[115], MODBUS_USEROBJECT_115_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_116_NAME #if defined(MODBUS_USEROBJECT_116_NAME) && MODBUS_NUMB_OF_USEROBJECTS>116
MB_ObjectInit(&MB_DEVID.User[116], MODBUS_USEROBJECT_116_NAME); MB_ObjectInit(&MB_DEVID.User[116], MODBUS_USEROBJECT_116_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_117_NAME #if defined(MODBUS_USEROBJECT_117_NAME) && MODBUS_NUMB_OF_USEROBJECTS>117
MB_ObjectInit(&MB_DEVID.User[117], MODBUS_USEROBJECT_117_NAME); MB_ObjectInit(&MB_DEVID.User[117], MODBUS_USEROBJECT_117_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_118_NAME #if defined(MODBUS_USEROBJECT_118_NAME) && MODBUS_NUMB_OF_USEROBJECTS>118
MB_ObjectInit(&MB_DEVID.User[118], MODBUS_USEROBJECT_118_NAME); MB_ObjectInit(&MB_DEVID.User[118], MODBUS_USEROBJECT_118_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_119_NAME #if defined(MODBUS_USEROBJECT_119_NAME) && MODBUS_NUMB_OF_USEROBJECTS>119
MB_ObjectInit(&MB_DEVID.User[119], MODBUS_USEROBJECT_119_NAME); MB_ObjectInit(&MB_DEVID.User[119], MODBUS_USEROBJECT_119_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_120_NAME #if defined(MODBUS_USEROBJECT_120_NAME) && MODBUS_NUMB_OF_USEROBJECTS>120
MB_ObjectInit(&MB_DEVID.User[120], MODBUS_USEROBJECT_120_NAME); MB_ObjectInit(&MB_DEVID.User[120], MODBUS_USEROBJECT_120_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_121_NAME #if defined(MODBUS_USEROBJECT_121_NAME) && MODBUS_NUMB_OF_USEROBJECTS>121
MB_ObjectInit(&MB_DEVID.User[121], MODBUS_USEROBJECT_121_NAME); MB_ObjectInit(&MB_DEVID.User[121], MODBUS_USEROBJECT_121_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_122_NAME #if defined(MODBUS_USEROBJECT_122_NAME) && MODBUS_NUMB_OF_USEROBJECTS>122
MB_ObjectInit(&MB_DEVID.User[122], MODBUS_USEROBJECT_122_NAME); MB_ObjectInit(&MB_DEVID.User[122], MODBUS_USEROBJECT_122_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_123_NAME #if defined(MODBUS_USEROBJECT_123_NAME) && MODBUS_NUMB_OF_USEROBJECTS>123
MB_ObjectInit(&MB_DEVID.User[123], MODBUS_USEROBJECT_123_NAME); MB_ObjectInit(&MB_DEVID.User[123], MODBUS_USEROBJECT_123_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_124_NAME #if defined(MODBUS_USEROBJECT_124_NAME) && MODBUS_NUMB_OF_USEROBJECTS>124
MB_ObjectInit(&MB_DEVID.User[124], MODBUS_USEROBJECT_124_NAME); MB_ObjectInit(&MB_DEVID.User[124], MODBUS_USEROBJECT_124_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_125_NAME #if defined(MODBUS_USEROBJECT_125_NAME) && MODBUS_NUMB_OF_USEROBJECTS>125
MB_ObjectInit(&MB_DEVID.User[125], MODBUS_USEROBJECT_125_NAME); MB_ObjectInit(&MB_DEVID.User[125], MODBUS_USEROBJECT_125_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_126_NAME #if defined(MODBUS_USEROBJECT_126_NAME) && MODBUS_NUMB_OF_USEROBJECTS>126
MB_ObjectInit(&MB_DEVID.User[126], MODBUS_USEROBJECT_126_NAME); MB_ObjectInit(&MB_DEVID.User[126], MODBUS_USEROBJECT_126_NAME);
#endif #endif
#ifdef MODBUS_USEROBJECT_127_NAME #if defined(MODBUS_USEROBJECT_127_NAME) && MODBUS_NUMB_OF_USEROBJECTS>127
MB_ObjectInit(&MB_DEVID.User[127], MODBUS_USEROBJECT_127_NAME); MB_ObjectInit(&MB_DEVID.User[127], MODBUS_USEROBJECT_127_NAME);
#endif #endif
} }
#endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#else //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
/* Получить количество объектов в сообщении */
void MB_WriteSingleObjectToMessage(char *mbdata, unsigned *ind, MB_DeviceObjectTypeDef *obj) {}
void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj) {}
uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg) {return 0;}
void MB_DeviceInentificationInit(void) {}
#endif

View File

@@ -1,8 +1,8 @@
/** /**
****************************************************************************** *******************************************************************************
* @file modbus_diag.c * @file modbus_diag.c
* @brief Реализация диагностики устройства Modbus * @brief Реализация диагностики устройства Modbus
****************************************************************************** *******************************************************************************
* @details * @details
Модуль обработки запросов диагностической информации (0x08): Модуль обработки запросов диагностической информации (0x08):
- Полная поддержка всех подфункций диагностики согласно спецификации Modbus - Полная поддержка всех подфункций диагностики согласно спецификации Modbus
@@ -74,8 +74,8 @@ int MB_Diagnostics_GetBit(int bit_num)
*/ */
uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg)
{ {
uint16_t sub_function = modbus_msg->DATA[0]; uint16_t sub_function = modbus_msg->MbData[0];
uint16_t request_data = modbus_msg->DATA[1]; uint16_t request_data = modbus_msg->MbData[1];
// Если устройство в режиме Listen Only, отвечаем только на sub-function 0x01 // Если устройство в режиме Listen Only, отвечаем только на sub-function 0x01
if (MB_DIAG.DeviceMode == MODBUS_LISTEN_ONLY_MODE && sub_function != 0x0001) if (MB_DIAG.DeviceMode == MODBUS_LISTEN_ONLY_MODE && sub_function != 0x0001)
@@ -87,8 +87,8 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg)
{ {
case 0x0000: // Return Query Data case 0x0000: // Return Query Data
// Эхо-ответ с теми же данными // Эхо-ответ с теми же данными
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = request_data; modbus_msg->MbData[1] = request_data;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
@@ -114,21 +114,21 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg)
MB_DIAG.Counters.BusCharacterOverrun = 0; MB_DIAG.Counters.BusCharacterOverrun = 0;
} }
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = request_data; modbus_msg->MbData[1] = request_data;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x0002: // Return Diagnostic Register case 0x0002: // Return Diagnostic Register
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.DiagnosticRegister; modbus_msg->MbData[1] = MB_DIAG.DiagnosticRegister;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x0003: // Change ASCII Input Delimiter case 0x0003: // Change ASCII Input Delimiter
// В RTU режиме не поддерживается // В RTU режиме не поддерживается
modbus_msg->Func_Code |= ERR_VALUES_START; modbus_msg->FuncCode |= FC_ERR_VALUES_START;
modbus_msg->Except_Code = ILLEGAL_FUNCTION; modbus_msg->Except_Code = ET_ILLEGAL_FUNCTION;
return 0; return 0;
case 0x0004: // Force Listen Only Mode case 0x0004: // Force Listen Only Mode
@@ -138,56 +138,56 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg)
case 0x000A: // Clear Counters and Diagnostic Register case 0x000A: // Clear Counters and Diagnostic Register
MB_DiagnosticsInit(); // Полный сброс MB_DiagnosticsInit(); // Полный сброс
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = 0; modbus_msg->MbData[1] = 0;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x000B: // Return Bus Message Count case 0x000B: // Return Bus Message Count
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.Counters.BusMessage; modbus_msg->MbData[1] = MB_DIAG.Counters.BusMessage;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x000C: // Return Bus Communication Error Count case 0x000C: // Return Bus Communication Error Count
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.Counters.BusCommunicationErr; modbus_msg->MbData[1] = MB_DIAG.Counters.BusCommunicationErr;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x000D: // Return Bus Exception Error Count case 0x000D: // Return Bus Exception Error Count
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.Counters.BusExceptionErr; modbus_msg->MbData[1] = MB_DIAG.Counters.BusExceptionErr;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x000E: // Return Server Message Count case 0x000E: // Return Server Message Count
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveMessage; modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveMessage;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x000F: // Return Slave No Response Count case 0x000F: // Return Slave No Response Count
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveNoResponse; modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveNoResponse;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x0010: // Return Slave NAK Count case 0x0010: // Return Slave NAK Count
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveNAK; modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveNAK;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x0011: // Return Slave Busy Count case 0x0011: // Return Slave Busy Count
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveBusy; modbus_msg->MbData[1] = MB_DIAG.Counters.SlaveBusy;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
case 0x0012: // Return Bus Character Overrun Count case 0x0012: // Return Bus Character Overrun Count
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = MB_DIAG.Counters.BusCharacterOverrun; modbus_msg->MbData[1] = MB_DIAG.Counters.BusCharacterOverrun;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
@@ -195,14 +195,14 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg)
MB_DIAG.Counters.BusCharacterOverrun = 0; MB_DIAG.Counters.BusCharacterOverrun = 0;
// Сбрасываем флаг переполнения в DiagnosticRegister // Сбрасываем флаг переполнения в DiagnosticRegister
MB_DIAG.DiagnosticRegister &= ~(1<<0); MB_DIAG.DiagnosticRegister &= ~(1<<0);
modbus_msg->DATA[0] = sub_function; modbus_msg->MbData[0] = sub_function;
modbus_msg->DATA[1] = 0; modbus_msg->MbData[1] = 0;
modbus_msg->ByteCnt = 4; modbus_msg->ByteCnt = 4;
break; break;
default: default:
modbus_msg->Func_Code |= ERR_VALUES_START; modbus_msg->FuncCode |= FC_ERR_VALUES_START;
modbus_msg->Except_Code = ILLEGAL_FUNCTION; modbus_msg->Except_Code = ET_ILLEGAL_FUNCTION;
return 0; return 0;
} }
@@ -293,20 +293,4 @@ MB_DeviceModeTypeDef MB_GetDeviceMode(void)
return MB_DIAG.DeviceMode; return MB_DIAG.DeviceMode;
} }
#else //MODBUS_ENABLE_DIAGNOSTICS #endif //MODBUS_ENABLE_DIAGNOSTICS
void MB_DiagnosticsInit(void) {}
int MB_Diagnostics_WriteBit(int bit_num, int bit_state) {return 0;}
int MB_Diagnostics_GetBit(int bit_num) {return 0;}
uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg) {return 0;}
void MB_Diagnostics_BusMessageCnt(void) {}
void MB_Diagnostics_CommunicationErrorCnt(void) {}
void MB_Diagnostics_ExceptionErrorCnt(void) {}
void MB_Diagnostics_CharacterOverrunCnt(void) {}
void MB_Diagnostics_SlaveMessageCnt(void) {}
void MB_Diagnostics_SlaveNoResponseCnt(void) {}
void MB_Diagnostics_SlaveNAKCnt(void) {}
void MB_Diagnostics_SlaveBusyCnt(void) {}
MB_DeviceModeTypeDef MB_GetDeviceMode(void) {return MODBUS_NORMAL_MODE;}
#endif

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"
@@ -29,7 +28,7 @@
* @brief Записать регистр хранения по глобальному адресу. * @brief Записать регистр хранения по глобальному адресу.
* @param Addr Адрес регистра. * @param Addr Адрес регистра.
* @param WriteVal Число для записи. * @param WriteVal Число для записи.
* @return ExceptionCode Код исключения если регистра по адресу не существует, и NO_ERRORS если все ок. * @return ExceptionCode Код исключения если регистра по адресу не существует, и ET_NO_ERRORS если все ок.
* *
* @details Позволяет обратиться к любому регистру по его глобальному адрессу. * @details Позволяет обратиться к любому регистру по его глобальному адрессу.
Вне зависимости от того как регистры размещены в памяти. Вне зависимости от того как регистры размещены в памяти.
@@ -37,12 +36,12 @@
MB_ExceptionTypeDef MB_Holding_Write_Global(uint16_t Addr, uint16_t WriteVal) MB_ExceptionTypeDef MB_Holding_Write_Global(uint16_t Addr, uint16_t WriteVal)
{ {
//---------CHECK FOR ERRORS---------- //---------CHECK FOR ERRORS----------
MB_ExceptionTypeDef Exception = NO_ERRORS; MB_ExceptionTypeDef Exception = ET_NO_ERRORS;
uint16_t *pHoldRegs; uint16_t *pHoldRegs;
//------------WRITE COIL------------- //------------WRITE COIL-------------
Exception = MB_DefineRegistersAddress(&pHoldRegs, Addr, 1, RegisterType_Holding); Exception = MB_DefineRegistersAddress(&pHoldRegs, Addr, 1, RegisterType_Holding);
if(Exception == NO_ERRORS) if(Exception == ET_NO_ERRORS)
{ {
*(pHoldRegs) = WriteVal; *(pHoldRegs) = WriteVal;
} }
@@ -72,7 +71,7 @@ uint16_t MB_Holding_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception)
if(Exception) // if exception is not given to func fill it if(Exception) // if exception is not given to func fill it
*Exception = Exception_tmp; *Exception = Exception_tmp;
if(Exception_tmp == NO_ERRORS) if(Exception_tmp == ET_NO_ERRORS)
{ {
return *(pHoldRegs); return *(pHoldRegs);
} }
@@ -96,7 +95,7 @@ uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
// get origin address for data // get origin address for data
uint16_t *pHoldRegs; uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров
if(modbus_msg->Except_Code != NO_ERRORS) if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0; return 0;
@@ -107,7 +106,7 @@ uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg)
int i; int i;
for (i = 0; i<modbus_msg->Qnt; i++) for (i = 0; i<modbus_msg->Qnt; i++)
{ {
modbus_msg->DATA[i] = *(pHoldRegs++); modbus_msg->MbData[i] = *(pHoldRegs++);
} }
return 1; return 1;
} }
@@ -123,7 +122,7 @@ uint8_t MB_Process_Write_Single_Reg(RS_MsgTypeDef *modbus_msg)
// get origin address for data // get origin address for data
uint16_t *pHoldRegs; uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, 1, RegisterType_Holding); // определение адреса регистров
if(modbus_msg->Except_Code != NO_ERRORS) if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0; return 0;
//-----------WRITTING REG------------ //-----------WRITTING REG------------
@@ -148,24 +147,15 @@ uint8_t MB_Process_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg)
// get origin address for data // get origin address for data
uint16_t *pHoldRegs; uint16_t *pHoldRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров modbus_msg->Except_Code = MB_DefineRegistersAddress(&pHoldRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Holding); // определение адреса регистров
if(modbus_msg->Except_Code != NO_ERRORS) if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0; return 0;
//-----------WRITTING REGS----------- //-----------WRITTING REGS-----------
for (int i = 0; i<modbus_msg->Qnt; i++) for (int i = 0; i<modbus_msg->Qnt; i++)
{ {
*(pHoldRegs++) = modbus_msg->DATA[i]; *(pHoldRegs++) = modbus_msg->MbData[i];
} }
return 1; return 1;
} }
#endif //MODBUS_ENABLE_HOLDINGS
#else //MODBUS_ENABLE_HOLDINGS
MB_ExceptionTypeDef MB_Holding_Write_Global(uint16_t Addr, uint16_t WriteVal) {return ILLEGAL_FUNCTION;}
uint16_t MB_Holding_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;}
uint8_t MB_Process_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg) {return 0;}
uint8_t MB_Process_Write_Single_Reg(RS_MsgTypeDef *modbus_msg) {return 0;}
uint8_t MB_Process_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg) {return 0;}
#endif

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"
@@ -19,7 +24,7 @@
* @brief Записать входной регистр по глобальному адресу. * @brief Записать входной регистр по глобальному адресу.
* @param Addr Адрес регистра. * @param Addr Адрес регистра.
* @param WriteVal Число для записи. * @param WriteVal Число для записи.
* @return ExceptionCode Код исключения если регистра по адресу не существует, и NO_ERRORS если все ок. * @return ExceptionCode Код исключения если регистра по адресу не существует, и ET_NO_ERRORS если все ок.
* *
* @details Позволяет обратиться к любому регистру по его глобальному адрессу. * @details Позволяет обратиться к любому регистру по его глобальному адрессу.
Вне зависимости от того как регистры размещены в памяти. Вне зависимости от того как регистры размещены в памяти.
@@ -27,12 +32,12 @@
MB_ExceptionTypeDef MB_Input_Write_Global(uint16_t Addr, uint16_t WriteVal) MB_ExceptionTypeDef MB_Input_Write_Global(uint16_t Addr, uint16_t WriteVal)
{ {
//---------CHECK FOR ERRORS---------- //---------CHECK FOR ERRORS----------
MB_ExceptionTypeDef Exception = NO_ERRORS; MB_ExceptionTypeDef Exception = ET_NO_ERRORS;
uint16_t *pInRegs; uint16_t *pInRegs;
//------------WRITE COIL------------- //------------WRITE COIL-------------
Exception = MB_DefineRegistersAddress(&pInRegs, Addr, 1, RegisterType_Input); Exception = MB_DefineRegistersAddress(&pInRegs, Addr, 1, RegisterType_Input);
if(Exception == NO_ERRORS) if(Exception == ET_NO_ERRORS)
{ {
*(pInRegs) = WriteVal; *(pInRegs) = WriteVal;
} }
@@ -62,7 +67,7 @@ uint16_t MB_Input_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception)
if(Exception) // if exception is not given to func fill it if(Exception) // if exception is not given to func fill it
*Exception = Exception_tmp; *Exception = Exception_tmp;
if(Exception_tmp == NO_ERRORS) if(Exception_tmp == ET_NO_ERRORS)
{ {
return *(pInRegs); return *(pInRegs);
} }
@@ -85,7 +90,7 @@ uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
// get origin address for data // get origin address for data
uint16_t *pInRegs; uint16_t *pInRegs;
modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров modbus_msg->Except_Code = MB_DefineRegistersAddress(&pInRegs, modbus_msg->Addr, modbus_msg->Qnt, RegisterType_Input); // определение адреса регистров
if(modbus_msg->Except_Code != NO_ERRORS) if(modbus_msg->Except_Code != ET_NO_ERRORS)
return 0; return 0;
@@ -97,17 +102,11 @@ uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg)
for (i = 0; i<modbus_msg->Qnt; i++) for (i = 0; i<modbus_msg->Qnt; i++)
{ {
if(*((int16_t *)pInRegs) > 0) if(*((int16_t *)pInRegs) > 0)
modbus_msg->DATA[i] = (*pInRegs++); modbus_msg->MbData[i] = (*pInRegs++);
else else
modbus_msg->DATA[i] = (*pInRegs++); modbus_msg->MbData[i] = (*pInRegs++);
} }
return 1; return 1;
} }
#else //MODBUS_ENABLE_INPUTS #endif //MODBUS_ENABLE_INPUTS
MB_ExceptionTypeDef MB_Input_Write_Global(uint16_t Addr, uint16_t WriteVal) {return ILLEGAL_FUNCTION;}
uint16_t MB_Input_Read_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception) {return 0;}
uint8_t MB_Process_Read_Input_Regs(RS_MsgTypeDef *modbus_msg) {return 0;}
#endif

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 Указатель для значения регистра
@@ -29,9 +66,9 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1
return 0; return 0;
// Проверяем что ответ связан с регистрами // Проверяем что ответ связан с регистрами
if((modbus_msg->Func_Code != MB_R_DISC_IN) && if((modbus_msg->FuncCode != FC_R_DISC_IN) &&
(modbus_msg->Func_Code != MB_R_HOLD_REGS) && (modbus_msg->FuncCode != FC_R_HOLD_REGS) &&
(modbus_msg->Func_Code != MB_R_IN_REGS)) (modbus_msg->FuncCode != FC_R_IN_REGS))
{ {
return 0; return 0;
} }
@@ -48,13 +85,38 @@ int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint1
return 0; return 0;
// Получаем значение регистра // Получаем значение регистра
*reg_value = modbus_msg->DATA[reg_index]; *reg_value = modbus_msg->MbData[reg_index];
return 1; return 1;
} }
/**
* @brief Получить состояние ВСЕХ coil в ответе
* @param modbus_msg Указатель на структуру сообщения
* @param coil_arr Указатель для массив доя сохранения состояний coil (1 - ON, 0 - OFF)
* @return 1 - успех, 0 - ошибка или coil_addr вне диапазона запроса
*/
int MB_RespGet_CoilAll(RS_MsgTypeDef *modbus_msg, int *coil_arr)
{
if(modbus_msg == NULL || coil_arr == NULL)
return 0;
int read_cnt = 0;
int i = 0;
for(int addr = modbus_msg->Addr; addr < modbus_msg->Addr + modbus_msg->Qnt; addr++)
{
if(MB_RespGet_CoilState(modbus_msg, addr, &coil_arr[i]))
{
read_cnt++;
}
i++;
}
return 1;
}
/** /**
* @brief Получить состояние coil в ответе по его адресу * @brief Получить состояние coil в ответе по его адресу
* @param modbus_msg Указатель на структуру сообщения * @param modbus_msg Указатель на структуру сообщения
@@ -68,7 +130,7 @@ int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coi
return 0; return 0;
// Проверяем что ответ связан с коилами // Проверяем что ответ связан с коилами
if(modbus_msg->Func_Code != MB_R_COILS) if(modbus_msg->FuncCode != FC_R_COILS)
{ {
return 0; return 0;
} }
@@ -91,9 +153,9 @@ 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->DATA[data_index] >> (bit_index+8)) & 0x01; *coil_state = (modbus_msg->MbData[data_index] >> (bit_index+8)) & 0x01;
else else
*coil_state = (modbus_msg->DATA[data_index] >> bit_index) & 0x01; *coil_state = ((modbus_msg->MbData[data_index]&0xFF) >> (bit_index-8)) & 0x01;
return 1; return 1;
@@ -112,7 +174,7 @@ int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg)
return 0; return 0;
} }
// Проверяем что ответ связан с диагностикой // Проверяем что ответ связан с диагностикой
if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
{ {
return 0; return 0;
} }
@@ -134,12 +196,12 @@ int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_d
return 0; return 0;
// Проверяем что ответ связан с диагностикой // Проверяем что ответ связан с диагностикой
if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
{ {
return 0; return 0;
} }
uint8_t *data = (uint8_t*)modbus_msg->DATA; uint8_t *data = (uint8_t*)modbus_msg->MbData;
unsigned ind = 0; unsigned ind = 0;
for(int i = 0; i < modbus_msg->DevId.NumbOfObj; i++) for(int i = 0; i < modbus_msg->DevId.NumbOfObj; i++)
@@ -185,7 +247,7 @@ int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_
return 0; return 0;
// Проверяем что ответ связан с диагностикой // Проверяем что ответ связан с диагностикой
if(modbus_msg->Func_Code != MB_R_DEVICE_INFO) if(modbus_msg->FuncCode != FC_R_DEVICE_ID)
{ {
return 0; return 0;
} }
@@ -193,7 +255,7 @@ int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_
if(index >= modbus_msg->DevId.NumbOfObj) if(index >= modbus_msg->DevId.NumbOfObj)
return 0; return 0;
uint8_t *data = (uint8_t*)modbus_msg->DATA; uint8_t *data = (uint8_t*)modbus_msg->MbData;
unsigned ind = 0; unsigned ind = 0;
for(int i = 0; i <= index; i++) for(int i = 0; i <= index; i++)
@@ -227,7 +289,7 @@ int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_
/** /**
* @brief Получить данные диагностики из сообщения (DATA[1]) * @brief Получить данные диагностики из сообщения (MbData[1])
* @param modbus_msg Указатель на структуру сообщения * @param modbus_msg Указатель на структуру сообщения
* @param data Указатель куда положить данные * @param data Указатель куда положить данные
* @return 1 - успех, 0 - ошибка * @return 1 - успех, 0 - ошибка
@@ -238,18 +300,22 @@ int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data)
return 0; return 0;
// Проверяем что ответ связан с диагностикой // Проверяем что ответ связан с диагностикой
if(modbus_msg->Func_Code != MB_R_DIAGNOSTIC) if(modbus_msg->FuncCode != FC_R_DIAGNOSTICS)
{ {
return 0; return 0;
} }
*data = modbus_msg->DATA[1]; *data = modbus_msg->MbData[1];
return 1; return 1;
} }
//-------------------------------------------------------------------
//-----------------------------INTERNAL------------------------------
/** /**
* @brief Определить размер модбас запроса (МАСТЕР версия). * @brief Определить размер модбас запроса (МАСТЕР версия).
* @param hRS Указатель на хендлер RS. * @param hRS Указатель на хендлер RS.
@@ -264,24 +330,24 @@ static int MB_Define_Size_of_Function(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *
// Master mode - calculating response size from slave // Master mode - calculating response size from slave
if (modbus_msg->Func_Code & ERR_VALUES_START) if (modbus_msg->FuncCode & FC_ERR_VALUES_START)
{ {
// Error response: [Addr][Func|0x80][ExceptCode][CRC] // Error response: [Addr][Func|0x80][ExceptCode][CRC]
mb_func_size = -1; // Only Exception Code mb_func_size = -1; // Only Exception Code
} }
else if (modbus_msg->Func_Code == MB_R_DIAGNOSTIC) else if (modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{ {
// Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO] // Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
mb_func_size = 1; mb_func_size = 1;
} }
else if (modbus_msg->Func_Code == MB_R_DEVICE_INFO) else if (modbus_msg->FuncCode == FC_R_DEVICE_ID)
{ {
// Device identifications: variable size, need to read first to determine // Device identifications: variable size, need to read first to determine
mb_func_size = 0; // Will be determined after reading header mb_func_size = 0; // Will be determined after reading header
} }
else else
{ {
switch (modbus_msg->Func_Code & ~ERR_VALUES_START) switch (modbus_msg->FuncCode & ~FC_ERR_VALUES_START)
{ {
case 0x01: // Read Coils case 0x01: // Read Coils
case 0x02: // Read Discrete Inputs case 0x02: // Read Discrete Inputs
@@ -329,25 +395,30 @@ RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgType
modbus_uart_buff[ind++] = modbus_msg->MbAddr; modbus_uart_buff[ind++] = modbus_msg->MbAddr;
// set function code // set function code
modbus_uart_buff[ind++] = modbus_msg->Func_Code; modbus_uart_buff[ind++] = modbus_msg->FuncCode;
if(modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur if(modbus_msg->FuncCode < FC_ERR_VALUES_START) // if no error occur
{ {
// fill modbus header // fill modbus header
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // device identifications request if(0) {}
#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // device identifications request
{ {
modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type; modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type;
modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId; modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId;
modbus_uart_buff[ind++] = modbus_msg->DevId.NextObjId; modbus_uart_buff[ind++] = modbus_msg->DevId.NextObjId;
} }
else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC) #endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#ifdef MODBUS_ENABLE_DIAGNOSTICS
else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{ {
// Diagnostics: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO] // Diagnostics: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
modbus_uart_buff[ind++] = modbus_msg->DATA[0] >> 8; // Sub-function HI modbus_uart_buff[ind++] = modbus_msg->MbData[0] >> 8; // Sub-function HI
modbus_uart_buff[ind++] = modbus_msg->DATA[0] & 0xFF; // Sub-function LO modbus_uart_buff[ind++] = modbus_msg->MbData[0] & 0xFF; // Sub-function LO
modbus_uart_buff[ind++] = modbus_msg->DATA[1] >> 8; // Data HI modbus_uart_buff[ind++] = modbus_msg->MbData[1] >> 8; // Data HI
modbus_uart_buff[ind++] = modbus_msg->DATA[1] & 0xFF; // Data LO modbus_uart_buff[ind++] = modbus_msg->MbData[1] & 0xFF; // Data LO
} }
#endif //MODBUS_ENABLE_DIAGNOSTICS
else // classic modbus request else // classic modbus request
{ {
// set address // set address
@@ -359,12 +430,12 @@ RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgType
modbus_uart_buff[ind++] = modbus_msg->Qnt & 0xFF; modbus_uart_buff[ind++] = modbus_msg->Qnt & 0xFF;
// for write multiple functions // for write multiple functions
if((modbus_msg->Func_Code == 0x0F) || (modbus_msg->Func_Code == 0x10)) if((modbus_msg->FuncCode == 0x0F) || (modbus_msg->FuncCode == 0x10))
{ {
modbus_uart_buff[ind++] = modbus_msg->ByteCnt; modbus_uart_buff[ind++] = modbus_msg->ByteCnt;
// write data bytes // write data bytes
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData;
for(int i = 0; i < modbus_msg->ByteCnt; i++) for(int i = 0; i < modbus_msg->ByteCnt; i++)
{ {
modbus_uart_buff[ind++] = tmp_data_addr[i]; modbus_uart_buff[ind++] = tmp_data_addr[i];
@@ -379,7 +450,7 @@ RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgType
//---------------CRC---------------- //---------------CRC----------------
//---------[last 2 bytes]---------- //---------[last 2 bytes]----------
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
modbus_msg->MB_CRC = CRC_VALUE; modbus_msg->MbCRC = CRC_VALUE;
modbus_uart_buff[ind++] = CRC_VALUE & 0xFF; modbus_uart_buff[ind++] = CRC_VALUE & 0xFF;
modbus_uart_buff[ind++] = CRC_VALUE >> 8; modbus_uart_buff[ind++] = CRC_VALUE >> 8;
@@ -404,15 +475,17 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe
modbus_msg->MbAddr = modbus_uart_buff[ind++]; modbus_msg->MbAddr = modbus_uart_buff[ind++];
// get function code (check if error response) // get function code (check if error response)
modbus_msg->Func_Code = modbus_uart_buff[ind++]; modbus_msg->FuncCode = modbus_uart_buff[ind++];
if(modbus_msg->Func_Code & ERR_VALUES_START) // error response if(modbus_msg->FuncCode & FC_ERR_VALUES_START) // error response
{ {
modbus_msg->Except_Code = modbus_uart_buff[ind++]; modbus_msg->Except_Code = modbus_uart_buff[ind++];
} }
else if(modbus_msg->Func_Code < ERR_VALUES_START) // normal response else if(modbus_msg->FuncCode < FC_ERR_VALUES_START) // normal response
{ {
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // device identifications response if(0) {}
#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // device identifications response
{ {
modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++]; modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++]; modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++];
@@ -424,7 +497,7 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe
modbus_msg->ByteCnt = 0; modbus_msg->ByteCnt = 0;
// Парсинг объектов идентификации устройства // Парсинг объектов идентификации устройства
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData;
int data_index = 0; int data_index = 0;
for(int obj = 0; obj < modbus_msg->DevId.NumbOfObj; obj++) for(int obj = 0; obj < modbus_msg->DevId.NumbOfObj; obj++)
@@ -446,24 +519,27 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe
modbus_msg->ByteCnt += (2 + object_length); // ID + длина + данные modbus_msg->ByteCnt += (2 + object_length); // ID + длина + данные
} }
} }
else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC) #endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#ifdef MODBUS_ENABLE_DIAGNOSTICS
else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{ {
// Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO] // Diagnostics response: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
modbus_msg->DATA[0] = modbus_uart_buff[ind++] << 8; modbus_msg->MbData[0] = modbus_uart_buff[ind++] << 8;
modbus_msg->DATA[0] |= modbus_uart_buff[ind++]; modbus_msg->MbData[0] |= modbus_uart_buff[ind++];
modbus_msg->DATA[1] = modbus_uart_buff[ind++] << 8; modbus_msg->MbData[1] = modbus_uart_buff[ind++] << 8;
modbus_msg->DATA[1] |= modbus_uart_buff[ind++]; modbus_msg->MbData[1] |= modbus_uart_buff[ind++];
} }
#endif //MODBUS_ENABLE_DIAGNOSTICS
else // classic modbus response else // classic modbus response
{ {
// get byte count for read functions // get byte count for read functions
if((modbus_msg->Func_Code == 0x01) || (modbus_msg->Func_Code == 0x02) || if((modbus_msg->FuncCode == 0x01) || (modbus_msg->FuncCode == 0x02) ||
(modbus_msg->Func_Code == 0x03) || (modbus_msg->Func_Code == 0x04)) (modbus_msg->FuncCode == 0x03) || (modbus_msg->FuncCode == 0x04))
{ {
modbus_msg->ByteCnt = modbus_uart_buff[ind++]; modbus_msg->ByteCnt = modbus_uart_buff[ind++];
// read data bytes // read data bytes
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData;
for(int i = 0; i < modbus_msg->ByteCnt; i++) for(int i = 0; i < modbus_msg->ByteCnt; i++)
{ {
if(i % 2 == 0) // HI byte if(i % 2 == 0) // HI byte
@@ -473,8 +549,8 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe
} }
} }
// for write functions - echo address and quantity // for write functions - echo address and quantity
else if((modbus_msg->Func_Code == 0x05) || (modbus_msg->Func_Code == 0x06) || else if((modbus_msg->FuncCode == 0x05) || (modbus_msg->FuncCode == 0x06) ||
(modbus_msg->Func_Code == 0x0F) || (modbus_msg->Func_Code == 0x10)) (modbus_msg->FuncCode == 0x0F) || (modbus_msg->FuncCode == 0x10))
{ {
modbus_msg->Addr = modbus_uart_buff[ind++] << 8; modbus_msg->Addr = modbus_uart_buff[ind++] << 8;
modbus_msg->Addr |= modbus_uart_buff[ind++]; modbus_msg->Addr |= modbus_uart_buff[ind++];
@@ -488,10 +564,10 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe
//---------------CRC---------------- //---------------CRC----------------
//----------[last 2 bytes]---------- //----------[last 2 bytes]----------
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
modbus_msg->MB_CRC = modbus_uart_buff[ind++]; modbus_msg->MbCRC = modbus_uart_buff[ind++];
modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8; modbus_msg->MbCRC |= modbus_uart_buff[ind++] << 8;
if(modbus_msg->MB_CRC != CRC_VALUE) if(modbus_msg->MbCRC != CRC_VALUE)
{ {
TrackerCnt_Err(hmodbus->rs_err); TrackerCnt_Err(hmodbus->rs_err);
return RS_PARSE_MSG_ERR; return RS_PARSE_MSG_ERR;
@@ -507,58 +583,58 @@ RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDe
/** @brief Сформировать запрос на чтение коилов */ /** @brief Сформировать запрос на чтение коилов */
RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0};
return msg; return msg;
} }
/** @brief Сформировать запрос на чтение дискретных регистров */ /** @brief Сформировать запрос на чтение дискретных регистров */
RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_DISC_IN, {0}, start_addr, quantity, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_DISC_IN, {0}, start_addr, quantity, 0, {0}, 0, 0};
return msg; return msg;
} }
/** @brief Сформировать запрос на чтение холдинг регистров */ /** @brief Сформировать запрос на чтение холдинг регистров */
RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
return msg; return msg;
} }
/** @brief Сформировать запрос на чтение инпут регистров */ /** @brief Сформировать запрос на чтение инпут регистров */
RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_IN_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_IN_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
return msg; return msg;
} }
/** @brief Сформировать запрос на запись одного коила */ /** @brief Сформировать запрос на запись одного коила */
RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value) RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_W_COIL, {0}, coil_addr, (value ? 0xFF00 : 0x0000), 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_W_COIL, {0}, coil_addr, (value ? 0xFF00 : 0x0000), 0, {0}, 0, 0};
return msg; return msg;
} }
/** @brief Сформировать запрос на запись одного регистра */ /** @brief Сформировать запрос на запись одного регистра */
RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value) RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_W_HOLD_REG, {0}, reg_addr, value, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_W_HOLD_REG, {0}, reg_addr, value, 0, {0}, 0, 0};
return msg; return msg;
} }
/** @brief Сформировать запрос на запись нескольких регистров */ /** @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 MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint8_t *coils_data)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_W_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_W_COILS, {0}, start_addr, quantity, 0, {0}, 0, 0};
// Calculate byte count and prepare data // Calculate byte count and prepare data
uint8_t byte_count = (quantity + 7) / 8; uint8_t byte_count = (quantity + 7) / 8;
msg.ByteCnt = byte_count; msg.ByteCnt = byte_count;
// Copy coil data to message DATA array // Copy coil data to message MbData array
for(int i = 0; i < byte_count; i++) { for(int i = 0; i < byte_count; i++) {
if(i < DATA_SIZE) { if(i < DATA_SIZE) {
msg.DATA[i] = coils_data[i]; msg.MbData[i] = coils_data[i];
} }
} }
@@ -568,13 +644,13 @@ RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start
/** @brief Сформировать запрос на запись нескольких коилов */ /** @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 MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint16_t *regs_data)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_W_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_W_HOLD_REGS, {0}, start_addr, quantity, 0, {0}, 0, 0};
msg.ByteCnt = quantity * 2; // Each register is 2 bytes msg.ByteCnt = quantity * 2; // Each register is 2 bytes
// Copy register data to message DATA array // Copy register data to message MbData array
for(int i = 0; i < quantity && i < DATA_SIZE; i++) { for(int i = 0; i < quantity && i < DATA_SIZE; i++) {
msg.DATA[i] = regs_data[i]; msg.MbData[i] = regs_data[i];
} }
return msg; return msg;
@@ -583,7 +659,7 @@ RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_
//---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ----------- //---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ-----------
RS_MsgTypeDef MB_REQUEST_DIAGNOSTIC_QUERY(uint8_t slave_addr, uint16_t sub_function, uint16_t data) RS_MsgTypeDef MB_REQUEST_DIAGNOSTIC_QUERY(uint8_t slave_addr, uint16_t sub_function, uint16_t data)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_DIAGNOSTIC, {0}, 0, 0, 0, {sub_function, data}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_DIAGNOSTICS, {0}, 0, 0, 0, {sub_function, data}, 0, 0};
return msg; return msg;
} }
RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr) RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr)
@@ -654,76 +730,26 @@ RS_MsgTypeDef MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(uint8_t slave_addr)
//---------ИДЕНТИФИКАТОРЫ МОДБАС----------- //---------ИДЕНТИФИКАТОРЫ МОДБАС-----------
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_BASIC(uint8_t slave_addr) RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_BASIC(uint8_t slave_addr)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x01, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x01, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
return msg; return msg;
} }
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_REGULAR(uint8_t slave_addr) RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_REGULAR(uint8_t slave_addr)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x02, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x02, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
return msg; return msg;
} }
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_EXTENDED(uint8_t slave_addr) RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_EXTENDED(uint8_t slave_addr)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x03, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x03, 0x00, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
return msg; return msg;
} }
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t object_id) RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t object_id)
{ {
RS_MsgTypeDef msg = {slave_addr, MB_R_DEVICE_INFO, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0}; RS_MsgTypeDef msg = {slave_addr, FC_R_DEVICE_ID, {0x0E, 0x04, object_id, 0, 0, 0}, 0, 0, 0, {0}, 0, 0};
return msg; return msg;
} }
#endif //MODBUS_ENABLE_MASTER
#else
RS_MsgTypeDef msg_dummy = {0};
int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value) {return 0;}
int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state) {return 0;}
int MB_RespGet_NumberOfObjects(RS_MsgTypeDef *modbus_msg) {return 0;}
int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length) {return 0;}
int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length) {return 0;}
int MB_RespGet_Diagnostic(RS_MsgTypeDef *modbus_msg, uint16_t *data) {return 0;}
RS_MsgTypeDef MB_REQUEST_READ_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_READ_DISCRETE_INPUTS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_READ_INPUT_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_COIL(uint8_t slave_addr, uint16_t coil_addr, uint8_t value) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_WRITE_SINGLE_REG(uint8_t slave_addr, uint16_t reg_addr, uint16_t value) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_COILS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint8_t *coils_data) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_WRITE_MULTIPLE_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity, uint16_t *regs_data) {return msg_dummy;}
//---------ДИАГНОСТИЧЕСКИЕ ДАННЫЕ-----------
RS_MsgTypeDef MB_REQUEST_DIAGNOSTIC_QUERY(uint8_t slave_addr, uint16_t sub_function, uint16_t data) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_QUERY_DATA(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RESTART_COMMUNICATIONS(uint8_t slave_addr, uint16_t data) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_DIAGNOSTIC_REGISTER(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_FORCE_LISTEN_ONLY_MODE(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_CLEAR_COUNTERS_AND_DIAGNOSTIC_REGISTER(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_BUS_MESSAGE_COUNT(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_BUS_COMMUNICATION_ERROR_COUNT(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_EXCEPTION_ERROR_COUNT(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_MESSAGE_COUNT(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NO_RESPONSE_COUNT(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_NAK_COUNT(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_SLAVE_BUSY_COUNT(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_RETURN_BUS_CHARACTER_OVERRUN_COUNT(uint8_t slave_addr) {return msg_dummy;}
//---------ИДЕНТИФИКАТОРЫ МОДБАС-----------
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_BASIC(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_REGULAR(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_EXTENDED(uint8_t slave_addr) {return msg_dummy;}
RS_MsgTypeDef MB_REQUEST_READ_DEVICE_ID_SPECIFIC(uint8_t slave_addr, uint8_t object_id) {return msg_dummy;}
RS_StatusTypeDef MB_Master_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) {return RS_ERR;}
RS_StatusTypeDef MB_Master_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) {return RS_ERR;}
#endif

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() — Сбор сообщения в режиме слейва.
@@ -37,26 +37,26 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod
} }
MB_Diagnostics_SlaveMessageCnt(); MB_Diagnostics_SlaveMessageCnt();
if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing if(modbus_msg->FuncCode < FC_ERR_VALUES_START)// if no errors after parsing
{ {
switch (modbus_msg->Func_Code) switch (modbus_msg->FuncCode)
{ {
// Read Coils // Read Coils
case MB_R_COILS: case FC_R_COILS:
hmodbus->f.MessageHandled = MB_Process_Read_Coils(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Read_Coils(hmodbus->pMessagePtr);
break; break;
// Read Hodling Registers // Read Hodling Registers
case MB_R_HOLD_REGS: case FC_R_HOLD_REGS:
hmodbus->f.MessageHandled = MB_Process_Read_Hold_Regs(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Read_Hold_Regs(hmodbus->pMessagePtr);
break; break;
case MB_R_IN_REGS: case FC_R_IN_REGS:
hmodbus->f.MessageHandled = MB_Process_Read_Input_Regs(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Read_Input_Regs(hmodbus->pMessagePtr);
break; break;
// Write Single Coils // Write Single Coils
case MB_W_COIL: case FC_W_COIL:
hmodbus->f.MessageHandled = MB_Process_Write_Single_Coil(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Write_Single_Coil(hmodbus->pMessagePtr);
if(hmodbus->f.MessageHandled) if(hmodbus->f.MessageHandled)
{ {
@@ -66,7 +66,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod
} }
break; break;
case MB_W_HOLD_REG: case FC_W_HOLD_REG:
hmodbus->f.MessageHandled = MB_Process_Write_Single_Reg(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Write_Single_Reg(hmodbus->pMessagePtr);
if(hmodbus->f.MessageHandled) if(hmodbus->f.MessageHandled)
{ {
@@ -77,7 +77,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod
break; break;
// Write Multiple Coils // Write Multiple Coils
case MB_W_COILS: case FC_W_COILS:
hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Coils(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Coils(hmodbus->pMessagePtr);
if(hmodbus->f.MessageHandled) if(hmodbus->f.MessageHandled)
{ {
@@ -88,7 +88,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod
break; break;
// Write Multiple Registers // Write Multiple Registers
case MB_W_HOLD_REGS: case FC_W_HOLD_REGS:
hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Regs(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Write_Miltuple_Regs(hmodbus->pMessagePtr);
if(hmodbus->f.MessageHandled) if(hmodbus->f.MessageHandled)
{ {
@@ -98,12 +98,12 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod
} }
break; break;
case MB_R_DEVICE_INFO: case FC_R_DEVICE_ID:
hmodbus->f.MessageHandled = MB_Process_Read_Device_Identifications(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Read_Device_Identifications(hmodbus->pMessagePtr);
break; break;
// Добавить в switch-case после других case: // Добавить в switch-case после других case:
case MB_R_DIAGNOSTIC: case FC_R_DIAGNOSTICS:
hmodbus->f.MessageHandled = MB_Process_Diagnostics(hmodbus->pMessagePtr); hmodbus->f.MessageHandled = MB_Process_Diagnostics(hmodbus->pMessagePtr);
break; break;
@@ -126,7 +126,7 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod
{ {
MB_Diagnostics_ExceptionErrorCnt(); MB_Diagnostics_ExceptionErrorCnt();
TrackerCnt_Warn(hmodbus->rs_err); TrackerCnt_Warn(hmodbus->rs_err);
modbus_msg->Func_Code |= ERR_VALUES_START; modbus_msg->FuncCode |= FC_ERR_VALUES_START;
} }
else else
{ {
@@ -173,17 +173,29 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD
else else
{ {
//------INFO ABOUT DATA/MESSAGE------ //------INFO ABOUT DATA/MESSAGE------
#ifdef MODBUS_PROTOCOL_TCP
modbus_uart_buff[ind++] = modbus_msg->TransactionID >> 8;
modbus_uart_buff[ind++] = modbus_msg->TransactionID& 0xFF;
modbus_uart_buff[ind++] = modbus_msg->ProtocolID >> 8;
modbus_uart_buff[ind++] = modbus_msg->ProtocolID& 0xFF;
modbus_uart_buff[ind++] = modbus_msg->PDULength >> 8;
modbus_uart_buff[ind++] = modbus_msg->PDULength& 0xFF;
#endif
//-----------[first bytes]----------- //-----------[first bytes]-----------
// set ID of message/user // set ID of message/user
modbus_uart_buff[ind++] = modbus_msg->MbAddr; modbus_uart_buff[ind++] = modbus_msg->MbAddr;
// set dat or err response // set dat or err response
modbus_uart_buff[ind++] = modbus_msg->Func_Code; modbus_uart_buff[ind++] = modbus_msg->FuncCode;
if (modbus_msg->Func_Code < ERR_VALUES_START) // if no error occur if (modbus_msg->FuncCode < FC_ERR_VALUES_START) // if no error occur
{ {
// fill modbus header // fill modbus header
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // devide identifications header if(0) {}
#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // devide identifications header
{ {
modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type; modbus_uart_buff[ind++] = modbus_msg->DevId.MEI_Type;
modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId; modbus_uart_buff[ind++] = modbus_msg->DevId.ReadDevId;
@@ -201,7 +213,7 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD
//---------------DATA---------------- //---------------DATA----------------
//-----------[data bytes]------------ //-----------[data bytes]------------
uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->DATA; uint8_t *tmp_data_addr = (uint8_t *)modbus_msg->MbData;
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
{ // set data { // set data
modbus_uart_buff[ind++] = *tmp_data_addr; modbus_uart_buff[ind++] = *tmp_data_addr;
@@ -209,14 +221,17 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD
} }
} }
else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC) #endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#ifdef MODBUS_ENABLE_DIAGNOSTICS
else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{ {
// Diagnostics special format: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO] // Diagnostics special format: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
modbus_uart_buff[ind++] = modbus_msg->DATA[0] >> 8; // Sub-function HI modbus_uart_buff[ind++] = modbus_msg->MbData[0] >> 8; // Sub-function HI
modbus_uart_buff[ind++] = modbus_msg->DATA[0] & 0xFF; // Sub-function LO modbus_uart_buff[ind++] = modbus_msg->MbData[0] & 0xFF; // Sub-function LO
modbus_uart_buff[ind++] = modbus_msg->DATA[1] >> 8; // Data HI modbus_uart_buff[ind++] = modbus_msg->MbData[1] >> 8; // Data HI
modbus_uart_buff[ind++] = modbus_msg->DATA[1] & 0xFF; // Data LO modbus_uart_buff[ind++] = modbus_msg->MbData[1] & 0xFF; // Data LO
} }
#endif //MODBUS_ENABLE_DIAGNOSTICS
else // modbus data header else // modbus data header
{ {
// set size of received data // set size of received data
@@ -230,7 +245,7 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD
//---------------DATA---------------- //---------------DATA----------------
//-----------[data bytes]------------ //-----------[data bytes]------------
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData;
for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data for(int i = 0; i < modbus_msg->ByteCnt; i++) // filling buffer with data
{ // set data { // set data
if (i%2 == 0) // HI byte if (i%2 == 0) // HI byte
@@ -255,12 +270,14 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD
//---------------CRC---------------- //---------------CRC----------------
//---------[last 16 bytes]---------- //---------[last 16 bytes]----------
#ifndef MODBUS_PROTOCOL_TCP
// calc crc of received data // calc crc of received data
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
// write crc to message structure and modbus-uart buffer // write crc to message structure and modbus-uart buffer
modbus_msg->MB_CRC = CRC_VALUE; modbus_msg->MbCRC = CRC_VALUE;
modbus_uart_buff[ind++] = CRC_VALUE; modbus_uart_buff[ind++] = CRC_VALUE;
modbus_uart_buff[ind++] = CRC_VALUE >> 8; modbus_uart_buff[ind++] = CRC_VALUE >> 8;
#endif
hmodbus->RS_Message_Size = ind; hmodbus->RS_Message_Size = ind;
@@ -279,15 +296,15 @@ static int MB_Define_Size_of_Function(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *
RS_StatusTypeDef MB_RES = 0; RS_StatusTypeDef MB_RES = 0;
int mb_func_size = 0; int mb_func_size = 0;
if (modbus_msg->Func_Code == MB_R_DIAGNOSTIC) if (modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{ {
mb_func_size = 1; mb_func_size = 1;
} }
else if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) else if(modbus_msg->FuncCode == FC_R_DEVICE_ID)
{ {
mb_func_size = 0; mb_func_size = 0;
} }
else if ((modbus_msg->Func_Code & ~ERR_VALUES_START) < 0x0F) else if ((modbus_msg->FuncCode & ~FC_ERR_VALUES_START) < 0x0F)
{ {
mb_func_size = 1; mb_func_size = 1;
} }
@@ -317,6 +334,16 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef
hmodbus->f.RX_Continue = 0; hmodbus->f.RX_Continue = 0;
int expected_size = 0; int expected_size = 0;
//-----INFO ABOUT DATA/MESSAGE------- //-----INFO ABOUT DATA/MESSAGE-------
#ifdef MODBUS_PROTOCOL_TCP
modbus_msg->TransactionID =modbus_uart_buff[ind++]<<8;
modbus_msg->TransactionID |=modbus_uart_buff[ind++];
modbus_msg->ProtocolID =modbus_uart_buff[ind++]<<8;
modbus_msg->ProtocolID |=modbus_uart_buff[ind++];
modbus_msg->PDULength =modbus_uart_buff[ind++]<<8;
modbus_msg->PDULength |=modbus_uart_buff[ind++];
#endif
//-----------[first bits]------------ //-----------[first bits]------------
// get ID of message/user // get ID of message/user
if(modbus_uart_buff[ind] != hmodbus->ID) if(modbus_uart_buff[ind] != hmodbus->ID)
@@ -330,33 +357,38 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef
} }
// get func code // get func code
modbus_msg->Func_Code = modbus_uart_buff[ind++]; modbus_msg->FuncCode = modbus_uart_buff[ind++];
if(modbus_msg->Func_Code & ERR_VALUES_START) // явная херня if(modbus_msg->FuncCode & FC_ERR_VALUES_START) // явная херня
{ {
MB_Diagnostics_SlaveNAKCnt(); MB_Diagnostics_SlaveNAKCnt();
modbus_msg->MbAddr = 0; modbus_msg->MbAddr = 0;
return RS_SKIP; return RS_SKIP;
} }
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO) // if it device identifications request if(0) {}
#ifdef MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
else if(modbus_msg->FuncCode == FC_R_DEVICE_ID) // if it device identifications request
{ {
modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++]; modbus_msg->DevId.MEI_Type = modbus_uart_buff[ind++];
modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++]; modbus_msg->DevId.ReadDevId = modbus_uart_buff[ind++];
modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++]; modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++];
modbus_msg->ByteCnt = 0; modbus_msg->ByteCnt = 0;
} }
else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC) #endif //MODBUS_ENABLE_DEVICE_IDENTIFICATIONS
#ifdef MODBUS_ENABLE_DIAGNOSTICS
else if(modbus_msg->FuncCode == FC_R_DIAGNOSTICS)
{ {
// Diagnostics: читаем 4 байта в DATA[0] и DATA[1] // Diagnostics: читаем 4 байта в MbData[0] и MbData[1]
// Sub-function // Sub-function
modbus_msg->DATA[0] = modbus_uart_buff[ind++] << 8; modbus_msg->MbData[0] = modbus_uart_buff[ind++] << 8;
modbus_msg->DATA[0] |= modbus_uart_buff[ind++]; modbus_msg->MbData[0] |= modbus_uart_buff[ind++];
// Data // Data
modbus_msg->DATA[1] = modbus_uart_buff[ind++] << 8; modbus_msg->MbData[1] = modbus_uart_buff[ind++] << 8;
modbus_msg->DATA[1] |= modbus_uart_buff[ind++]; modbus_msg->MbData[1] |= modbus_uart_buff[ind++];
modbus_msg->Addr = 0; // не использует Addr modbus_msg->Addr = 0; // не использует Addr
modbus_msg->Qnt = 0; // не использует Qnt modbus_msg->Qnt = 0; // не использует Qnt
} }
#endif //MODBUS_ENABLE_DIAGNOSTICS
else // if its classic modbus request else // if its classic modbus request
{ {
// get address from CMD // get address from CMD
@@ -368,7 +400,7 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef
modbus_msg->Qnt |= modbus_uart_buff[ind++]; modbus_msg->Qnt |= modbus_uart_buff[ind++];
} }
if((hmodbus->pMessagePtr->Func_Code == 0x0F) || (hmodbus->pMessagePtr->Func_Code == 0x10)) if((hmodbus->pMessagePtr->FuncCode == 0x0F) || (hmodbus->pMessagePtr->FuncCode == 0x10))
hmodbus->pMessagePtr->ByteCnt = modbus_uart_buff[ind++]; hmodbus->pMessagePtr->ByteCnt = modbus_uart_buff[ind++];
else else
hmodbus->pMessagePtr->ByteCnt = 0; hmodbus->pMessagePtr->ByteCnt = 0;
@@ -395,11 +427,11 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef
if (modbus_msg->ByteCnt > DATA_SIZE*2) if (modbus_msg->ByteCnt > DATA_SIZE*2)
{ {
TrackerCnt_Err(hmodbus->rs_err); TrackerCnt_Err(hmodbus->rs_err);
modbus_msg->Func_Code |= ERR_VALUES_START; modbus_msg->FuncCode |= FC_ERR_VALUES_START;
MB_Diagnostics_CommunicationErrorCnt(); MB_Diagnostics_CommunicationErrorCnt();
return RS_PARSE_MSG_ERR; return RS_PARSE_MSG_ERR;
} }
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA; uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->MbData;
for(int i = 0; i < modbus_msg->ByteCnt; i++) for(int i = 0; i < modbus_msg->ByteCnt; i++)
{ // set data { // set data
if (i%2 == 0) if (i%2 == 0)
@@ -414,24 +446,22 @@ RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef
//---------------CRC---------------- //---------------CRC----------------
//----------[last 16 bits]---------- //----------[last 16 bits]----------
#ifndef MODBUS_PROTOCOL_TCP
// calc crc of received data // calc crc of received data
uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind); uint16_t CRC_VALUE = crc16(modbus_uart_buff, ind);
// get crc of received data // get crc of received data
modbus_msg->MB_CRC = modbus_uart_buff[ind++]; modbus_msg->MbCRC = modbus_uart_buff[ind++];
modbus_msg->MB_CRC |= modbus_uart_buff[ind++] << 8; modbus_msg->MbCRC |= modbus_uart_buff[ind++] << 8;
// compare crc // compare crc
if (modbus_msg->MB_CRC != CRC_VALUE) if (modbus_msg->MbCRC != CRC_VALUE)
{ {
MB_Diagnostics_CommunicationErrorCnt(); MB_Diagnostics_CommunicationErrorCnt();
TrackerCnt_Err(hmodbus->rs_err); TrackerCnt_Err(hmodbus->rs_err);
modbus_msg->Func_Code |= ERR_VALUES_START; modbus_msg->FuncCode |= FC_ERR_VALUES_START;
} }
#endif
return RS_OK; return RS_OK;
} }
#else // MODBUS_ENABLE_SLAVE #endif //MODBUS_ENABLE_SLAVE
RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg) {return RS_ERR;}
RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) {return RS_ERR;}
RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff) {return RS_ERR;}
#endif

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()
******************************************************************************/ ******************************************************************************/
@@ -323,6 +323,7 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
{ {
return; return;
} }
RS_UART_Handler_ENTER();
//-------------CHECK IDLE FLAG FIRST------------- //-------------CHECK IDLE FLAG FIRST-------------
/* Проверяем флаг IDLE в первую очередь - это гарантирует обработку только после idle */ /* Проверяем флаг IDLE в первую очередь - это гарантирует обработку только после idle */
if(__HAL_UART_GET_FLAG(hRS->huart, UART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(hRS->huart, UART_IT_IDLE)) if(__HAL_UART_GET_FLAG(hRS->huart, UART_FLAG_IDLE) && __HAL_UART_GET_IT_SOURCE(hRS->huart, UART_IT_IDLE))
@@ -362,10 +363,10 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
} }
else else
{ {
RS_Set_Free(hRS); // освобожднаем RS
if(hRS->pCallback) if(hRS->pCallback)
{ {
hRS->pCallback(hRS, hRS->pMessagePtr); // обрабатываем ответ hRS->pCallback(hRS, hRS->pMessagePtr); // обрабатываем ответ
RS_Set_Free(hRS); // освобожднаем RS
} }
} }
} }
@@ -419,6 +420,7 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
// later, maybe, will be added specific handlers for err // later, maybe, will be added specific handlers for err
} }
RS_UART_Handler_EXIT();
} }
@@ -434,11 +436,12 @@ void RS_TIM_Handler(RS_HandleTypeDef *hRS)
{ {
return; return;
} }
RS_TIM_Handler_ENTER();
HAL_TIM_IRQHandler(hRS->htim); HAL_TIM_IRQHandler(hRS->htim);
RS_Abort(hRS, ABORT_RS); RS_Abort(hRS, ABORT_RS);
hRS->RS_STATUS = RS_TIMEOUT; hRS->RS_STATUS = RS_TIMEOUT;
if(hRS->sRS_Mode < RS_MASTER_MODE_START) if(hRS->sRS_Mode < RS_MASTER_MODE_START)
@@ -447,15 +450,16 @@ void RS_TIM_Handler(RS_HandleTypeDef *hRS)
if(hRS->sRS_Mode >= RS_MASTER_MODE_START) if(hRS->sRS_Mode >= RS_MASTER_MODE_START)
{ // Мастер: коллбек и освобождение для нового запроса { // Мастер: коллбек и освобождение для нового запроса
RS_Set_Free(hRS);
if(hRS->pCallback) if(hRS->pCallback)
{ {
hRS->pCallback(hRS, hRS->pMessagePtr); // обрабатываем ответ hRS->pCallback(hRS, hRS->pMessagePtr); // обрабатываем ответ
} }
RS_Set_Free(hRS);
} else { } else {
// Слейв: перезапускаем прием // Слейв: перезапускаем прием
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr); RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
} }
RS_TIM_Handler_EXIT();
} }
/** /**

View File

@@ -5,6 +5,7 @@
****************************************************************************** ******************************************************************************
@addtogroup MODBUS_CONFIGS Modbus configs @addtogroup MODBUS_CONFIGS Modbus configs
@ingroup MODBUS @ingroup MODBUS
@brief Конфигурация библиотеки
@{ @{
****************************************************************************** ******************************************************************************
* @details * @details
@@ -32,7 +33,9 @@
#define MODBUS_PRODUCT_NAME "" #define MODBUS_PRODUCT_NAME ""
#define MODBUS_MODEL_NAME "" #define MODBUS_MODEL_NAME ""
#define MODBUS_USER_APPLICATION_NAME "" #define MODBUS_USER_APPLICATION_NAME ""
#define MODBUS_NUMB_OF_USEROBJECTS 0
#define MODBUS_NUMB_OF_USEROBJECTS 0 ///< Количество пользовательских объектов
#define MODBUS_USEROBJECT_0_NAME "" ///< Строка пользовательского идентификатора 0. По аналогии можно определить строки до <=128 USEROBJECT
// Периферия (опционально) // Периферия (опционально)
#define mb_huart huart1 ///< Удобный дефайн для модбасовского uart #define mb_huart huart1 ///< Удобный дефайн для модбасовского uart
@@ -51,6 +54,7 @@
#define MODBUS_ENABLE_DEVICE_IDENTIFICATIONS ///< Включить обработку идентификаторы устройства #define MODBUS_ENABLE_DEVICE_IDENTIFICATIONS ///< Включить обработку идентификаторы устройства
#define MODBUS_ENABLE_DIAGNOSTICS ///< Включить обработку диагностики модбас #define MODBUS_ENABLE_DIAGNOSTICS ///< Включить обработку диагностики модбас
//#define MODBUS_PROTOCOL_TCP ///< Включить TCP-протокол, иначе - RTU
/** /**
* @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей) * @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей)

View File

@@ -29,11 +29,11 @@
* @param Qnt Количество запрашиваемых элементов. * @param Qnt Количество запрашиваемых элементов.
* @param R_ARR_ADDR Начальный адресс массива R_ARR. * @param R_ARR_ADDR Начальный адресс массива R_ARR.
* @param R_ARR_NUMB Количество элементов в массиве R_ARR. * @param R_ARR_NUMB Количество элементов в массиве R_ARR.
* @return ExceptionCode - ILLEGAL DATA ADRESS если адресс недействителен, и NO_ERRORS если все ок. * @return ExceptionCode - ET_ILLEGAL_DATA_ADRESS если адресс недействителен, и ET_NO_ERRORS если все ок.
* *
* @details Позволяет определить, принадлежит ли адресс Addr массиву R_ARR: * @details Позволяет определить, принадлежит ли адресс Addr массиву R_ARR:
* Если адресс Addr находится в диапазоне адрессов массива R_ARR, то возвращаем NO_ERROR. * Если адресс Addr находится в диапазоне адрессов массива R_ARR, то возвращаем NO_ERROR.
* Если адресс Addr находится за пределами адрессов массива R_ARR - ILLEGAL_DATA_ADDRESSю. * Если адресс Addr находится за пределами адрессов массива R_ARR - ET_ILLEGAL_DATA_ADDRESSю.
*/ */
MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB) MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB)
{ {
@@ -43,14 +43,14 @@ MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16
// if quantity too big return error // if quantity too big return error
if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB) if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB)
{ {
return ILLEGAL_DATA_ADDRESS; // return exception code return ET_ILLEGAL_DATA_ADDRESS; // return exception code
} }
// if all ok - return no errors // if all ok - return no errors
return NO_ERRORS; return ET_NO_ERRORS;
} }
// if address isnt from this array return error // if address isnt from this array return error
else else
return ILLEGAL_DATA_ADDRESS; // return exception code return ET_ILLEGAL_DATA_ADDRESS; // return exception code
} }
/** /**
* @brief Define Address Origin for Input/Holding Registers * @brief Define Address Origin for Input/Holding Registers
@@ -58,7 +58,7 @@ MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16
* @param Addr Адрес начального регистра. * @param Addr Адрес начального регистра.
* @param Qnt Количество запрашиваемых регистров. * @param Qnt Количество запрашиваемых регистров.
* @param WriteFlag Флаг регистр нужны для чтения или записи. * @param WriteFlag Флаг регистр нужны для чтения или записи.
* @return ExceptionCode Код исключения если есть, и NO_ERRORS если нет. * @return ExceptionCode Код исключения если есть, и ET_NO_ERRORS если нет.
* *
* @details Определение адреса начального регистра. * @details Определение адреса начального регистра.
* @note WriteFlag пока не используется. * @note WriteFlag пока не используется.
@@ -68,41 +68,41 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u
/* check quantity error */ /* check quantity error */
if (Qnt > DATA_SIZE) if (Qnt > DATA_SIZE)
{ {
return ILLEGAL_DATA_VALUE; // return exception code return ET_ILLEGAL_DATA_VALUE; // return exception code
} }
if(RegisterType == RegisterType_Holding) if(RegisterType == RegisterType_Holding)
{ {
// Default holding registers // Default holding registers
if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == NO_ERRORS) if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == ET_NO_ERRORS)
{ {
*pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр *pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр
} }
// if address doesnt match any array - return illegal data address response // if address doesnt match any array - return illegal data address response
else else
{ {
return ILLEGAL_DATA_ADDRESS; return ET_ILLEGAL_DATA_ADDRESS;
} }
} }
else if(RegisterType == RegisterType_Input) else if(RegisterType == RegisterType_Input)
{ {
// Default input registers // Default input registers
if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == NO_ERRORS) if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == ET_NO_ERRORS)
{ {
*pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr - R_INPUT_ADDR); // указатель на выбранный по Addr регистр *pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr - R_INPUT_ADDR); // указатель на выбранный по Addr регистр
} }
// if address doesnt match any array - return illegal data address response // if address doesnt match any array - return illegal data address response
else else
{ {
return ILLEGAL_DATA_ADDRESS; return ET_ILLEGAL_DATA_ADDRESS;
} }
} }
else else
{ {
return ILLEGAL_FUNCTION; return ET_ILLEGAL_FUNCTION;
} }
// if found requeried array return no err // if found requeried array return no err
return NO_ERRORS; // return no errors return ET_NO_ERRORS; // return no errors
} }
/** /**
* @brief Define Address Origin for coils * @brief Define Address Origin for coils
@@ -111,7 +111,7 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u
* @param Qnt Количество запрашиваемых коилов. * @param Qnt Количество запрашиваемых коилов.
* @param start_shift Указатель на переменную содержащую сдвиг внутри регистра для начального коила. * @param start_shift Указатель на переменную содержащую сдвиг внутри регистра для начального коила.
* @param WriteFlag Флаг коилы нужны для чтения или записи. * @param WriteFlag Флаг коилы нужны для чтения или записи.
* @return ExceptionCode Код исключения если есть, и NO_ERRORS если нет. * @return ExceptionCode Код исключения если есть, и ET_NO_ERRORS если нет.
* *
* @details Определение адреса начального регистра запрашиваемых коилов. * @details Определение адреса начального регистра запрашиваемых коилов.
* @note WriteFlag используется для определния регистров GPIO: ODR или IDR. * @note WriteFlag используется для определния регистров GPIO: ODR или IDR.
@@ -121,21 +121,21 @@ MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint
/* check quantity error */ /* check quantity error */
if (Qnt > 2000) if (Qnt > 2000)
{ {
return ILLEGAL_DATA_VALUE; // return exception code return ET_ILLEGAL_DATA_VALUE; // return exception code
} }
// Default coils // Default coils
if(MB_Check_Address_For_Arr(Addr, Qnt, C_COILS_ADDR, C_COILS_QNT) == NO_ERRORS) if(MB_Check_Address_For_Arr(Addr, Qnt, C_COILS_ADDR, C_COILS_QNT) == ET_NO_ERRORS)
{ {
*pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr - C_COILS_ADDR); // указатель на выбранный по Addr массив коилов *pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr - C_COILS_ADDR); // указатель на выбранный по Addr массив коилов
} }
// if address doesnt match any array - return illegal data address response // if address doesnt match any array - return illegal data address response
else else
{ {
return ILLEGAL_DATA_ADDRESS; return ET_ILLEGAL_DATA_ADDRESS;
} }
*start_shift = Addr % 16; // set shift to requested coil *start_shift = Addr % 16; // set shift to requested coil
// if found requeried array return no err // if found requeried array return no err
return NO_ERRORS; // return no errors return ET_NO_ERRORS; // return no errors
} }

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.
@@ -36,14 +36,14 @@
uint16_t user_regs[16]; uint16_t user_regs[16];
//... //...
else if(MB_Check_Address_For_Arr(Addr, Qnt, R_USER_ADDR, R_USER_QNT) == NO_ERRORS) else if(MB_Check_Address_For_Arr(Addr, Qnt, R_USER_ADDR, R_USER_QNT) == ET_NO_ERRORS)
{ {
*pRegs = MB_Set_Register_Ptr(&user_regs, Addr-R_USER_ADDR); // ВАЖНО! *pRegs = MB_Set_Register_Ptr(&user_regs, Addr-R_USER_ADDR); // ВАЖНО!
// -R_USER_ADDR нужен чтобы взять адрес относительно начала массива // -R_USER_ADDR нужен чтобы взять адрес относительно начала массива
} }
else else
{ {
return ILLEGAL_DATA_ADDRESS; return ET_ILLEGAL_DATA_ADDRESS;
} }
@endcode @endcode
******************************************************************************/ ******************************************************************************/
@@ -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
* @{ * @{
*/ */