release 0.51

Бета добавление новых кодов исключения

Улучшение механики ответа с задержкой, когда время ответа определяется пользователем, а не в прерывании сразу
This commit is contained in:
2026-02-20 16:39:15 +03:00
parent ca8fa259c8
commit 7d40b019fb
4 changed files with 81 additions and 12 deletions

View File

@@ -72,15 +72,17 @@ first receive info part of message, than defines size of rest message*/
*/ */
typedef enum //MB_ExceptionTypeDef typedef enum //MB_ExceptionTypeDef
{ {
// reading /* Регулярные коды ошибок, которые определены конкретной программой */
ET_NO_ERRORS = 0x00, ///< no errors ET_NO_ERRORS = 0x00, ///< no errors
ET_ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан ET_ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан
ET_ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен ET_ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен
ET_ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной ET_ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной
ET_SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие ET_SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие
// ET_ACKNOWLEDGE = 0x05, ///< idk
// ET_SLAVE_DEVICE_BUSY = 0x06, ///< idk /* Специальные коды ошибок, которые определены конкретной программой */
// ET_MEMORY_PARITY_ERROR = 0x08, ///< idk ET_ACKNOWLEDGE = 0x05, ///< Устройство приняло запрос, но на обработку требуется время. Нужно чтобы не было Timeout ошибки
ET_SLAVE_DEVICE_BUSY = 0x06, ///< Устройство занято обработкой комманды
ET_MEMORY_PARITY_ERROR = 0x08, ///< Ошибка внешней памяти
}MB_ExceptionTypeDef; }MB_ExceptionTypeDef;
#define FC_ERR_VALUES_START 0x80U ///< from this value starts error func codes #define FC_ERR_VALUES_START 0x80U ///< from this value starts error func codes

View File

@@ -21,6 +21,10 @@
* @{ * @{
*/ */
/* Ответить позже, не в прерывании */
HAL_StatusTypeDef MB_Slave_ResponseLater(RS_HandleTypeDef *hmodbus, uint8_t ResponseCode);
/* Ответить на запрос */
HAL_StatusTypeDef MB_Slave_SendResponse(RS_HandleTypeDef *hmodbus, uint8_t ResponseCode, MB_ExceptionTypeDef error);
/* Ответ на сообщение в режиме слейва */ /* Ответ на сообщение в режиме слейва */
RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg); RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg);
/* Сбор сообщения в буфер UART в режиме слейв (фрейм слейва из msg -> uart) */ /* Сбор сообщения в буфер UART в режиме слейв (фрейм слейва из msg -> uart) */

View File

@@ -219,11 +219,13 @@ typedef struct
unsigned TX_Done:1; ///< 1 - Передача закончена, 0 - Передача еще в процессе или не инициализирована unsigned TX_Done:1; ///< 1 - Передача закончена, 0 - Передача еще в процессе или не инициализирована
// Выставление следующие флагов определяет пользователь // Выставление следующие флагов определяет пользователь
unsigned RX_Continue:1; ///< 0 - Продолжить принимать, 0 - Начать прием сначала unsigned RX_Continue:1; ///< 1 - Продолжить принимать, 0 - Начать прием сначала
unsigned MessageHandled:1; ///< 1 - Обработка запроса успешна, 0 - Обработка запроса в процессе или ошибка unsigned MessageHandled:1; ///< 1 - Обработка запроса успешна, 0 - Обработка запроса в процессе или ошибка
unsigned EchoResponse:1; ///< 1 - Ответить эхом, 0 - Ответить своим сообщением unsigned EchoResponse:1; ///< 1 - Ответить эхом, 0 - Ответить своим сообщением
unsigned DeferredResponse:1; ///< 1 - Не начинать передачу в IT, 0 - Ответить в прерывании unsigned DataUpdated:1; ///< 1 - Данные были обновлены:
unsigned DataUpdated:1; ///< 1 - Данные были обновлены unsigned DeviceBusy:1; ///< 1 - Устройство занято (важно! не rs а именно устрройство)
unsigned DeferredResponse:8; ///< >0 - Не начинать передачу в IT, 0 - Ответить в прерывании
}RS_FlagsTypeDef; }RS_FlagsTypeDef;

View File

