Loading...
Searching...
No Matches
Инструкция по подключению релиза библиотеки STM Modbus

Данная библиотека подключается напрямую из Git, как субмодуль. Позволяя при желании обновлять её напрямую через git.

# Структура библиотеки

*Note: Файлы начинающиеся с __ и которых нет в этом дереве являются **внутренними/непротестированными/недокументированными***

Modbus/ Иерархия модулей:
│ inc/ modbus
│ ├── modbus.h # Главный заголовочный файл modbus_slave
│ ├── modbus_core.h # Базовые определения и структуры modbus_master
│ ├── modbus_coils.h # Работа с дискретными выходами ├── modbus_coils
│ ├── modbus_holdregs.h # Работа с регистрами хранения ├── modbus_inputregs
│ ├── modbus_inputregs.h # Работа с входными регистрами ├── modbus_inputregs
│ ├── modbus_devid.h # Идентификация устройства ├── modbus_devid
│ ├── rs_message.h # Драйвер обмена по RS/UART ├── modbus_diag
├── src/ └── rs_message
│ ├── modbus.c # Основная логика Modbus │
│ ├── modbus_slave.c # Основная логика Slave Modbus └── modbus_core (единое ядро)
│ ├── modbus_master.c # Основная логика Master Modbus ├── modbus_config
│ ├── modbus_coils.c # Реализация работы с coils ├── modbus_data
│ ├── modbus_holdregs.c # Реализация регистров хранения └── __crc_algs
│ ├── modbus_inputregs.c # Реализация входных регистров
│ ├── modbus_devid.c # Реализация идентификации устройства
│ ├── modbus_data.c # Функции доступа к данным
│ └── rs_message.c # Реализация драйвера RS
├── __modbus_config.h # Конфигурация Modbus (надо заменить)
├── __modbus_data.h # Структуры данных (надо заменить)
└── __modbus_data.c # Функции доступа (надо заменить)

# Инструкция по подключению

## 1. Склонируйте субмодуль в ваш проект:

git submodule add https://git.arktika.cyou/set506/STM32_Modbus path/to/Modbus
git submodule update --init --recursive

## 2. Скопируйте файлы конфигурации в отдельную папку в вашем проекте (вне субмодуля) и удалите __ из имени файлов:

ProjectRoot/
├── Configs/
│ ├── modbus_config.h # скопировать из __modbus_config.h
│ ├── modbus_data.h # скопировать из __modbus_data.h
│ └── modbus_data.c # скопировать из __modbus_data.c
└── Modbus/ # Субмодуль

## 3. Настройте конфигурацию под ваш проект:

### 3.1. Настройка периферии

- UART: Настройте в режиме Asynchronous, нужная скорость (9600, 19200, etc), 8N1
- TIM: Настройте таймер для генерации прерываний (например, 1ms tick)
- Включите прерывания для UART и TIM

### 3.2. Подключение обработчиков прерываний

Подключите обработчики прерываний UART и TIM в свои IRQ обработчики вместо HAL-обработчиков:

#include "modbus.h"
void USARTx_IRQHandler(void)
{
RS_UART_Handler(&hmodbus1);
return;
HAL_UART_IRQHandler(&huart);
}
void TIMx_IRQHandler(void)
{
RS_TIM_Handler(&hmodbus1);
return;
HAL_TIM_IRQHandler(&htim);
}
RS_TIM_Handler
void RS_TIM_Handler(RS_HandleTypeDef *hRS)
Обработчик прерывания TIM.
Definition rs_message.c:433
RS_UART_Handler
void RS_UART_Handler(RS_HandleTypeDef *hRS)
Обработчик прерывания UART.
Definition rs_message.c:320
hmodbus1
RS_HandleTypeDef hmodbus1
Default Handle for Modbus.
Definition modbus.c:24
modbus.h
Главный заголовочный файл Modbus библиотеки

