Files
UKSI_TEST/Core/Config/modbus_data.c
2025-12-16 17:57:59 +03:00

152 lines
6.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
******************************************************************************
* @file modbus_data.c
* @brief Функции доступа к данным Modbus
******************************************************************************
* @details
Модуль реализует функции валидации адресов и доступа к данным:
- Проверка корректности запрашиваемых адресов
- Определение указателей на реальные данные в памяти
- Поддержка пользовательских массивов регистров и coils
@section Валидация адресов:
- MB_Check_Address_For_Arr() - проверка принадлежности адреса массиву
- MB_DefineRegistersAddress() - получение указателя на регистры
- MB_DefineCoilsAddress() - получение указателя на coils
******************************************************************************/
#include "modbus_core.h"
#include "modbus_coils.h"
#include "modbus_holdregs.h"
#include "modbus_inputregs.h"
#include "modbus_devid.h"
/* DEFINE DATA FOR MODBUS */
MB_DataStructureTypeDef MB_DATA = {0}; ///< Coils & Registers
MB_DataInternalTypeDef MB_INTERNAL;
/**
* @brief Check is address valid for certain array.
* @param Addr Начальный адресс.
* @param Qnt Количество запрашиваемых элементов.
* @param R_ARR_ADDR Начальный адресс массива R_ARR.
* @param R_ARR_NUMB Количество элементов в массиве R_ARR.
* @return ExceptionCode - ET_ILLEGAL_DATA_ADRESS если адресс недействителен, и ET_NO_ERRORS если все ок.
*
* @details Позволяет определить, принадлежит ли адресс Addr массиву R_ARR:
* Если адресс Addr находится в диапазоне адрессов массива R_ARR, то возвращаем NO_ERROR.
* Если адресс Addr находится за пределами адрессов массива R_ARR - ET_ILLEGAL_DATA_ADDRESSю.
*/
MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB)
{
// if address from this array
if(Addr >= R_ARR_ADDR)
{
// if quantity too big return error
if ((Addr - R_ARR_ADDR) + Qnt > R_ARR_NUMB)
{
return ET_ILLEGAL_DATA_ADDRESS; // return exception code
}
// if all ok - return no errors
return ET_NO_ERRORS;
}
// if address isnt from this array return error
else
return ET_ILLEGAL_DATA_ADDRESS; // return exception code
}
/**
* @brief Define Address Origin for Input/Holding Registers
* @param pRegs Указатель на указатель регистров.
* @param Addr Адрес начального регистра.
* @param Qnt Количество запрашиваемых регистров.
* @param WriteFlag Флаг регистр нужны для чтения или записи.
* @return ExceptionCode Код исключения если есть, и ET_NO_ERRORS если нет.
*
* @details Определение адреса начального регистра.
* @note WriteFlag пока не используется.
*/
MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, uint16_t Qnt, uint8_t RegisterType, uint8_t WriteFlag)
{
/* check quantity error */
if (Qnt > MbData_size)
{
return ET_ILLEGAL_DATA_VALUE; // return exception code
}
if(RegisterType == RegisterType_Holding)
{
// Default holding registers
if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_ADDR, R_HOLDING_QNT) == ET_NO_ERRORS)
{
*pRegs = MB_Set_Register_Ptr(&MB_DATA.HoldRegs, Addr - R_HOLDING_ADDR); // указатель на выбранный по Addr регистр
}
else if(MB_Check_Address_For_Arr(Addr, Qnt, R_HOLDING_PRVT_PARAMS_ADR, R_HOLDING_PRVT_PARAMS_QNT) == ET_NO_ERRORS)
{
*pRegs = MB_Set_Register_Ptr(&MB_INTERNAL, Addr - R_HOLDING_PRVT_PARAMS_ADR); // указатель на выбранный по Addr регистр
}
// if address doesnt match any array - return illegal data address response
else
{
return ET_ILLEGAL_DATA_ADDRESS;
}
}
else if(RegisterType == RegisterType_Input)
{
// Default input registers
if(MB_Check_Address_For_Arr(Addr, Qnt, R_INPUT_ADDR, R_INPUT_QNT) == ET_NO_ERRORS)
{
*pRegs = MB_Set_Register_Ptr(&MB_DATA.InRegs, Addr - R_INPUT_ADDR); // указатель на выбранный по Addr регистр
}
// if address doesnt match any array - return illegal data address response
else
{
return ET_ILLEGAL_DATA_ADDRESS;
}
}
else
{
return ET_ILLEGAL_FUNCTION;
}
// if found requeried array return no err
return ET_NO_ERRORS; // return no errors
}
/**
* @brief Define Address Origin for coils
* @param pCoils Указатель на указатель коилов.
* @param Addr Адресс начального коила.
* @param Qnt Количество запрашиваемых коилов.
* @param start_shift Указатель на переменную содержащую сдвиг внутри регистра для начального коила.
* @param WriteFlag Флаг коилы нужны для чтения или записи.
* @return ExceptionCode Код исключения если есть, и ET_NO_ERRORS если нет.
*
* @details Определение адреса начального регистра запрашиваемых коилов.
* @note WriteFlag используется для определния регистров GPIO: ODR или IDR.
*/
MB_ExceptionTypeDef MB_DefineCoilsAddress(uint16_t **pCoils, uint16_t Addr, uint16_t Qnt, uint16_t *start_shift, uint8_t WriteFlag)
{
/* В режиме работа ничего не записываем */
/* check quantity error */
if (Qnt > 2000)
{
return ET_ILLEGAL_DATA_VALUE; // return exception code
}
// Default coils
if(MB_Check_Address_For_Arr(Addr, Qnt, C_COILS_ADDR, C_COILS_QNT) == ET_NO_ERRORS)
{
*pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr - C_COILS_ADDR); // указатель на выбранный по Addr массив коилов
}
// if address doesnt match any array - return illegal data address response
else
{
return ET_ILLEGAL_DATA_ADDRESS;
}
*start_shift = Addr % 16; // set shift to requested coil
// if found requeried array return no err
return ET_NO_ERRORS; // return no errors
}