214 lines
6.9 KiB
C
214 lines
6.9 KiB
C
/**
|
||
*******************************************************************************
|
||
* @file modbus.c
|
||
* @brief Модуль для реализации MODBUS.
|
||
*******************************************************************************
|
||
* @details
|
||
Файл содержит реализацию функций работы с Modbus.
|
||
|
||
@section mbapi Функции и макросы
|
||
|
||
### Инициализация:
|
||
- MODBUS_FirstInit() — Инициализация Modbus (подключение UART, TIM)
|
||
- MODBUS_Config() — Конфигурацмя Modbus (ID, Timeout).
|
||
- MODBUS_SlaveStart() — Запуск Modbus как Slave.
|
||
- MODBUS_MasterRequest() — Отправить запрос в MODBUS как Master.
|
||
|
||
### Функции для работы с RS (UART):
|
||
- RS_Parse_Message() / RS_Collect_Message() — Парсинг и сборка сообщения.
|
||
- RS_Response() — Отправка ответа.
|
||
******************************************************************************/
|
||
#include "modbus.h"
|
||
|
||
/* MODBUS HANDLES */
|
||
RS_HandleTypeDef hmodbus1; ///< Default Handle for Modbus
|
||
RS_MsgTypeDef MODBUS_MSG; ///< Default Message Struct for Modbus
|
||
|
||
|
||
static void MB_DefaultCallback(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg);
|
||
|
||
//-------------------------------------------------------------------
|
||
//-----------------------------FOR USER------------------------------
|
||
/**
|
||
* @brief Инициализация периферии модбас.
|
||
* @param hmodbus Указатель на хендлер RS
|
||
* @param huart Указатель на хендлер UART
|
||
* @param htim Указатель на хендлер TIM
|
||
* @details Подключает хендлы периферии к hmodbus
|
||
* Конфигурация выставляется по умолчанию из modbus_config.h
|
||
*/
|
||
HAL_StatusTypeDef MODBUS_FirstInit(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim)
|
||
{
|
||
if((hmodbus == NULL) || (huart == NULL))
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
MB_DeviceInentificationInit();
|
||
//-----------SETUP MODBUS-------------
|
||
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
||
hmodbus->ID = MODBUS_DEVICE_ID;
|
||
hmodbus->sRS_Timeout = MODBUS_TIMEOUT;
|
||
hmodbus->sRS_Mode = RS_SLAVE_ALWAYS_WAIT;
|
||
|
||
// INIT
|
||
hmodbus->RS_STATUS = RS_Init(hmodbus, huart, htim, 0);
|
||
|
||
RS_EnableReceive();
|
||
|
||
if(hmodbus->RS_STATUS == RS_OK)
|
||
return HAL_OK;
|
||
else
|
||
return HAL_ERROR;
|
||
}
|
||
/**
|
||
* @brief Программная конфигурация модбас.
|
||
* @param hmodbus указатель на хендлер RS
|
||
* @param Timeout Время тишины между двумя байтами после которых перезапускается прием
|
||
* @param master Режим мастер (пока не сделан)
|
||
* @details Конфигурирует ID, таймаут и режим hmodbus
|
||
*/
|
||
HAL_StatusTypeDef MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint8_t master)
|
||
{
|
||
if(hmodbus == NULL)
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
if(!master)
|
||
{
|
||
if((ID < 1) || (ID > 247))
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
hmodbus->ID = ID;
|
||
}
|
||
else
|
||
hmodbus->ID = 0;
|
||
|
||
hmodbus->sRS_Timeout = Timeout;
|
||
if(master)
|
||
hmodbus->sRS_Mode = RS_MASTER_REQUEST;
|
||
else
|
||
hmodbus->sRS_Mode = RS_SLAVE_ALWAYS_WAIT;
|
||
|
||
return HAL_OK;
|
||
}
|
||
|
||
/**
|
||
* @brief Запуск слейв модбас.
|
||
* @param hmodbus Указатель на хендлер RS.
|
||
* @param modbus_msg Указатель на структуру сообщения.
|
||
(NULL чтобы использовать дефолтную)
|
||
* @details Конфигурирует ID, таймаут и режим hmodbus
|
||
*/
|
||
HAL_StatusTypeDef MODBUS_SlaveStart(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
||
{
|
||
if(hmodbus == NULL)
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
|
||
if(hmodbus->sRS_Mode >= RS_MASTER_MODE_START)
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
|
||
MB_DiagnosticsInit();
|
||
|
||
if(modbus_msg)
|
||
hmodbus->RS_STATUS = RS_Receive_IT(hmodbus, modbus_msg);
|
||
else
|
||
hmodbus->RS_STATUS = RS_Receive_IT(hmodbus, &MODBUS_MSG);
|
||
|
||
if(hmodbus->RS_STATUS == RS_OK)
|
||
return HAL_OK;
|
||
else
|
||
return HAL_ERROR;
|
||
}
|
||
|
||
/**
|
||
* @brief Реквест мастера модбас.
|
||
* @param hmodbus Указатель на хендлер RS.
|
||
* @param modbus_msg Указатель на структуру сообщения
|
||
* @details Конфигурирует ID, таймаут и режим hmodbus
|
||
*/
|
||
HAL_StatusTypeDef MODBUS_MasterRequest(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, void (*pClbk)(RS_HandleTypeDef*, RS_MsgTypeDef*))
|
||
{
|
||
if(hmodbus == NULL)
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
if(modbus_msg == NULL)
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
if(hmodbus->sRS_Mode < RS_MASTER_MODE_START)
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
|
||
if(hmodbus->f.RS_Busy)
|
||
return HAL_BUSY;
|
||
|
||
if(pClbk) // если задан используем пользовательский коллбек
|
||
hmodbus->pCallback = (void (*)(void*, void*))(pClbk);
|
||
else // иначе дефолтный
|
||
hmodbus->pCallback = (void (*)(void*, void*))(&MB_DefaultCallback);
|
||
|
||
hmodbus->RS_STATUS = RS_Transmit_IT(hmodbus, modbus_msg);
|
||
|
||
if(hmodbus->RS_STATUS == RS_OK)
|
||
return HAL_OK;
|
||
else
|
||
return HAL_ERROR;
|
||
}
|
||
|
||
//-------------------------------------------------------------------
|
||
//-----------------------------INTERNAL------------------------------
|
||
|
||
/**
|
||
* @brief Дефолтный коллбек для мастера.
|
||
* @param hmodbus Указатель на хендлер RS
|
||
* @param modbus_msg Указатель на структуру сообщения
|
||
* @details В этот коллбек попадут все запросы, с NULL-коллбеком
|
||
*/
|
||
static void MB_DefaultCallback(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
||
{
|
||
__NOP();
|
||
return;
|
||
}
|
||
|
||
|
||
/* Реализация функций из rs_message.c для протокола */
|
||
RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
||
{
|
||
if(hmodbus->sRS_Mode >= RS_MASTER_MODE_START)
|
||
{
|
||
return RS_ERR;
|
||
}
|
||
return MB_Slave_Response(hmodbus, modbus_msg);
|
||
}
|
||
|
||
RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
|
||
{
|
||
if(hmodbus->sRS_Mode < RS_MASTER_MODE_START)
|
||
{
|
||
return MB_Slave_Collect_Message(hmodbus, modbus_msg, modbus_uart_buff);
|
||
}
|
||
else
|
||
{
|
||
return MB_Master_Collect_Message(hmodbus, modbus_msg, modbus_uart_buff);
|
||
}
|
||
}
|
||
|
||
RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg, uint8_t *modbus_uart_buff)
|
||
{
|
||
if(hmodbus->sRS_Mode < RS_MASTER_MODE_START)
|
||
{
|
||
return MB_Slave_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff);
|
||
}
|
||
else
|
||
{
|
||
return MB_Master_Parse_Message(hmodbus, modbus_msg, modbus_uart_buff);
|
||
}
|
||
}
|