- чуть переделаны некоторые дефайны для универсализации - смена направления сделана через указател на функцию, а не глобальный дефайн - добавлен бета осцилограф модбас - некоторый рефакторинг
216 lines
7.1 KiB
C
216 lines
7.1 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
|
|
* @param pSetDirection Указатель на функцию для смены направления RS485
|
|
* @details Подключает хендлы периферии к hmodbus
|
|
* Конфигурация выставляется по умолчанию из modbus_config.h
|
|
*/
|
|
HAL_StatusTypeDef MODBUS_FirstInit(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim, void (*pSetDirection)(int Tx))
|
|
{
|
|
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, pSetDirection);
|
|
|
|
if(hmodbus->pSetDirection)
|
|
hmodbus->pSetDirection(0);
|
|
|
|
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);
|
|
}
|
|
}
|