142 lines
6.3 KiB
C
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
|
|
}
|