release 0.2
Добавлен модуль диагностически модбас (функция 0x08) + мелкие кореркции
This commit is contained in:
@@ -27,7 +27,7 @@
|
|||||||
//----------------Прием модбас----------------//
|
//----------------Прием модбас----------------//
|
||||||
#include "modbus.h"
|
#include "modbus.h"
|
||||||
|
|
||||||
MODBUS_SetupHardware(&hmodbus1, &huart1, &htim3);
|
MODBUS_FirstInit(&hmodbus1, &huart1, &htim3);
|
||||||
MODBUS_SlaveStart(&hmodbus1, NULL);
|
MODBUS_SlaveStart(&hmodbus1, NULL);
|
||||||
// или если нужно переключится на другой
|
// или если нужно переключится на другой
|
||||||
@endverbatim
|
@endverbatim
|
||||||
@@ -68,6 +68,7 @@ MODBUS_SlaveStart(&hmodbus1, NULL);
|
|||||||
#include "modbus_holdregs.h"
|
#include "modbus_holdregs.h"
|
||||||
#include "modbus_inputregs.h"
|
#include "modbus_inputregs.h"
|
||||||
#include "modbus_devid.h"
|
#include "modbus_devid.h"
|
||||||
|
#include "modbus_diag.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -83,11 +84,11 @@ MODBUS_SlaveStart(&hmodbus1, NULL);
|
|||||||
@{
|
@{
|
||||||
*/
|
*/
|
||||||
/* Инициализация периферии модбас. */
|
/* Инициализация периферии модбас. */
|
||||||
void MODBUS_SetupHardware(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim);
|
HAL_StatusTypeDef MODBUS_FirstInit(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim);
|
||||||
/* Программная конфигурация модбас. */
|
/* Программная конфигурация модбас. */
|
||||||
void MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint8_t master);
|
HAL_StatusTypeDef MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint8_t master);
|
||||||
/* Запуск слейв устройства */
|
/* Запуск слейв устройства */
|
||||||
void MODBUS_SlaveStart(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg);
|
HAL_StatusTypeDef MODBUS_SlaveStart(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg);
|
||||||
/** MODBUS_INIT_FUNCTIONS
|
/** MODBUS_INIT_FUNCTIONS
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ typedef enum
|
|||||||
/**
|
/**
|
||||||
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS Modbus Data Access
|
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS Modbus Data Access
|
||||||
* @ingroup MODBUS_FUNCTIONS
|
* @ingroup MODBUS_FUNCTIONS
|
||||||
* @brief Функции для доступа к данным модбас (коилы)
|
* @brief Функции для доступа к данным модбас
|
||||||
@{
|
@{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* @file modbus_devid.h
|
* @file modbus_devid.h
|
||||||
* @brief Идентификация устройства Modbus
|
* @brief Идентификаторы устройства Modbus
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
@addtogroup MODBUS_DEVID Device Identificators Tools
|
@addtogroup MODBUS_DEVID Device Identificators Tools
|
||||||
@ingroup MODBUS_INTERNAL
|
@ingroup MODBUS_INTERNAL
|
||||||
@@ -53,30 +53,6 @@ extern MB_DeviceIdentificationTypeDef MB_DEVID;
|
|||||||
void MB_DeviceInentificationInit(void);
|
void MB_DeviceInentificationInit(void);
|
||||||
///////////////---DEVICE IDENTIVICATIONS DEFINES---//////////////////
|
///////////////---DEVICE IDENTIVICATIONS DEFINES---//////////////////
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
/////////////////---DEVICE DIAGNOSTICS DEFINES---////////////////////
|
|
||||||
|
|
||||||
/** @brief Структура со диагностической информацией устройства модбас */
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint16_t DiagnosticRegister;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint16_t BusMessage;
|
|
||||||
uint16_t BusCommunicationErr;
|
|
||||||
uint16_t BusExceptionErr;
|
|
||||||
uint16_t SlaveMessage;
|
|
||||||
uint16_t SlaveNoResponse;
|
|
||||||
uint16_t SlaveNAK;
|
|
||||||
uint16_t SlaveBusy;
|
|
||||||
uint16_t BusCharacterOverrun;
|
|
||||||
}Counters;
|
|
||||||
}MB_DiagnosticsInfoTypeDef;
|
|
||||||
extern MB_DiagnosticsInfoTypeDef MB_DINFO;
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////---DEVICE DIAGNOSTICS DEFINES---////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
////////////////////---MODBUS FUNCTION DEFINES---////////////////////
|
////////////////////---MODBUS FUNCTION DEFINES---////////////////////
|
||||||
|
|||||||
107
Inc/modbus_diag.h
Normal file
107
Inc/modbus_diag.h
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file modbus_diag.h
|
||||||
|
* @brief Диагностика устройства Modbus
|
||||||
|
******************************************************************************
|
||||||
|
@addtogroup MODBUS_DIAG Diagnostics Tools
|
||||||
|
@ingroup MODBUS_INTERNAL
|
||||||
|
@{
|
||||||
|
******************************************************************************
|
||||||
|
* @details
|
||||||
|
Модуль реализации Diagnostics (Serial Line only) (0x08):
|
||||||
|
- Полная поддержка всех подфункций диагностики
|
||||||
|
- Возможность выставить/сбросить любой бит в диагностическом регистре
|
||||||
|
- Сбор статистики работы устройства
|
||||||
|
- Управление режимами работы
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef __MODBUS_DIAG_H_
|
||||||
|
#define __MODBUS_DIAG_H_
|
||||||
|
#include "modbus_core.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////---DEVICE DIAGNOSTICS DEFINES---////////////////////
|
||||||
|
|
||||||
|
/** @brief Режимы работы устройства */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MODBUS_NORMAL_MODE = 0,
|
||||||
|
MODBUS_LISTEN_ONLY_MODE = 1
|
||||||
|
} MB_DeviceModeTypeDef;
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Структура со диагностической информацией устройства модбас */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t DiagnosticRegister;
|
||||||
|
MB_DeviceModeTypeDef DeviceMode;
|
||||||
|
uint8_t AsciiDelimiter;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t BusMessage;
|
||||||
|
uint16_t BusCommunicationErr;
|
||||||
|
uint16_t BusExceptionErr;
|
||||||
|
uint16_t SlaveMessage;
|
||||||
|
uint16_t SlaveNoResponse;
|
||||||
|
uint16_t SlaveNAK;
|
||||||
|
uint16_t SlaveBusy;
|
||||||
|
uint16_t BusCharacterOverrun;
|
||||||
|
} Counters;
|
||||||
|
} MB_DiagnosticsInfoTypeDef;
|
||||||
|
|
||||||
|
extern MB_DiagnosticsInfoTypeDef MB_DIAG;
|
||||||
|
|
||||||
|
/////////////////---DEVICE DIAGNOSTICS DEFINES---////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
/////////////////////////---FUNCTIONS---/////////////////////////////
|
||||||
|
|
||||||
|
/* Инициализация диагностических счетчиков */
|
||||||
|
void MB_DiagnosticsInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS Modbus Data Access
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Выставить бит в регистре диагностике */
|
||||||
|
int MB_Diagnostics_WriteBit(int bit_num, int bit_state);
|
||||||
|
/*ь Прочитать состояние бита диагностического регистра */
|
||||||
|
int MB_Diagnostics_GetBit(int bit_num);
|
||||||
|
/* Получение текущего режима устройства */
|
||||||
|
MB_DeviceModeTypeDef MB_GetDeviceMode(void);
|
||||||
|
/** MODBUS_CMD_PROCESS_FUNCTIONS
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------PROCESS MODBUS COMMAND FUNCTIONS---------
|
||||||
|
/**
|
||||||
|
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Обработка команды диагностики (0x08) */
|
||||||
|
uint8_t MB_Proccess_Diagnostics(RS_MsgTypeDef *modbus_msg);
|
||||||
|
|
||||||
|
/** MODBUS_CMD_PROCESS_FUNCTIONS
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Функции для обновления счетчиков диагностики */
|
||||||
|
void MB_Diagnostics_BusMessageCnt(void);
|
||||||
|
void MB_Diagnostics_CommunicationErrorCnt(void);
|
||||||
|
void MB_Diagnostics_ExceptionErrorCnt(void);
|
||||||
|
void MB_Diagnostics_CharacterOverrunCnt(void);
|
||||||
|
void MB_Diagnostics_SlaveMessageCnt(void);
|
||||||
|
void MB_Diagnostics_SlaveNoResponseCnt(void);
|
||||||
|
void MB_Diagnostics_SlaveNAKCnt(void);
|
||||||
|
void MB_Diagnostics_SlaveBusyCnt(void);
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////---FUNCTIONS---/////////////////////////////
|
||||||
|
|
||||||
|
#endif //__MODBUS_DIAG_H_
|
||||||
|
|
||||||
|
/** MODBUS_DIAG
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
@@ -33,7 +33,7 @@ Modbus/
|
|||||||
1. **Склонируйте субмодуль** в ваш проект:
|
1. **Склонируйте субмодуль** в ваш проект:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git submodule add https://git.arktika.cyou/Razvalyaev/STM32_ExtendedLibs path/to/ExtendedLibs
|
git submodule add https://git.arktika.cyou/set506/STM32_Modbus path/to/Modbus
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
171
Src/modbus.c
171
Src/modbus.c
@@ -9,8 +9,9 @@
|
|||||||
@section Функции и макросы
|
@section Функции и макросы
|
||||||
|
|
||||||
### Инициализация:
|
### Инициализация:
|
||||||
- MODBUS_SetupHardware() — Инициализация модуля Modbus.
|
- MODBUS_FirstInit() — Инициализация модуля Modbus.
|
||||||
- MODBUS_Config() — Инициализация модуля Modbus.
|
- MODBUS_Config() — Инициализация модуля Modbus.
|
||||||
|
- MODBUS_SlaveStart() — Запуск Modbus как Slave.
|
||||||
|
|
||||||
### Функции для Modbus
|
### Функции для Modbus
|
||||||
- MB_Slave_Response()
|
- MB_Slave_Response()
|
||||||
@@ -22,45 +23,50 @@
|
|||||||
### Функции для работы с RS (UART):
|
### Функции для работы с RS (UART):
|
||||||
- RS_Parse_Message() / RS_Collect_Message() — Парсинг и сборка сообщения.
|
- RS_Parse_Message() / RS_Collect_Message() — Парсинг и сборка сообщения.
|
||||||
- RS_Response() — Отправка ответа.
|
- RS_Response() — Отправка ответа.
|
||||||
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "modbus.h"
|
#include "modbus.h"
|
||||||
|
|
||||||
/* MODBUS HANDLES */
|
/* MODBUS HANDLES */
|
||||||
RS_HandleTypeDef hmodbus1;
|
RS_HandleTypeDef hmodbus1; ///< Default Handle for Modbus
|
||||||
RS_MsgTypeDef MODBUS_MSG;
|
RS_MsgTypeDef MODBUS_MSG; ///< Default Message Struct for Modbus
|
||||||
|
|
||||||
/* DEFINE REGISTERS/COILS */
|
/* DEFINE DATA FOR MODBUS */
|
||||||
MB_DeviceIdentificationTypeDef MB_DEVID;
|
MB_DataStructureTypeDef MB_DATA = {0};; ///< Coils & Registers
|
||||||
MB_DataStructureTypeDef MB_DATA = {0};;
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
//-----------------------------FOR USER------------------------------
|
//-----------------------------FOR USER------------------------------
|
||||||
/**
|
/**
|
||||||
* @brief Инициализация периферии модбас.
|
* @brief Инициализация периферии модбас.
|
||||||
* @param hmodbus Указатель на хендлер RS
|
* @param hmodbus Указатель на хендлер RS
|
||||||
|
* @param huart Указатель на хендлер UART
|
||||||
|
* @param htim Указатель на хендлер TIM
|
||||||
* @details Подключает хендлы периферии к hmodbus
|
* @details Подключает хендлы периферии к hmodbus
|
||||||
* Конфигурация выставляется по умолчанию из modbus_config.h
|
* Конфигурация выставляется по умолчанию из modbus_config.h
|
||||||
*/
|
*/
|
||||||
void MODBUS_SetupHardware(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim)
|
HAL_StatusTypeDef MODBUS_FirstInit(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart, TIM_HandleTypeDef *htim)
|
||||||
{
|
{
|
||||||
if((hmodbus == NULL) || (huart == NULL))
|
if((hmodbus == NULL) || (huart == NULL))
|
||||||
{
|
{
|
||||||
return;
|
return HAL_ERROR;
|
||||||
}
|
}
|
||||||
MB_DeviceInentificationInit();
|
MB_DeviceInentificationInit();
|
||||||
|
MB_DiagnosticsInit();
|
||||||
//-----------SETUP MODBUS-------------
|
//-----------SETUP MODBUS-------------
|
||||||
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
||||||
hmodbus1.ID = MODBUS_DEVICE_ID;
|
hmodbus->ID = MODBUS_DEVICE_ID;
|
||||||
hmodbus1.sRS_Timeout = MODBUS_TIMEOUT;
|
hmodbus->sRS_Timeout = MODBUS_TIMEOUT;
|
||||||
hmodbus1.sRS_Mode = RS_SLAVE_ALWAYS_WAIT;
|
hmodbus->sRS_Mode = RS_SLAVE_ALWAYS_WAIT;
|
||||||
hmodbus1.sRS_RX_Size_Mode = RS_RX_Size_NotConst;
|
hmodbus->sRS_RX_Size_Mode = RS_RX_Size_NotConst;
|
||||||
|
|
||||||
// INIT
|
// INIT
|
||||||
hmodbus1.RS_STATUS = RS_Init(hmodbus, huart, htim, 0);
|
hmodbus->RS_STATUS = RS_Init(hmodbus, huart, htim, 0);
|
||||||
|
|
||||||
RS_EnableReceive();
|
RS_EnableReceive();
|
||||||
|
|
||||||
|
if(hmodbus->RS_STATUS == RS_OK)
|
||||||
|
return HAL_OK;
|
||||||
|
else
|
||||||
|
return HAL_ERROR;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Программная конфигурация модбас.
|
* @brief Программная конфигурация модбас.
|
||||||
@@ -69,11 +75,15 @@ void MODBUS_SetupHardware(RS_HandleTypeDef *hmodbus, UART_HandleTypeDef *huart,
|
|||||||
* @param master Режим мастер (пока не сделан)
|
* @param master Режим мастер (пока не сделан)
|
||||||
* @details Конфигурирует ID, таймаут и режим hmodbus
|
* @details Конфигурирует ID, таймаут и режим hmodbus
|
||||||
*/
|
*/
|
||||||
void MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint8_t master)
|
HAL_StatusTypeDef MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint8_t master)
|
||||||
{
|
{
|
||||||
if(hmodbus == NULL)
|
if(hmodbus == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return HAL_ERROR;
|
||||||
|
}
|
||||||
|
if((ID < 1) || (ID > 247))
|
||||||
|
{
|
||||||
|
return HAL_ERROR;
|
||||||
}
|
}
|
||||||
//-----------SETUP MODBUS-------------
|
//-----------SETUP MODBUS-------------
|
||||||
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
// set up modbus: MB_RX_Size_NotConst and Timeout enable
|
||||||
@@ -84,30 +94,45 @@ void MODBUS_Config(RS_HandleTypeDef *hmodbus, uint8_t ID, uint16_t Timeout, uint
|
|||||||
else
|
else
|
||||||
hmodbus->sRS_Mode = RS_SLAVE_ALWAYS_WAIT;
|
hmodbus->sRS_Mode = RS_SLAVE_ALWAYS_WAIT;
|
||||||
hmodbus->sRS_RX_Size_Mode = RS_RX_Size_NotConst;
|
hmodbus->sRS_RX_Size_Mode = RS_RX_Size_NotConst;
|
||||||
|
|
||||||
|
return HAL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Запуск слейв модбас.
|
* @brief Запуск слейв модбас.
|
||||||
* @param hmodbus Указатель на хендлер RS.
|
* @param hmodbus Указатель на хендлер RS.
|
||||||
* @param modbus_msg Указатель на структуру сообщения.
|
* @param modbus_msg Указатель на структуру сообщения.
|
||||||
|
(NULL чтобы использовать дефолтную)
|
||||||
* @details Конфигурирует ID, таймаут и режим hmodbus
|
* @details Конфигурирует ID, таймаут и режим hmodbus
|
||||||
*/
|
*/
|
||||||
void MODBUS_SlaveStart(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
HAL_StatusTypeDef MODBUS_SlaveStart(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *modbus_msg)
|
||||||
{
|
{
|
||||||
if(hmodbus == NULL)
|
if(hmodbus == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return HAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(hmodbus->sRS_Mode >= RS_MASTER_START)
|
||||||
|
{
|
||||||
|
return HAL_ERROR;
|
||||||
|
}
|
||||||
if(modbus_msg)
|
if(modbus_msg)
|
||||||
RS_Receive_IT(hmodbus, modbus_msg);
|
hmodbus->RS_STATUS = RS_Receive_IT(hmodbus, modbus_msg);
|
||||||
else
|
else
|
||||||
RS_Receive_IT(hmodbus, &MODBUS_MSG);
|
hmodbus->RS_STATUS = RS_Receive_IT(hmodbus, &MODBUS_MSG);
|
||||||
|
|
||||||
|
if(hmodbus->RS_STATUS == RS_OK)
|
||||||
|
return HAL_OK;
|
||||||
|
else
|
||||||
|
return HAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
//-----------------------------INTERNAL------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Ответ на сообщение в режиме слейва.
|
* @brief Ответ на сообщение в режиме слейва.
|
||||||
* @param hmodbus Указатель на хендлер RS.
|
* @param hmodbus Указатель на хендлер RS.
|
||||||
@@ -121,11 +146,14 @@ static RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeD
|
|||||||
hmodbus->f.EchoResponse = 0;
|
hmodbus->f.EchoResponse = 0;
|
||||||
RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit
|
RS_Reset_TX_Flags(hmodbus); // reset flag for correct transmit
|
||||||
|
|
||||||
if(hmodbus->ID == 0)
|
MB_Diagnostics_BusMessageCnt();
|
||||||
|
if(hmodbus->ID == 0 || modbus_msg->MbAddr == 0)
|
||||||
{
|
{
|
||||||
|
MB_Diagnostics_SlaveNoResponseCnt(); // <-- Устройство не отвечает на широковещательные сообщения
|
||||||
hmodbus->RS_STATUS = RS_SKIP;
|
hmodbus->RS_STATUS = RS_SKIP;
|
||||||
return MB_RES;
|
return RS_Handle_Receive_Start(hmodbus, modbus_msg);
|
||||||
}
|
}
|
||||||
|
MB_Diagnostics_SlaveMessageCnt();
|
||||||
|
|
||||||
if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing
|
if(modbus_msg->Func_Code < ERR_VALUES_START)// if no errors after parsing
|
||||||
{
|
{
|
||||||
@@ -192,12 +220,30 @@ static RS_StatusTypeDef MB_Slave_Response(RS_HandleTypeDef *hmodbus, RS_MsgTypeD
|
|||||||
hmodbus->f.MessageHandled = MB_Proccess_Read_Device_Identification(hmodbus->pMessagePtr);
|
hmodbus->f.MessageHandled = MB_Proccess_Read_Device_Identification(hmodbus->pMessagePtr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Добавить в switch-case после других case:
|
||||||
|
case MB_R_DIAGNOSTIC:
|
||||||
|
hmodbus->f.MessageHandled = MB_Proccess_Diagnostics(hmodbus->pMessagePtr);
|
||||||
|
break;
|
||||||
|
|
||||||
/* unknown func code */
|
/* unknown func code */
|
||||||
default: modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */
|
default:
|
||||||
|
modbus_msg->Except_Code = 0x01; /* set exception code: illegal function */
|
||||||
|
MB_Diagnostics_SlaveNAKCnt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Проверяем режим устройства - если Listen Only, не обрабатываем команды
|
||||||
|
if (MB_GetDeviceMode() == MODBUS_LISTEN_ONLY_MODE)
|
||||||
|
{
|
||||||
|
MB_Diagnostics_SlaveNoResponseCnt();
|
||||||
|
hmodbus->RS_STATUS = RS_SKIP;
|
||||||
|
return RS_Handle_Receive_Start(hmodbus, modbus_msg);;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем статус обработки запроса
|
||||||
if(hmodbus->f.MessageHandled == 0)
|
if(hmodbus->f.MessageHandled == 0)
|
||||||
{
|
{
|
||||||
|
MB_Diagnostics_ExceptionErrorCnt();
|
||||||
TrackerCnt_Warn(hmodbus->rs_err);
|
TrackerCnt_Warn(hmodbus->rs_err);
|
||||||
modbus_msg->Func_Code |= ERR_VALUES_START;
|
modbus_msg->Func_Code |= ERR_VALUES_START;
|
||||||
}
|
}
|
||||||
@@ -282,6 +328,14 @@ static RS_StatusTypeDef MB_Slave_Collect_Message(RS_HandleTypeDef *hmodbus, RS_M
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC)
|
||||||
|
{
|
||||||
|
// Diagnostics special format: [SubFunc_HI][SubFunc_LO][Data_HI][Data_LO]
|
||||||
|
modbus_uart_buff[ind++] = modbus_msg->DATA[0] >> 8; // Sub-function HI
|
||||||
|
modbus_uart_buff[ind++] = modbus_msg->DATA[0] & 0xFF; // Sub-function LO
|
||||||
|
modbus_uart_buff[ind++] = modbus_msg->DATA[1] >> 8; // Data HI
|
||||||
|
modbus_uart_buff[ind++] = modbus_msg->DATA[1] & 0xFF; // Data LO
|
||||||
|
}
|
||||||
else // modbus data header
|
else // modbus data header
|
||||||
{
|
{
|
||||||
// set size of received data
|
// set size of received data
|
||||||
@@ -344,24 +398,23 @@ static int MB_Define_Size_of_Function(RS_HandleTypeDef *hmodbus, RS_MsgTypeDef *
|
|||||||
RS_StatusTypeDef MB_RES = 0;
|
RS_StatusTypeDef MB_RES = 0;
|
||||||
int mb_func_size = 0;
|
int mb_func_size = 0;
|
||||||
|
|
||||||
if ((modbus_msg->Func_Code & ~ERR_VALUES_START) < 0x0F)
|
if (modbus_msg->Func_Code == MB_R_DIAGNOSTIC)
|
||||||
{
|
{
|
||||||
modbus_msg->ByteCnt = 0;
|
|
||||||
mb_func_size = 1;
|
mb_func_size = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else if(modbus_msg->Func_Code == MB_R_DEVICE_INFO)
|
||||||
{
|
|
||||||
modbus_msg->ByteCnt = hmodbus->pBufferPtr[RX_FIRST_PART_SIZE-1]; // get numb of data in command
|
|
||||||
// +1 because that defines is size, not ind.
|
|
||||||
mb_func_size = modbus_msg->ByteCnt + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(modbus_msg->Func_Code == MB_R_DEVICE_INFO)
|
|
||||||
{
|
{
|
||||||
mb_func_size = 0;
|
mb_func_size = 0;
|
||||||
}
|
}
|
||||||
|
else if ((modbus_msg->Func_Code & ~ERR_VALUES_START) < 0x0F)
|
||||||
|
{
|
||||||
|
mb_func_size = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mb_func_size = modbus_msg->ByteCnt + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mb_func_size = RX_FIRST_PART_SIZE + mb_func_size; // size of whole message
|
mb_func_size = RX_FIRST_PART_SIZE + mb_func_size; // size of whole message
|
||||||
return mb_func_size;
|
return mb_func_size;
|
||||||
@@ -381,20 +434,25 @@ static RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_Msg
|
|||||||
uint32_t check_empty_buff;
|
uint32_t check_empty_buff;
|
||||||
int ind = 0; // ind for modbus-uart buffer
|
int ind = 0; // ind for modbus-uart buffer
|
||||||
hmodbus->f.RX_Continue = 0;
|
hmodbus->f.RX_Continue = 0;
|
||||||
|
int expected_size = 0;
|
||||||
//-----INFO ABOUT DATA/MESSAGE-------
|
//-----INFO ABOUT DATA/MESSAGE-------
|
||||||
//-----------[first bits]------------
|
//-----------[first bits]------------
|
||||||
// get ID of message/user
|
// get ID of message/user
|
||||||
if(modbus_uart_buff[ind] != hmodbus->ID)
|
if(modbus_uart_buff[ind] != hmodbus->ID)
|
||||||
{
|
{
|
||||||
modbus_msg->MbAddr = 0;
|
modbus_msg->MbAddr = 0;
|
||||||
return RS_SKIP;
|
ind++;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
modbus_msg->MbAddr = modbus_uart_buff[ind++];
|
modbus_msg->MbAddr = modbus_uart_buff[ind++];
|
||||||
|
}
|
||||||
|
|
||||||
// get func code
|
// get func code
|
||||||
modbus_msg->Func_Code = modbus_uart_buff[ind++];
|
modbus_msg->Func_Code = modbus_uart_buff[ind++];
|
||||||
if(modbus_msg->Func_Code & ERR_VALUES_START) // явная херня
|
if(modbus_msg->Func_Code & ERR_VALUES_START) // явная херня
|
||||||
{
|
{
|
||||||
|
MB_Diagnostics_SlaveNAKCnt();
|
||||||
modbus_msg->MbAddr = 0;
|
modbus_msg->MbAddr = 0;
|
||||||
return RS_SKIP;
|
return RS_SKIP;
|
||||||
}
|
}
|
||||||
@@ -406,6 +464,18 @@ static RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_Msg
|
|||||||
modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++];
|
modbus_msg->DevId.NextObjId = modbus_uart_buff[ind++];
|
||||||
modbus_msg->ByteCnt = 0;
|
modbus_msg->ByteCnt = 0;
|
||||||
}
|
}
|
||||||
|
else if(modbus_msg->Func_Code == MB_R_DIAGNOSTIC)
|
||||||
|
{
|
||||||
|
// Diagnostics: читаем 4 байта в DATA[0] и DATA[1]
|
||||||
|
// Sub-function
|
||||||
|
modbus_msg->DATA[0] = modbus_uart_buff[ind++] << 8;
|
||||||
|
modbus_msg->DATA[0] |= modbus_uart_buff[ind++];
|
||||||
|
// Data
|
||||||
|
modbus_msg->DATA[1] = modbus_uart_buff[ind++] << 8;
|
||||||
|
modbus_msg->DATA[1] |= modbus_uart_buff[ind++];
|
||||||
|
modbus_msg->Addr = 0; // не использует Addr
|
||||||
|
modbus_msg->Qnt = 0; // не использует Qnt
|
||||||
|
}
|
||||||
else // if its classic modbus request
|
else // if its classic modbus request
|
||||||
{
|
{
|
||||||
// get address from CMD
|
// get address from CMD
|
||||||
@@ -422,6 +492,20 @@ static RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_Msg
|
|||||||
else
|
else
|
||||||
hmodbus->pMessagePtr->ByteCnt = 0;
|
hmodbus->pMessagePtr->ByteCnt = 0;
|
||||||
|
|
||||||
|
expected_size = MB_Define_Size_of_Function(hmodbus, modbus_msg);
|
||||||
|
// если размер меньше ожидаемого - продолжаем принимать
|
||||||
|
if(hmodbus->RS_Message_Size < expected_size)
|
||||||
|
{
|
||||||
|
hmodbus->f.RX_Continue = 1;
|
||||||
|
return RS_SKIP;
|
||||||
|
}
|
||||||
|
// если больше Ошибка
|
||||||
|
else if (hmodbus->RS_Message_Size > expected_size)
|
||||||
|
{
|
||||||
|
MB_Diagnostics_CommunicationErrorCnt();
|
||||||
|
return RS_PARSE_MSG_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------DATA----------------
|
//---------------DATA----------------
|
||||||
// (optional)
|
// (optional)
|
||||||
if (modbus_msg->ByteCnt != 0)
|
if (modbus_msg->ByteCnt != 0)
|
||||||
@@ -431,6 +515,7 @@ static RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_Msg
|
|||||||
{
|
{
|
||||||
TrackerCnt_Err(hmodbus->rs_err);
|
TrackerCnt_Err(hmodbus->rs_err);
|
||||||
modbus_msg->Func_Code |= ERR_VALUES_START;
|
modbus_msg->Func_Code |= ERR_VALUES_START;
|
||||||
|
MB_Diagnostics_CommunicationErrorCnt();
|
||||||
return RS_PARSE_MSG_ERR;
|
return RS_PARSE_MSG_ERR;
|
||||||
}
|
}
|
||||||
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA;
|
uint16_t *tmp_data_addr = (uint16_t *)modbus_msg->DATA;
|
||||||
@@ -456,6 +541,7 @@ static RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_Msg
|
|||||||
// compare crc
|
// compare crc
|
||||||
if (modbus_msg->MB_CRC != CRC_VALUE)
|
if (modbus_msg->MB_CRC != CRC_VALUE)
|
||||||
{
|
{
|
||||||
|
MB_Diagnostics_CommunicationErrorCnt();
|
||||||
TrackerCnt_Err(hmodbus->rs_err);
|
TrackerCnt_Err(hmodbus->rs_err);
|
||||||
modbus_msg->Func_Code |= ERR_VALUES_START;
|
modbus_msg->Func_Code |= ERR_VALUES_START;
|
||||||
}
|
}
|
||||||
@@ -468,17 +554,6 @@ static RS_StatusTypeDef MB_Slave_Parse_Message(RS_HandleTypeDef *hmodbus, RS_Msg
|
|||||||
// if(check_empty_buff == 0)
|
// if(check_empty_buff == 0)
|
||||||
// hmodbus->MB_RESPONSE = MB_EMPTY_MSG; //
|
// hmodbus->MB_RESPONSE = MB_EMPTY_MSG; //
|
||||||
|
|
||||||
// если размер меньше ожидаемого - продолжаем принимать
|
|
||||||
if(hmodbus->RS_Message_Size < MB_Define_Size_of_Function(hmodbus, modbus_msg))
|
|
||||||
{
|
|
||||||
hmodbus->f.RX_Continue = 1;
|
|
||||||
return RS_SKIP;
|
|
||||||
}
|
|
||||||
// если больше Ошибка
|
|
||||||
else if (hmodbus->RS_Message_Size > MB_Define_Size_of_Function(hmodbus, modbus_msg))
|
|
||||||
{
|
|
||||||
return RS_PARSE_MSG_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RS_OK;
|
return RS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* @file modbus_devid.c
|
* @file modbus_devid.c
|
||||||
* @brief Реализация идентификации устройства Modbus
|
* @brief Реализация идентификаторов устройства Modbus
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* @details
|
* @details
|
||||||
Модуль обработки запросов идентификации устройства через MEI-тип 0x0E:
|
Модуль обработки запросов идентификации устройства через MEI-тип 0x0E:
|
||||||
@@ -14,9 +14,10 @@
|
|||||||
сообщений с установкой флага MoreFollows и указанием NextObjId для
|
сообщений с установкой флага MoreFollows и указанием NextObjId для
|
||||||
продолжения чтения в следующем запросе.
|
продолжения чтения в следующем запросе.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "modbus_devid.h"
|
#include "modbus_devid.h"
|
||||||
|
|
||||||
|
MB_DeviceIdentificationTypeDef MB_DEVID; ///< Device Identificatino=
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Write Object of Device Identification to MessageData
|
* @brief Write Object of Device Identification to MessageData
|
||||||
@@ -115,6 +116,11 @@ uint8_t MB_Proccess_Read_Device_Identification(RS_MsgTypeDef *modbus_msg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MB_EXTENDED_IDENTIFICATION:
|
case MB_EXTENDED_IDENTIFICATION:
|
||||||
|
if(MODBUS_NUMB_OF_USEROBJECTS <= 0 || MODBUS_NUMB_OF_USEROBJECTS > 128)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (modbus_msg->DevId.NextObjId == 0)
|
if (modbus_msg->DevId.NextObjId == 0)
|
||||||
{
|
{
|
||||||
modbus_msg->DevId.NextObjId = 0x80;
|
modbus_msg->DevId.NextObjId = 0x80;
|
||||||
|
|||||||
293
Src/modbus_diag.c
Normal file
293
Src/modbus_diag.c
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file modbus_diag.c
|
||||||
|
* @brief Реализация диагностики устройства Modbus
|
||||||
|
******************************************************************************
|
||||||
|
* @details
|
||||||
|
Модуль обработки запросов диагностической информации (0x08):
|
||||||
|
- Полная поддержка всех подфункций диагностики согласно спецификации Modbus
|
||||||
|
- Выставление любого бита в Diagnostics Register
|
||||||
|
- Сбор статистики работы устройства
|
||||||
|
- Управление режимами работы (Normal/Listen Only)
|
||||||
|
******************************************************************************/
|
||||||
|
#include "modbus_diag.h"
|
||||||
|
|
||||||
|
// Глобальная структура диагностики
|
||||||
|
MB_DiagnosticsInfoTypeDef MB_DIAG = {0};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Инициализация диагностических счетчиков
|
||||||
|
*/
|
||||||
|
void MB_DiagnosticsInit(void)
|
||||||
|
{
|
||||||
|
MB_DIAG.DiagnosticRegister = 0;
|
||||||
|
MB_DIAG.DeviceMode = MODBUS_NORMAL_MODE;
|
||||||
|
MB_DIAG.AsciiDelimiter = '\n'; // LF по умолчанию
|
||||||
|
|
||||||
|
// Инициализация счетчиков
|
||||||
|
MB_DIAG.Counters.BusMessage = 0;
|
||||||
|
MB_DIAG.Counters.BusCommunicationErr = 0;
|
||||||
|
MB_DIAG.Counters.BusExceptionErr = 0;
|
||||||
|
MB_DIAG.Counters.SlaveMessage = 0;
|
||||||
|
MB_DIAG.Counters.SlaveNoResponse = 0;
|
||||||
|
MB_DIAG.Counters.SlaveNAK = 0;
|
||||||
|
MB_DIAG.Counters.SlaveBusy = 0;
|
||||||
|
MB_DIAG.Counters.BusCharacterOverrun = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Выставить бит в регистре диагностике
|
||||||
|
* @param bit_num Номер бита для выставления (1-15, 0 бит нельзя выставить)
|
||||||
|
* @param bit_state Состояние бита для выставления (Выставить/Сбросить)
|
||||||
|
* @return >0 - номер выставленного бита, 0 - ошибка
|
||||||
|
*/
|
||||||
|
int MB_Diagnostics_WriteBit(int bit_num, int bit_state)
|
||||||
|
{
|
||||||
|
if(bit_num == 0 || bit_num > 15)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(bit_state)
|
||||||
|
MB_DIAG.DiagnosticRegister |= (1 << bit_num);
|
||||||
|
else
|
||||||
|
MB_DIAG.DiagnosticRegister &= ~(1 << bit_num);
|
||||||
|
|
||||||
|
return bit_num;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Прочитать состояние бита диагностического регистра
|
||||||
|
* @param bit_num Номер бита (0-15)
|
||||||
|
* @return 1 - бит установлен, 0 - бит сброшен или ошибка
|
||||||
|
*/
|
||||||
|
int MB_Diagnostics_GetBit(int bit_num)
|
||||||
|
{
|
||||||
|
if(bit_num < 0 || bit_num > 15)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (MB_DIAG.DiagnosticRegister >> bit_num) & 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Обработка команды диагностики (0x08)
|
||||||
|
* @param modbus_msg Указатель на структуру сообщения modbus
|
||||||
|
* @return fMessageHandled Статус обработки команды
|
||||||
|
*/
|
||||||
|
uint8_t MB_Proccess_Diagnostics(RS_MsgTypeDef *modbus_msg)
|
||||||
|
{
|
||||||
|
uint16_t sub_function = modbus_msg->DATA[0];
|
||||||
|
uint16_t request_data = modbus_msg->DATA[1];
|
||||||
|
|
||||||
|
// Если устройство в режиме Listen Only, отвечаем только на sub-function 0x01
|
||||||
|
if (MB_DIAG.DeviceMode == MODBUS_LISTEN_ONLY_MODE && sub_function != 0x0001)
|
||||||
|
{
|
||||||
|
return 0; // Не отвечаем в режиме Listen Only
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(sub_function)
|
||||||
|
{
|
||||||
|
case 0x0000: // Return Query Data
|
||||||
|
// Эхо-ответ с теми же данными
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = request_data;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0001: // Restart Communications
|
||||||
|
// Перезапуск коммуникаций - выходим из Listen Only режима
|
||||||
|
MB_DIAG.DeviceMode = MODBUS_NORMAL_MODE;
|
||||||
|
|
||||||
|
// Если request_data = 0xFF00, очищаем лог событий
|
||||||
|
if (request_data == 0xFF00)
|
||||||
|
{
|
||||||
|
MB_DiagnosticsInit(); // Полный сброс
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Очищаем только счетчики, но не регистр диагностики
|
||||||
|
MB_DIAG.Counters.BusMessage = 0;
|
||||||
|
MB_DIAG.Counters.BusCommunicationErr = 0;
|
||||||
|
MB_DIAG.Counters.BusExceptionErr = 0;
|
||||||
|
MB_DIAG.Counters.SlaveMessage = 0;
|
||||||
|
MB_DIAG.Counters.SlaveNoResponse = 0;
|
||||||
|
MB_DIAG.Counters.SlaveNAK = 0;
|
||||||
|
MB_DIAG.Counters.SlaveBusy = 0;
|
||||||
|
MB_DIAG.Counters.BusCharacterOverrun = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = request_data;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0002: // Return Diagnostic Register
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.DiagnosticRegister;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0003: // Change ASCII Input Delimiter
|
||||||
|
// В RTU режиме не поддерживается
|
||||||
|
modbus_msg->Func_Code |= ERR_VALUES_START;
|
||||||
|
modbus_msg->Except_Code = ILLEGAL_FUNCTION;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 0x0004: // Force Listen Only Mode
|
||||||
|
MB_DIAG.DeviceMode = MODBUS_LISTEN_ONLY_MODE;
|
||||||
|
// В режиме Listen Only не отправляем ответ
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 0x000A: // Clear Counters and Diagnostic Register
|
||||||
|
MB_DiagnosticsInit(); // Полный сброс
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = 0;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x000B: // Return Bus Message Count
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.Counters.BusMessage;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x000C: // Return Bus Communication Error Count
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.Counters.BusCommunicationErr;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x000D: // Return Bus Exception Error Count
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.Counters.BusExceptionErr;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x000E: // Return Server Message Count
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveMessage;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x000F: // Return Slave No Response Count
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveNoResponse;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0010: // Return Slave NAK Count
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveNAK;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0011: // Return Slave Busy Count
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.Counters.SlaveBusy;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0012: // Return Bus Character Overrun Count
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = MB_DIAG.Counters.BusCharacterOverrun;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0014: // Clear Overrun Counter and Flag
|
||||||
|
MB_DIAG.Counters.BusCharacterOverrun = 0;
|
||||||
|
// Сбрасываем флаг переполнения в DiagnosticRegister
|
||||||
|
MB_DIAG.DiagnosticRegister &= ~(1<<0);
|
||||||
|
modbus_msg->DATA[0] = sub_function;
|
||||||
|
modbus_msg->DATA[1] = 0;
|
||||||
|
modbus_msg->ByteCnt = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
modbus_msg->Func_Code |= ERR_VALUES_START;
|
||||||
|
modbus_msg->Except_Code = ILLEGAL_FUNCTION;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличивает счетчик сообщений на шине
|
||||||
|
*/
|
||||||
|
void MB_Diagnostics_BusMessageCnt(void)
|
||||||
|
{
|
||||||
|
MB_DIAG.Counters.BusMessage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличивает счетчик ошибок связи
|
||||||
|
*/
|
||||||
|
void MB_Diagnostics_CommunicationErrorCnt(void)
|
||||||
|
{
|
||||||
|
if (MB_DIAG.Counters.BusCommunicationErr < 0xFFFF)
|
||||||
|
MB_DIAG.Counters.BusCommunicationErr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличивает счетчик исключений
|
||||||
|
*/
|
||||||
|
void MB_Diagnostics_ExceptionErrorCnt(void)
|
||||||
|
{
|
||||||
|
if (MB_DIAG.Counters.BusExceptionErr < 0xFFFF)
|
||||||
|
MB_DIAG.Counters.BusExceptionErr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличивает счетчик переполнения символов
|
||||||
|
*/
|
||||||
|
void MB_Diagnostics_CharacterOverrunCnt(void)
|
||||||
|
{
|
||||||
|
if (MB_DIAG.Counters.BusCharacterOverrun < 0xFFFF)
|
||||||
|
{
|
||||||
|
MB_DIAG.Counters.BusCharacterOverrun++;
|
||||||
|
// Устанавливаем флаг переполнения в DiagnosticRegister
|
||||||
|
MB_DIAG.DiagnosticRegister |= (1 << 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличивает счетчик отсутствия ответов
|
||||||
|
*/
|
||||||
|
void MB_Diagnostics_SlaveMessageCnt(void)
|
||||||
|
{
|
||||||
|
if (MB_DIAG.Counters.SlaveMessage < 0xFFFF)
|
||||||
|
MB_DIAG.Counters.SlaveMessage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличивает счетчик отсутствия ответов
|
||||||
|
*/
|
||||||
|
void MB_Diagnostics_SlaveNoResponseCnt(void)
|
||||||
|
{
|
||||||
|
if (MB_DIAG.Counters.SlaveNoResponse < 0xFFFF)
|
||||||
|
MB_DIAG.Counters.SlaveNoResponse++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличивает счетчик NAK ответов
|
||||||
|
*/
|
||||||
|
void MB_Diagnostics_SlaveNAKCnt(void)
|
||||||
|
{
|
||||||
|
if (MB_DIAG.Counters.SlaveNAK < 0xFFFF)
|
||||||
|
MB_DIAG.Counters.SlaveNAK++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Увеличивает счетчик занятости устройства
|
||||||
|
*/
|
||||||
|
void MB_Diagnostics_SlaveBusyCnt(void)
|
||||||
|
{
|
||||||
|
if (MB_DIAG.Counters.SlaveBusy < 0xFFFF)
|
||||||
|
MB_DIAG.Counters.SlaveBusy++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Получение текущего режима устройства
|
||||||
|
* @return Текущий режим работы устройства
|
||||||
|
*/
|
||||||
|
MB_DeviceModeTypeDef MB_GetDeviceMode(void)
|
||||||
|
{
|
||||||
|
return MB_DIAG.DeviceMode;
|
||||||
|
}
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
#include "modbus_inputregs.h"
|
#include "modbus_inputregs.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Proccess command Read Holding Registers (03 - 0x03).
|
* @brief Proccess command Read Holding Registers (03 - 0x03).
|
||||||
* @param modbus_msg Указатель на структуру собщения modbus.
|
* @param modbus_msg Указатель на структуру собщения modbus.
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
Копирование данных из структур устройства в буфер ответа
|
Копирование данных из структур устройства в буфер ответа
|
||||||
- Поддержка знаковых и беззнаковых значений
|
- Поддержка знаковых и беззнаковых значений
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "modbus_inputregs.h"
|
#include "modbus_inputregs.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
- RS_TIM_Handler() в TIMx_IRQHandler вместо HAL_TIM_IRQHandler()
|
- RS_TIM_Handler() в TIMx_IRQHandler вместо HAL_TIM_IRQHandler()
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#include "rs_message.h"
|
#include "rs_message.h"
|
||||||
|
#include "modbus_diag.h"
|
||||||
|
|
||||||
uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
|
uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
|
||||||
|
|
||||||
@@ -357,19 +358,8 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
|
|||||||
// Парсим наше сообщение
|
// Парсим наше сообщение
|
||||||
RS_StatusTypeDef parse_res = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr);
|
RS_StatusTypeDef parse_res = RS_Parse_Message(hRS, hRS->pMessagePtr, hRS->pBufferPtr);
|
||||||
|
|
||||||
// Проверяем адрес Modbus перед обработкой
|
|
||||||
if(hRS->pMessagePtr->MbAddr != hRS->ID)
|
|
||||||
{
|
|
||||||
// Чужое сообщение - игнорируем и начинаем новый прием
|
|
||||||
RS_Abort(hRS, ABORT_RX);
|
|
||||||
RS_Handle_Receive_Start(hRS, hRS->pMessagePtr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Если сообещине принято корректно - отвечаем на него
|
// Если сообещине принято корректно - отвечаем на него
|
||||||
if(parse_res != RS_SKIP)
|
if(parse_res == RS_OK)
|
||||||
{
|
{
|
||||||
if(hRS->htim)
|
if(hRS->htim)
|
||||||
{
|
{
|
||||||
@@ -425,6 +415,10 @@ void RS_UART_Handler(RS_HandleTypeDef *hRS)
|
|||||||
//----------------ERRORS HANDLER----------------
|
//----------------ERRORS HANDLER----------------
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (hRS->huart->ErrorCode & HAL_UART_ERROR_ORE)
|
||||||
|
{
|
||||||
|
MB_Diagnostics_CharacterOverrunCnt(); // <-- Обнаружено переполнение
|
||||||
|
}
|
||||||
//TrackerCnt_Err(hRS->rs_err);
|
//TrackerCnt_Err(hRS->rs_err);
|
||||||
/* de-init uart transfer */
|
/* de-init uart transfer */
|
||||||
RS_Abort(hRS, ABORT_RS);
|
RS_Abort(hRS, ABORT_RS);
|
||||||
|
|||||||
Reference in New Issue
Block a user