ds18b20-MODBUS/john103C6T6/Modbus/modbus_data.c
2025-11-07 16:22:00 +03:00

142 lines
6.3 KiB
C

/**
******************************************************************************
* @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"
/**
* @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)
{
/* check quantity error */
if (Qnt > DATA_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 регистр
}
// 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_CONTROL_ADDR, C_CONTROL_QNT) == ET_NO_ERRORS)
{
*pCoils = MB_Set_Coil_Reg_Ptr(&MB_DATA.Coils, Addr - C_CONTROL_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
}