### 3.3. В modbus_config.h укажите параметры устройства

### 3.4. Инициализация в коде

Чтобы настроить Slave-режим main() после инициализации HAL:

#include "modbus.h"
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, MODBUS_DEVICE_ID, MODBUS_TIMEOUT, MODBUS_MODE_SLAVE);
// Запуск приема Modbus
MODBUS_SlaveStart(&hmodbus1, NULL);
while (1)
{
// Основной цикл
}
}
mb_huart
#define mb_huart
Удобный дефайн для модбасовского uart.
Definition modbus_config.h:41
MODBUS_TIMEOUT
#define MODBUS_TIMEOUT
Таймаут в тиках таймера
Definition modbus_config.h:26
mb_htim
#define mb_htim
Удобный дефайн для модбасовского таймера
Definition modbus_config.h:42
MODBUS_DEVICE_ID
#define MODBUS_DEVICE_ID
Адрес устройства в сети Modbus.
Definition modbus_config.h:25
MODBUS_Config
HAL_StatusTypeDef MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint8_t master)
Программная конфигурация модбас.
Definition modbus.c:72
MODBUS_SlaveStart
HAL_StatusTypeDef MODBUS_SlaveStart(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
Запуск слейв модбас.
Definition modbus.c:105
MODBUS_FirstInit
HAL_StatusTypeDef MODBUS_FirstInit(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim)
Инициализация периферии модбас.
Definition modbus.c:42
MODBUS_MODE_SLAVE
#define MODBUS_MODE_SLAVE
Псевдо-enum: Режим слейв
Definition modbus.h:117

Чтобы настроить Master-режим main() после инициализации HAL:

#include "modbus.h"
// Запрос на 1 ID, считать холдинг регистры с 0 адреса 10 штук
RS_MsgTypeDef read_hold_cmd = MB_REQUEST_READ_HOLDING_REGS(1, 0, 10);
// коллбек, вызовется при получении ответа от слейва
read_hold[10];
void callback_func(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
{
// MB_RespGet_... Чтобы достать нужные данные из ответа
if(hmodbus->RS_STATUS == RS_OK)
{
for(int addr = MODBUS_MSG.Addr; addr < MODBUS_MSG.Addr + MODBUS_MSG.Qnt; addr++)
{
uint16_t value;
if(MB_RespGet_RegisterValue(&MODBUS_MSG, addr, &value))
{
read_hold[i] = value;
}
}
}
}
int main(void)
{
// Инициализация HAL
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM3_Init();
// Инициализация Modbus
MODBUS_FirstInit(&hmodbus1, &mb_huart, &mb_htim);
MODBUS_Config(&hmodbus1, 0, MODBUS_TIMEOUT, MODBUS_MODE_MASTER);
// Запрос по Modbus
MODBUS_MasterRequest(&hmodbus1, &read_hold_cmd, &callback_func);
}
MODBUS_MasterRequest
HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, void(*pClbk)(RS_HandleTypeDef *, RS_MsgTypeDef *))
Реквест мастера модбас.
Definition modbus.c:136
MODBUS_MODE_MASTER
#define MODBUS_MODE_MASTER
Псевдо-enum: Режим мастер
Definition modbus.h:113
MODBUS_MSG
RS_MsgTypeDef MODBUS_MSG
Default Message Struct for Modbus.
Definition modbus.c:25
MB_RespGet_RegisterValue
int MB_RespGet_RegisterValue(RS_MsgTypeDef *modbus_msg, uint16_t reg_addr, uint16_t *reg_value)
Получить значение регистра в ответе по его адресу
Definition modbus_master.c:63
MB_REQUEST_READ_HOLDING_REGS
RS_MsgTypeDef MB_REQUEST_READ_HOLDING_REGS(uint8_t slave_addr, uint16_t start_addr, uint16_t quantity)
Сформировать запрос на чтение холдинг регистров
Definition modbus_master.c:598
RS_HandleTypeDef
Handle for RS communication.
Definition rs_message.h:228
RS_HandleTypeDef::RS_STATUS
RS_StatusTypeDef RS_STATUS
Статус RS.
Definition rs_message.h:247
RS_MsgTypeDef
Structure for modbus messsage.
Definition modbus_core.h:177

### 3.5. Настройка карты данных

В modbus_data.h настройте регистры и coils под ваше устройство:

Input Registers (только чтение)

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 регистров
MB_DataInRegsTypeDef
Регистры хранения
Definition modbus_data.h:91

Holding Registers (чтение/запись)

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 регистров
MB_DataHoldRegsTypeDef
Входные регистры
Definition modbus_data.h:100

Coils (1-битные)

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
MB_DataCoilsTypeDef
Коилы
Definition modbus_data.h:130

### 3.6. Доступ к данным в коде

В режиме слейва есть дефайны для удобного выставления Коилов. На случай если они не упакованы в битовые поля

// Чтение входных регистров
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_Coil_Read_Local
#define MB_Coil_Read_Local(_parr_, _coil_)
Считать коил по локальному адресу.
Definition modbus_coils.h:71
MB_Coil_Set_Local
#define MB_Coil_Set_Local(_parr_, _coil_)
Выставить коил по локальному адресу.
Definition modbus_coils.h:79
MB_Coil_Reset_Local
#define MB_Coil_Reset_Local(_parr_, _coil_)
Сбросить коил по локальному адресу.
Definition modbus_coils.h:87

В режиме мастера есть функции для получения информации из ответа MB_RespGet_...()

// Чтение регистров: Получить запрошенные регистры
uint16_t value;
if(MB_RespGet_RegisterValue(&MODBUS_MSG, 105, &reg_value))
{
printf("Register 105 value: %d\n", reg_value);
}
// Чтение коилов: Получить запрошенные коилы
int state;
if(MB_RespGet_CoilState(&MODBUS_MSG, 25, &coil_state))
{
printf("Coil 25 state: %s\n", coil_state ? "ON" : "OFF");
}
// Чтение диагностики: Получить запрошенныую диагностику
uint16_t counter_value;
if(MB_RespGet_DiagnosticResponse(&MODBUS_MSG, &counter_value))
{
printf("Counter value: %d\n", counter_value);
}
// Чтение идентификаторов: Получить запрошенные идентификаторы
uint8_t length;
char vendor_name[64];
if(MB_RespGet_ObjectById(&MODBUS_MSG, 0x00, vendor_name, &length))
{
printf("Vendor Name: %s (length: %d)\n", vendor_name, length);
}
uint8_t obj_id, obj_length;
char obj_data[64];
if(MB_RespGet_ObjectByIndex(&MODBUS_MSG, 0x00, &obj_id, obj_data, &obj_length))
{
printf("First object - ID: 0x%02X, Data: %s\n", obj_id, obj_data);
}
MB_RespGet_CoilState
int MB_RespGet_CoilState(RS_MsgTypeDef *modbus_msg, uint16_t coil_addr, int *coil_state)
Получить состояние coil в ответе по его адресу
Definition modbus_master.c:127
MB_RespGet_ObjectById
int MB_RespGet_ObjectById(RS_MsgTypeDef *modbus_msg, uint8_t obj_id, char *obj_data, uint8_t *obj_length)
Найти объект по ID в сообщении
Definition modbus_master.c:193
MB_RespGet_ObjectByIndex
int MB_RespGet_ObjectByIndex(RS_MsgTypeDef *modbus_msg, int index, uint8_t *obj_id, char *obj_data, uint8_t *obj_length)
Получить объект по индексу в сообщении
Definition modbus_master.c:244

## 5. Обновление библиотеки:

После обновления субмодуля из Git, исходные файлы библиотеки будут обновлены, и ваши конфиги вне субмодуля не перезапишутся:

git submodule update --remote