@@ -7,6 +7,8 @@
Файл содержит реализацию функций для работы Modbus в режиме слейва. Файл содержит реализацию функций для работы Modbus в режиме слейва.
@section slave Функции и макросы @section slave Функции и макросы
- MB_Slave_ResponseLater() — Выставить флаг на ответ вне прерывания
- MB_Slave_SendResponse() — Ответить на запрос
- MB_Slave_Response() — Ответ на запрос - MB_Slave_Response() — Ответ на запрос
- MB_Slave_Collect_Message() — Сбор сообщения в режиме слейва. - MB_Slave_Collect_Message() — Сбор сообщения в режиме слейва.
@@ -15,6 +17,66 @@
#include "modbus.h" #include "modbus.h"
#ifdef MODBUS_ENABLE_SLAVE #ifdef MODBUS_ENABLE_SLAVE
/**
* @brief Ответить позже, не в прерывании.
* @param hmodbus Указатель на хендлер RS.
* @param ResponseCode Код запроса на который надо ответить.
* @return HAL Status.
* @details Отменяет ответ в прерывании на запрос.
Используется вместе с @ref MB_Slave_SendResponse
*/
HAL_StatusTypeDef MB_Slave_ResponseLater(RS_HandleTypeDef *hmodbus, uint8_t ResponseCode)
{
hmodbus->f.DeferredResponse = ResponseCode;
return HAL_OK;
}
/**
* @brief Ответить на запрос.
* @param hmodbus Указатель на хендлер RS.
* @param ResponseCode Код запроса на который надо ответить.
* @param error Тип ошибки или её отсутствия в ответе.
* @return HAL Status.
* @details Ответить на запрос вне прерывания.
Используется вместе с @ref MB_Slave_ResponseLater
*/
HAL_StatusTypeDef MB_Slave_SendResponse(RS_HandleTypeDef *hmodbus, uint8_t ResponseCode, MB_ExceptionTypeDef error)
{
RS_StatusTypeDef MB_RES = 0;
if(hmodbus->f.DeferredResponse == ResponseCode)
{
hmodbus->f.DeferredResponse = 0;
switch(error)
{
case ET_NO_ERRORS:
break;
case ET_ACKNOWLEDGE:
MB_Diagnostics_SlaveNAKCnt();
break;
case ET_SLAVE_DEVICE_BUSY:
MB_Diagnostics_SlaveBusyCnt();
break;
default:
break;
}
if(error != ET_NO_ERRORS)
{
MB_Diagnostics_ExceptionErrorCnt();
TrackerCnt_Warn(hmodbus->rs_err);
hmodbus->pMessagePtr->FuncCode |= FC_ERR_VALUES_START;
hmodbus->pMessagePtr->Except_Code = error;
}
hmodbus->RS_STATUS = RS_Handle_Transmit_Start(hmodbus, hmodbus->pMessagePtr);
}
return HAL_OK;
}
/** /**
* @brief Ответ на сообщение в режиме слейва. * @brief Ответ на сообщение в режиме слейва.
* @param hmodbus Указатель на хендлер RS. * @param hmodbus Указатель на хендлер RS.
@@ -117,7 +179,6 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod
modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */ modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */
} }
// Проверяем режим устройства - если Listen Only, не обрабатываем команды // Проверяем режим устройства - если Listen Only, не обрабатываем команды
if (MB_GetDeviceMode() == MODBUS_LISTEN_ONLY_MODE) if (MB_GetDeviceMode() == MODBUS_LISTEN_ONLY_MODE)
{ {
@@ -152,8 +213,8 @@ RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *mod
} }
else else
{ {
RS_Handle_Receive_Start(hmodbus, modbus_msg); // RS_Handle_Receive_Start(hmodbus, modbus_msg);
hmodbus->f.DeferredResponse = 0; // hmodbus->f.DeferredResponse = 0;
} }
hmodbus->RS_STATUS = MB_RES; hmodbus->RS_STATUS = MB_RES;
@@ -173,7 +234,7 @@ RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_MsgTypeD
{ {
int ind = 0; // ind for modbus-uart buffer int ind = 0; // ind for modbus-uart buffer
if(hmodbus->f.EchoResponse && hmodbus->f.MessageHandled) // if echo response need if(hmodbus->f.EchoResponse && (modbus_msg->Except_Code == ET_NO_ERRORS)) // if echo response need
ind = hmodbus->RS_Message_Size; ind = hmodbus->RS_Message_Size;
else else
{ {