API ПОМЕНЯЛОС - Реструктуризация модбас

- Переработана архитектура:
  * modbus_core.h - базовые определения и структуры
  * modbus_coils.[h/c] - работа с коилами
  * modbus_holdregs.[h/c] - работа с регистрами хранения (R/W)
  * modbus_inputregs.[h/c] -работа с входными регистрами (R/O)
  * modbus_devid.[h/c] - идентификаторы устройства
  * modbus_data.[h/c] - карта регистров и коилов и валидация адресов

- Улучшена документация:
  * Обновлены Doxygen-комментарии к функциям
  * Обновлены шапки файлов с подробным описанием
  * Обновлена инструкция по подключению и использованию
This commit is contained in:
2025-11-03 19:32:53 +03:00
parent 52de3f9c08
commit 7e21fc7f28
36 changed files with 6269 additions and 2259 deletions

214
README.md
View File

@@ -1,73 +1,165 @@
# Modbus: подключение и использование
Это вариант голого (bare) modbus, где вся инициализация скинута на CubeMX
# STM Modbus: подключение и использование
## Настройка
Библиотека реализует Modbus RTU Slave для STM32 с использованием HAL. Работает в прерываниях с детектированием конца фрейма по IDLE линии и таймаутами через прерывание таймера.
1. Подключите обработчики прерываний **UART** и **TIM** в свои IRQ обработчики после HAL-обработчиков:
## Быстрый старт
_Note: Здесь описано подключение просто архива c исходниками. Если надо подключить библиотеку как субмодуль: см. ветку release в этом репозитории._
```c
#include "rs_message.h"
### 1. Настройка периферии
void USARTx_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart);
RS_UART_Handler(&modbus1);
}
- **UART**: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1
- **TIM**: Настройте таймер для генерации прерываний (например, 1ms tick)
- **Включите прерывания** для UART и TIM
void TIMx_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim);
RS_TIM_Handler(&modbus1);
}
```
### 2. Подключение обработчиков прерываний
2. Настройте `modbus_config.h`:
Подключите обработчики прерываний **UART** и **TIM** в свои IRQ обработчики ***вместо*** HAL-обработчиков:
```c
// MODBUS PARAMS
#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства
#define MODBUS_TIMEOUT 5000 ///< максимальнйы тайтаут MB в тиках таймера
```c
#include "modbus.h"
void USARTx_IRQHandler(void)
{
RS_UART_Handler(&modbus1);
return;
HAL_UART_IRQHandler(&huart);
}
void TIMx_IRQHandler(void)
{
RS_TIM_Handler(&modbus1);
return;
HAL_TIM_IRQHandler(&htim);
}
```
### 3. Настройка конфигурации
В `modbus_config.h` укажите параметры устройства:
```c
// MODBUS PARAMS
#define MODBUS_DEVICE_ID 1 // Адрес устройства в сети Modbus
#define MODBUS_TIMEOUT 100 // Таймаут в тиках таймера (рекомендуется 100-200ms)
// Строковые идентификаторы устройства
#define MODBUS_VENDOR_NAME "NIO-12"
#define MODBUS_PRODUCT_CODE ""
#define MODBUS_REVISION "Ver. 1.0"
#define MODBUS_VENDOR_URL ""
#define MODBUS_PRODUCT_NAME ""
#define MODBUS_MODEL_NAME "STM32F103"
#define MODBUS_USER_APPLICATION_NAME ""
#define MODBUS_NUMB_OF_USEROBJECTS 0
// Периферия
#define mb_huart huart1 // Удобный дефайн для модбасовского UART
#define mb_htim htim3 // Удобный дефайн для модбасовского таймера
```
### 4. Инициализация в коде
В `main()` после инициализации HAL:
```c
#include "modbus.h"
int main(void)
{
// Инициализация HAL
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM3_Init();
// PERIPH FUNCTIONS AND HANDLERS
#define RS_UART_Init MX_USART1_UART_Init
#define RS_UART_DeInit HAL_UART_MspDeInit
#define RS_TIM_Init MX_TIM3_Init
#define RS_TIM_DeInit HAL_TIM_Base_MspDeInit
#define rs_huart huart1
#define rs_htim htim3
```
3. Для инициализации Modbus добавьте:
```c
#include "rs_message.h"
MODBUS_FirstInit();
```
4. Настройка регистров и коилов
Все данные объединены в общую структуру устройства `MB_DataStructureTypeDef`, которая содержит:
- Входные регистры (`InRegs`) - 16-битные регистры только для чтения
- Коилы (`Coils`) - 1-битовые коилы для чтения/записи
- Регистры хранения (`HoldRegs`) - 16-битные регистры для чтения/записи
// Инициализация Modbus
MODBUS_SetupHardware(&hmodbus1, &mb_huart, &mb_htim);
Пример настройки `Input Registers`:
```c
typedef struct //MB_DataInRegsTypeDef
// Запуск приема Modbus
MODBUS_SlaveStart(&hmodbus1, &MODBUS_MSG);
while (1)
{
uint16_t ForwardVoltage;
uint16_t ReversePeakVoltage;
}MB_DataInRegsTypeDef;
// Основной цикл
}
}
```
// DEFINES FOR INPUT REGISTERS ARRAYS
#define R_INPUT_ADDR 0 // начальный адресс инпут регистров
#define R_INPUT_QNT 2 // количество инпут регистров
```
Аналогично с `Hodling Registers` и `Coils` (в коилах только желательно использовать битовые поля)
### 5. Настройка карты данных
5. Для запуска Modbus вызовите:
```c
RS_Receive_IT(&hmodbus1, &MODBUS_MSG);
```
В `modbus_data.h` настройте регистры и coils под ваше устройство:
#### Input Registers (только чтение)
```c
typedef struct
{
uint16_t Temperature; // Адрес 0
uint16_t Humidity; // Адрес 1
uint16_t Pressure; // Адрес 2
uint16_t Voltage; // Адрес 3
} MB_DataInRegsTypeDef;
#define R_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;
#define R_HOLDING_ADDR 0 // Начальный адрес Holding регистров
#define R_HOLDING_QNT 3 // Количество Holding регистров
```
#### Coils (1-битные)
```c
typedef struct
{
unsigned Relay1 : 1; // Адрес 0
unsigned Relay2 : 1; // Адрес 1
unsigned Pump : 1; // Адрес 2
unsigned Heater : 1; // Адрес 3
unsigned reserved : 12; // Резерв (выравнивание до 16 бит)
} MB_DataCoilsTypeDef;
#define C_COILS_ADDR 0 // Начальный адрес Coils
#define C_COILS_QNT 4 // Количество Coils
```
### 6. Доступ к данным в коде
```c
// Чтение входных регистров
uint16_t temp = MB_DATA.InRegs.Temperature;
// Запись в регистры хранения
MB_DATA.HoldRegs.SetpointTemp = 2500;
// Управление coils
MB_Set_Coil_Local(&MB_DATA.Coils, 0); // Включить Relay1
MB_Reset_Coil_Local(&MB_DATA.Coils, 1); // Выключить Relay2
// Чтение coil
if (MB_Read_Coil_Local(&MB_DATA.Coils, 2)) {
// Pump включен
}
```
## Поддерживаемые функции Modbus
| Функция | Код | Описание |
|---------|-----|-----------|
| Read Coils | 0x01 | Чтение дискретных выходов |
| Read Input Registers | 0x04 | Чтение входных регистров |
| Read Holding Registers | 0x03 | Чтение регистров хранения |
| Write Single Coil | 0x05 | Запись одиночного coil |
| Write Single Register | 0x06 | Запись одиночного регистра |
| Write Multiple Coils | 0x0F | Запись множественных coils |
| Write Multiple Registers | 0x10 | Запись множественных регистров |
| Read Device Identification | 0x2B | Чтение идентификации устройства |