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:
118
Inc/__modbus_compat.h
Normal file
118
Inc/__modbus_compat.h
Normal 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 */
|
||||||
79
Inc/modbus.h
79
Inc/modbus.h
@@ -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,43 +25,43 @@
|
|||||||
|
|
||||||
- Инициализировать хендл мобдас. По умолчанию глобально создается 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);
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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++)
|
||||||
{
|
{
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value))
|
if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value))
|
||||||
{
|
{
|
||||||
read_hold[i] = value;
|
read_hold[i] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@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
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
@@ -124,4 +140,5 @@ HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef
|
|||||||
|
|
||||||
/** MODBUS_FUNCTIONS
|
/** MODBUS_FUNCTIONS
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -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);
|
||||||
@@ -115,4 +119,4 @@ uint8_t MB_Process_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg);
|
|||||||
*/
|
*/
|
||||||
/////////////////////////---FUNCTIONS---/////////////////////////////
|
/////////////////////////---FUNCTIONS---/////////////////////////////
|
||||||
|
|
||||||
#endif //__MODBUS_COILS_H_
|
#endif //__MODBUS_COILS_H_
|
||||||
|
|||||||
@@ -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,8 +305,11 @@ 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
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|
||||||
|
|||||||
@@ -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) */
|
||||||
@@ -119,4 +120,5 @@ uint8_t MB_Process_Diagnostics(RS_MsgTypeDef *modbus_msg);
|
|||||||
|
|
||||||
/** MODBUS_DIAG
|
/** MODBUS_DIAG
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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, ®_value))
|
* if(MB_RespGet_RegisterValue(modbus_msg, 105, ®_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
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
107
Inc/rs_message.h
107
Inc/rs_message.h
@@ -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
|
||||||
|
|||||||
413
README.md
413
README.md
@@ -6,40 +6,40 @@
|
|||||||
|
|
||||||
*Note: Файлы начинающиеся с `__` и которых **нет** в этом дереве являются **внутренними/непротестированными/недокументированными***
|
*Note: Файлы начинающиеся с `__` и которых **нет** в этом дереве являются **внутренними/непротестированными/недокументированными***
|
||||||
```
|
```
|
||||||
Modbus/ Иерархия модулей:
|
Modbus/ Иерархия модулей:
|
||||||
│ inc/ modbus
|
│ inc/ modbus
|
||||||
│ ├── modbus.h # Главный заголовочный файл modbus_slave
|
│ ├── modbus.h # Главный заголовочный файл modbus_slave
|
||||||
│ ├── modbus_core.h # Базовые определения и структуры modbus_master
|
│ ├── modbus_core.h # Базовые определения и структуры modbus_master
|
||||||
│ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils
|
│ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils
|
||||||
│ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs
|
│ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs
|
||||||
│ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs
|
│ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs
|
||||||
│ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid
|
│ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid
|
||||||
│ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag
|
│ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag
|
||||||
├── src/ └── rs_message
|
├── src/ └── rs_message
|
||||||
│ ├── modbus.c # Основная логика Modbus │
|
│ ├── modbus.c # Основная логика Modbus │
|
||||||
│ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро)
|
│ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро)
|
||||||
│ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config
|
│ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config
|
||||||
│ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data
|
│ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data
|
||||||
│ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs
|
│ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs
|
||||||
│ ├── modbus_inputregs.c # Реализация входных регистров
|
│ ├── modbus_inputregs.c # Реализация входных регистров
|
||||||
│ ├── modbus_devid.c # Реализация идентификации устройства
|
│ ├── modbus_devid.c # Реализация идентификации устройства
|
||||||
│ ├── modbus_data.c # Функции доступа к данным
|
│ ├── modbus_data.c # Функции доступа к данным
|
||||||
│ └── rs_message.c # Реализация драйвера RS
|
│ └── rs_message.c # Реализация драйвера RS
|
||||||
├── __modbus_config.h # Конфигурация Modbus (надо заменить)
|
├── __modbus_config.h # Конфигурация Modbus (надо заменить)
|
||||||
├── __modbus_data.h # Структуры данных (надо заменить)
|
├── __modbus_data.h # Структуры данных (надо заменить)
|
||||||
└── __modbus_data.c # Функции доступа (надо заменить)
|
└── __modbus_data.c # Функции доступа (надо заменить)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Инструкция по подключению
|
## Инструкция по подключению
|
||||||
|
|
||||||
1. **Склонируйте субмодуль** в ваш проект:
|
### 1. **Склонируйте субмодуль** в ваш проект:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git submodule add https://git.arktika.cyou/set506/STM32_Modbus path/to/Modbus
|
git submodule add https://git.arktika.cyou/set506/STM32_Modbus path/to/Modbus
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Скопируйте файлы конфигурации** в отдельную папку в вашем проекте (вне субмодуля) и удалите `__` из имени файлов:
|
### 2. **Скопируйте файлы конфигурации** в отдельную папку в вашем проекте (вне субмодуля) и удалите `__` из имени файлов:
|
||||||
|
|
||||||
```
|
```
|
||||||
ProjectRoot/
|
ProjectRoot/
|
||||||
@@ -47,219 +47,210 @@ ProjectRoot/
|
|||||||
│ ├── modbus_config.h # скопировать из __modbus_config.h
|
│ ├── modbus_config.h # скопировать из __modbus_config.h
|
||||||
│ ├── modbus_data.h # скопировать из __modbus_data.h
|
│ ├── modbus_data.h # скопировать из __modbus_data.h
|
||||||
│ └── modbus_data.c # скопировать из __modbus_data.c
|
│ └── modbus_data.c # скопировать из __modbus_data.c
|
||||||
└── Modbus/ # Субмодуль
|
└── Modbus/ # Субмодуль
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Настройте конфигурацию** под ваш проект:
|
### 3. **Настройте конфигурацию** под ваш проект:
|
||||||
|
#### 3.1. Настройка периферии
|
||||||
3.1. Настройка периферии
|
|
||||||
|
|
||||||
- **UART**: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1
|
- **UART**: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1
|
||||||
- **TIM**: Настройте таймер для генерации прерываний (например, 1ms tick)
|
- **TIM**: Настройте таймер для генерации прерываний (например, 1ms tick)
|
||||||
- **Включите прерывания** для UART и TIM
|
- **Включите прерывания** для UART и TIM
|
||||||
|
|
||||||
3.2. Подключение обработчиков прерываний
|
#### 3.2. Подключение обработчиков прерываний
|
||||||
|
|
||||||
Подключите обработчики прерываний **UART** и **TIM** в свои IRQ обработчики ***вместо*** HAL-обработчиков:
|
Подключите обработчики прерываний **UART** и **TIM** в свои IRQ обработчики ***вместо*** HAL-обработчиков:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
#include "modbus.h"
|
#include "modbus.h"
|
||||||
|
|
||||||
void USARTx_IRQHandler(void)
|
void USARTx_IRQHandler(void)
|
||||||
{
|
{
|
||||||
RS_UART_Handler(&hmodbus1);
|
RS_UART_Handler(&hmodbus1);
|
||||||
return;
|
return;
|
||||||
HAL_UART_IRQHandler(&huart);
|
HAL_UART_IRQHandler(&huart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIMx_IRQHandler(void)
|
void TIMx_IRQHandler(void)
|
||||||
{
|
{
|
||||||
RS_TIM_Handler(&hmodbus1);
|
RS_TIM_Handler(&hmodbus1);
|
||||||
return;
|
return;
|
||||||
HAL_TIM_IRQHandler(&htim);
|
HAL_TIM_IRQHandler(&htim);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
#### 3.3. В `modbus_config.h` укажите параметры устройства
|
||||||
|
|
||||||
3.3. В `modbus_config.h` укажите параметры устройства
|
#### 3.4. Инициализация в коде
|
||||||
|
|
||||||
|
Чтобы настроить Slave-режим `main()` после инициализации HAL:
|
||||||
|
|
||||||
3.4. Инициализация в коде
|
```c
|
||||||
|
#include "modbus.h"
|
||||||
Чтобы настроить Slave-режим `main()` после инициализации HAL:
|
|
||||||
|
|
||||||
```c
|
int main(void)
|
||||||
#include "modbus.h"
|
{
|
||||||
|
// Инициализация HAL
|
||||||
|
HAL_Init();
|
||||||
|
SystemClock_Config();
|
||||||
|
MX_GPIO_Init();
|
||||||
|
MX_USART1_UART_Init();
|
||||||
|
MX_TIM3_Init();
|
||||||
|
|
||||||
|
// Инициализация Modbus
|
||||||
|
MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim);
|
||||||
|
MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE);
|
||||||
|
|
||||||
|
// Запуск приема Modbus
|
||||||
|
MODBUS_SlaveStart(&hmodbus1, NULL);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Основной цикл
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Чтобы настроить Master-режим `main()` после инициализации HAL:
|
||||||
|
|
||||||
int main(void)
|
```c
|
||||||
{
|
#include "modbus.h"
|
||||||
// Инициализация HAL
|
// Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук
|
||||||
HAL_Init();
|
RS_MsgTypeDef read_hold_cmd = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10);
|
||||||
SystemClock_Config();
|
// коллбек, вызовется при получении ответа от слейва
|
||||||
MX_GPIO_Init();
|
read_hold[10];
|
||||||
MX_USART1_UART_Init();
|
void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
||||||
MX_TIM3_Init();
|
{
|
||||||
|
// MB_RespGet_... Чтобы достать нужные данные из ответа
|
||||||
// Инициализация Modbus
|
if(hmodbus->RS_STATUS == RS_OK)
|
||||||
MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim);
|
{
|
||||||
MODBUS_Config(&hmodbus1, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE);
|
for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++)
|
||||||
|
{
|
||||||
// Запуск приема Modbus
|
uint16_t value;
|
||||||
MODBUS_SlaveStart(&hmodbus1, NULL);
|
if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value))
|
||||||
|
{
|
||||||
while (1)
|
read_hold[i] = value;
|
||||||
{
|
}
|
||||||
// Основной цикл
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
int main(void)
|
||||||
|
{
|
||||||
|
// Инициализация HAL
|
||||||
|
HAL_Init();
|
||||||
|
SystemClock_Config();
|
||||||
|
MX_GPIO_Init();
|
||||||
|
MX_USART1_UART_Init();
|
||||||
|
MX_TIM3_Init();
|
||||||
|
|
||||||
|
// Инициализация Modbus
|
||||||
|
MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim);
|
||||||
|
MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER);
|
||||||
|
|
||||||
|
// Запрос по Modbus
|
||||||
|
MODBUS_MasterRequest(&hmodbus1, &read_hold_cmd, &callback_func);
|
||||||
|
|
||||||
Чтобы настроить Master-режим `main()` после инициализации HAL:
|
}
|
||||||
|
```
|
||||||
|
#### 3.5. Настройка карты данных
|
||||||
|
|
||||||
```c
|
В `modbus_data.h` настройте регистры и coils под ваше устройство:
|
||||||
#include "modbus.h"
|
|
||||||
// Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук
|
|
||||||
RS_MsgTypeDef read_hold_cmd = MB_MASTER_READ_HOLDING_REGS(1, 0, 10);
|
|
||||||
// коллбек, вызовется при получении ответа от слейва
|
|
||||||
read_hold[10];
|
|
||||||
void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
|
||||||
{
|
|
||||||
// MB_RespGet_... Чтобы достать нужные данные из ответа
|
|
||||||
if(hmodbus->RS_STATUS == RS_OK)
|
|
||||||
{
|
|
||||||
for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++)
|
|
||||||
{
|
|
||||||
uint16_t value;
|
|
||||||
if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value))
|
|
||||||
{
|
|
||||||
read_hold[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
// Инициализация HAL
|
|
||||||
HAL_Init();
|
|
||||||
SystemClock_Config();
|
|
||||||
MX_GPIO_Init();
|
|
||||||
MX_USART1_UART_Init();
|
|
||||||
MX_TIM3_Init();
|
|
||||||
|
|
||||||
// Инициализация Modbus
|
|
||||||
MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim);
|
|
||||||
MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER);
|
|
||||||
|
|
||||||
// Запрос по Modbus
|
|
||||||
MODBUS_MasterRequest(&hmodbus1, &read_hold_cmd, &callback_func);
|
|
||||||
|
|
||||||
}
|
**Input Registers (только чтение)**
|
||||||
```
|
```c
|
||||||
3.5. Настройка карты данных
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t Temperature; // Адрес 0
|
||||||
|
uint16_t Humidity; // Адрес 1
|
||||||
|
uint16_t Pressure; // Адрес 2
|
||||||
|
uint16_t Voltage; // Адрес 3
|
||||||
|
} MB_DataInRegsTypeDef;
|
||||||
|
|
||||||
В `modbus_data.h` настройте регистры и coils под ваше устройство:
|
#define R_INPUT_ADDR 0 // Начальный адрес Input регистров
|
||||||
|
#define R_INPUT_QNT 4 // Количество Input регистров
|
||||||
|
```
|
||||||
|
**Holding Registers (чтение/запись)**
|
||||||
|
```c
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t SetpointTemp; // Адрес 0
|
||||||
|
uint16_t SetpointHumidity; // Адрес 1
|
||||||
|
uint16_t ControlMode; // Адрес 2
|
||||||
|
} MB_DataHoldRegsTypeDef;
|
||||||
|
|
||||||
**Input Registers (только чтение)**
|
#define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров
|
||||||
```c
|
#define R_HOLDING_QNT 3 // Количество Holding регистров
|
||||||
typedef struct
|
```
|
||||||
{
|
**Coils (1-битные)**
|
||||||
uint16_t Temperature; // Адрес 0
|
```c
|
||||||
uint16_t Humidity; // Адрес 1
|
typedef struct
|
||||||
uint16_t Pressure; // Адрес 2
|
{
|
||||||
uint16_t Voltage; // Адрес 3
|
unsigned Relay1 : 1; // Адрес 0
|
||||||
} MB_DataInRegsTypeDef;
|
unsigned Relay2 : 1; // Адрес 1
|
||||||
|
unsigned Pump : 1; // Адрес 2
|
||||||
|
unsigned Heater : 1; // Адрес 3
|
||||||
|
unsigned reserved : 12; // Резерв (выравнивание до 16 бит)
|
||||||
|
} MB_DataCoilsTypeDef;
|
||||||
|
|
||||||
#define R_INPUT_ADDR 0 // Начальный адрес Input регистров
|
#define C_COILS_ADDR 0 // Начальный адрес Coils
|
||||||
#define R_INPUT_QNT 4 // Количество Input регистров
|
#define C_COILS_QNT 4 // Количество Coils
|
||||||
```
|
```
|
||||||
|
#### 3.6. Доступ к данным в коде
|
||||||
|
|
||||||
**Holding Registers (чтение/запись)**
|
В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля
|
||||||
```c
|
```c
|
||||||
typedef struct
|
// Чтение входных регистров
|
||||||
{
|
uint16_t temp = MB_DATA.InRegs.Temperature;
|
||||||
uint16_t SetpointTemp; // Адрес 0
|
|
||||||
uint16_t SetpointHumidity; // Адрес 1
|
|
||||||
uint16_t ControlMode; // Адрес 2
|
|
||||||
} MB_DataHoldRegsTypeDef;
|
|
||||||
|
|
||||||
#define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров
|
// Запись в регистры хранения
|
||||||
#define R_HOLDING_QNT 3 // Количество Holding регистров
|
MB_DATA.HoldRegs.SetpointTemp = 2500;
|
||||||
```
|
|
||||||
|
|
||||||
**Coils (1-битные)**
|
// Управление coils
|
||||||
```c
|
MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить Relay1
|
||||||
typedef struct
|
MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить Relay2
|
||||||
{
|
|
||||||
unsigned Relay1 : 1; // Адрес 0
|
|
||||||
unsigned Relay2 : 1; // Адрес 1
|
|
||||||
unsigned Pump : 1; // Адрес 2
|
|
||||||
unsigned Heater : 1; // Адрес 3
|
|
||||||
unsigned reserved : 12; // Резерв (выравнивание до 16 бит)
|
|
||||||
} MB_DataCoilsTypeDef;
|
|
||||||
|
|
||||||
#define C_COILS_ADDR 0 // Начальный адрес Coils
|
// Чтение coil
|
||||||
#define C_COILS_QNT 4 // Количество Coils
|
if (MB_Coil_Read_Local(&MB_DATA.Coils, 2)) {
|
||||||
```
|
// Pump включен
|
||||||
|
}
|
||||||
|
```
|
||||||
|
В режиме мастера есть функции для получения информации из ответа `MB_RespGet_...()`
|
||||||
|
```c
|
||||||
|
// Чтение регистров: Получить запрошенные регистры
|
||||||
|
uint16_t value;
|
||||||
|
if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, ®_value))
|
||||||
|
{
|
||||||
|
printf("Register 105 value: %d\n", reg_value);
|
||||||
|
}
|
||||||
|
// Чтение коилов: Получить запрошенные коилы
|
||||||
|
int state;
|
||||||
|
if(MB_RespGet_CoilState(&MODBUS_MSG, 25, &coil_state))
|
||||||
|
{
|
||||||
|
printf("Coil 25 state: %s\n", coil_state ? "ON" : "OFF");
|
||||||
|
}
|
||||||
|
// Чтение диагностики: Получить запрошенныую диагностику
|
||||||
|
uint16_t counter_value;
|
||||||
|
if(MB_RespGet_DiagnosticResponse(&MODBUS_MSG, &counter_value))
|
||||||
|
{
|
||||||
|
printf("Counter value: %d\n", counter_value);
|
||||||
|
}
|
||||||
|
// Чтение идентификаторов: Получить запрошенные идентификаторы
|
||||||
|
uint8_t length;
|
||||||
|
char vendor_name[64];
|
||||||
|
if(MB_RespGet_ObjectById(&MODBUS_MSG, 0x00, vendor_name, &length))
|
||||||
|
{
|
||||||
|
printf("Vendor Name: %s (length: %d)\n", vendor_name, length);
|
||||||
|
}
|
||||||
|
|
||||||
3.6. Доступ к данным в коде
|
uint8_t obj_id, obj_length;
|
||||||
|
char obj_data[64];
|
||||||
|
if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, 0x00, &obj_id, obj_data, &obj_length))
|
||||||
В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля
|
{
|
||||||
```c
|
printf("First object - ID: 0x%02X, Data: %s\n", obj_id, obj_data);
|
||||||
// Чтение входных регистров
|
}
|
||||||
uint16_t temp = MB_DATA.InRegs.Temperature;
|
```
|
||||||
|
|
||||||
// Запись в регистры хранения
|
|
||||||
MB_DATA.HoldRegs.SetpointTemp = 2500;
|
|
||||||
|
|
||||||
// Управление coils
|
|
||||||
MB_Coil_Set_Local(&MB_DATA.Coils, 0); // Включить Relay1
|
|
||||||
MB_Coil_Reset_Local(&MB_DATA.Coils, 1); // Выключить Relay2
|
|
||||||
|
|
||||||
// Чтение coil
|
|
||||||
if (MB_Coil_Read_Local(&MB_DATA.Coils, 2)) {
|
|
||||||
// Pump включен
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
В режиме мастера есть функции для получения информации из ответа `MB_RespGet_...()`
|
|
||||||
```c
|
|
||||||
// Чтение регистров: Получить запрошенные регистры
|
|
||||||
uint16_t value;
|
|
||||||
if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, ®_value))
|
|
||||||
{
|
|
||||||
printf("Register 105 value: %d\n", reg_value);
|
|
||||||
}
|
|
||||||
// Чтение коилов: Получить запрошенные коилы
|
|
||||||
int state;
|
|
||||||
if(MB_RespGet_CoilState(&MODBUS_MSG, 25, &coil_state))
|
|
||||||
{
|
|
||||||
printf("Coil 25 state: %s\n", coil_state ? "ON" : "OFF");
|
|
||||||
}
|
|
||||||
// Чтение диагностики: Получить запрошенныую диагностику
|
|
||||||
uint16_t counter_value;
|
|
||||||
if(MB_RespGet_DiagnosticResponse(&MODBUS_MSG, &counter_value))
|
|
||||||
{
|
|
||||||
printf("Counter value: %d\n", counter_value);
|
|
||||||
}
|
|
||||||
// Чтение идентификаторов: Получить запрошенные идентификаторы
|
|
||||||
uint8_t length;
|
|
||||||
char vendor_name[64];
|
|
||||||
if(MB_RespGet_ObjectById(&MODBUS_MSG, 0x00, vendor_name, &length))
|
|
||||||
{
|
|
||||||
printf("Vendor Name: %s (length: %d)\n", vendor_name, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t obj_id, obj_length;
|
|
||||||
char obj_data[64];
|
|
||||||
if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, 0x00, &obj_id, obj_data, &obj_length))
|
|
||||||
{
|
|
||||||
printf("First object - ID: 0x%02X, Data: %s\n", obj_id, obj_data);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
5. **Обновление библиотеки**:
|
### 5. **Обновление библиотеки**:
|
||||||
|
|
||||||
После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся:
|
После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
7
Src/__modbus_compat.c
Normal file
7
Src/__modbus_compat.c
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
*******************************************************************************
|
||||||
|
* @file __modbus_compat.c
|
||||||
|
* @brief Модуль для совместимости библиотеки MODBUS.
|
||||||
|
*******************************************************************************
|
||||||
|
******************************************************************************/
|
||||||
|
#include "modbus.h"
|
||||||
22
Src/modbus.c
22
Src/modbus.c
@@ -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();
|
||||||
@@ -206,4 +212,4 @@ RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modb
|
|||||||
{
|
{
|
||||||
return MB_Master_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff);
|
return MB_Master_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
*******************************************************************************
|
||||||
* @file modbus_core.c
|
* @file modbus_core.c
|
||||||
* @brief Базовая реализация ядра Modbus
|
* @brief Базовая реализация ядра Modbus
|
||||||
******************************************************************************
|
*******************************************************************************
|
||||||
* @details
|
* @details
|
||||||
В текущей реализации этот файл служит заглушкой для будущего расширения
|
В текущей реализации этот файл служит заглушкой для будущего расширения
|
||||||
функциональности ядра Modbus протокола.
|
функциональности ядра Modbus протокола.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#include "modbus_core.h"
|
#include "modbus_core.h"
|
||||||
|
|||||||
@@ -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,15 +82,23 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
|
|||||||
MB_WriteSingleObjectToMessage(mbdata, &ind, &obj[objid]);
|
MB_WriteSingleObjectToMessage(mbdata, &ind, &obj[objid]);
|
||||||
}
|
}
|
||||||
objid--;
|
objid--;
|
||||||
modbus_msg->ByteCnt = ind;
|
|
||||||
modbus_msg->DevId.NextObjId = lastobjid+1;
|
if(modbus_msg->ByteCnt != 0)
|
||||||
if(objid == maxidofobj)
|
|
||||||
{
|
{
|
||||||
modbus_msg->DevId.MoreFollows = 0;
|
modbus_msg->ByteCnt = ind;
|
||||||
|
modbus_msg->DevId.NextObjId = lastobjid+1;
|
||||||
|
if(objid == maxidofobj)
|
||||||
|
{
|
||||||
|
modbus_msg->DevId.MoreFollows = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
modbus_msg->DevId.MoreFollows = 0xFF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
modbus_msg->DevId.MoreFollows = 0xFF;
|
modbus_msg->Except_Code = ET_ILLEGAL_DATA_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,9 +111,11 @@ void MB_WriteObjectsToMessage(RS_MsgTypeDef *modbus_msg, unsigned maxidofobj)
|
|||||||
*/
|
*/
|
||||||
uint8_t MB_Process_Read_Device_Identifications(RS_MsgTypeDef *modbus_msg)
|
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,29 +135,38 @@ 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)
|
||||||
{
|
{
|
||||||
modbus_msg->DevId.NextObjId = 0x80;
|
modbus_msg->DevId.NextObjId = 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
MB_WriteObjectsToMessage(modbus_msg, 0x80+MODBUS_NUMB_OF_USEROBJECTS);
|
MB_WriteObjectsToMessage(modbus_msg, 0x80+MODBUS_NUMB_OF_USEROBJECTS);
|
||||||
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;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
|
if(modbus_msg->Except_Code != ET_NO_ERRORS)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -158,400 +183,391 @@ void MB_DeviceInentificationInit(void)
|
|||||||
MB_ObjectInit(&MB_DEVID.ProductName, MODBUS_PRODUCT_NAME);
|
MB_ObjectInit(&MB_DEVID.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
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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, ®_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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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,10 +436,11 @@ 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;
|
||||||
|
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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 терминалки от двигателей)
|
||||||
@@ -64,4 +68,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif //_MODBUS_CONFIG_H_
|
#endif //_MODBUS_CONFIG_H_
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -156,4 +156,4 @@ extern MB_DataStructureTypeDef MB_DATA;
|
|||||||
#endif //_MODBUS_DATA_H_
|
#endif //_MODBUS_DATA_H_
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
///////////////////////TEMP/OUTDATE/OTHER////////////////////
|
///////////////////////TEMP/OUTDATE/OTHER////////////////////
|
||||||
|
|||||||
Reference in New Issue
Block a user