Files
UPP/UPP/Core/UPP/upp_params.c

578 lines
22 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 upp_params.c
* @brief Модуль проверяющий параметры УПП
******************************************************************************
* @details
* ИНСТРУКЦИЯ ПО ДОБАВЛЕНИЮ НОВЫХ ПАРАМЕТРОВ:
*
* 1. Добавить новый параметр в соответствующую структуру в файле параметров:
* - PARAM_PUI для параметров от ПУИ (пульт управления и индикации)
* - PARAM_INTERNAL для внутренних параметров УПП
*
* 2. В функции UPP_Params_ControlInternal() или UPP_Params_ControlPUI():
* a. Объявить временную переменную для хранения текущего значения
* b. Проверить изменение параметра (можно с помощью __CheckParamX() функции)
* c. Обновить параметр в соответствующем модуле новым параметром если он изменился
*
* 3. В функции UPP_Params_SetDefault() добавить установку значения по умолчанию
*
* 4. При необходимости добавить сатурацию параметра в UPP_Params_Saturate()
*
* Пример добавления простого параметра:
*
* // В UPP_Params_ControlInternal():
* float new_param = module.param;
* if(__CheckParamF(&new_param, PARAM_INTERNAL->new_param, 1000))
* {
* module_update = 1;
* }
*
* // В блоке обновления модуля:
* if(module_update)
* {
* if(Module_SetParam(&module, new_param) == HAL_OK)
* module_update = 0;
* }
*
* // В UPP_Params_SetDefault():
* PARAM_INTERNAL->new_param = NEW_PARAM_DEFAULT * 1000;
*
******************************************************************************
*/
#include "upp_main.h" // всё остальное по работе с УПП
#define SATURATE_U16(value, min, max) \
value = ((value) < (min) ? (min) : ((value) > (max) ? (max) : (value)))
static int __CheckParamF(float *paramDist, uint16_t paramSrc, float Coef);
static int __CheckParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef);
static int __CheckParamU16(uint16_t *paramDist, uint16_t paramSrc);
static int __CheckParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef);
static void __AngleSetLimit(void);
/**
* @brief Контроль параметров УПП.
* @return HAL Status.
*/
void UPP_Params_Control(void)
{
/* Проверяем параметры на корректный диапазон */
UPP_Params_Saturate();
/* Чекаем изменились ли параметры от ПУИ */
UPP_Params_ControlPUI();
/* Чекаем изменились ли внутренние параметры */
UPP_Params_ControlInternal();
}
/**
* @brief Контроль параметров от ПУИ.
* @return HAL Status.
*/
void UPP_Params_ControlPUI(void)
{
if(upp.call->go) // при запущеном УПП ничего не меняем
return;
/* Tnt - Уставка на скорость нарастания пускового тока */
float angle_ref_alphaPUI = PUI_Tnt_CalcAlpha(u2f(PARAM_PUI->Tnt, 1000), PM_SLOW_PERIOD_US);
float angle_ref_alpha = upp.hangle.refFilter.alpha;
if(angle_ref_alpha != angle_ref_alphaPUI)
{
angle_ref_alpha = angle_ref_alphaPUI;
if(Angle_PID_Init(&upp.hangle,
upp.hangle.pid.Kp,
upp.hangle.pid.Ki,
upp.hangle.pid.Kd,
angle_ref_alpha) != HAL_OK)
ERR_PRIVATE_CNT->angle_reinit_err++;
}
}
/**
* @brief Контроль внутренних параметров УПП.
* @return HAL Status.
*/
void UPP_Params_ControlInternal(void)
{
if(upp.call->go) // при запущеном УПП ничего не меняем
return;
// флаги обновились ли конфиги
static int alpha_update = 0;
static int adc_channel_update[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
static int zc_update = 0;
static int pwm_update = 0;
// временная переменная для параметров Мониторинга сети
float angle_max = upp.hangle.Config.AngleMax;
float angle_min = upp.hangle.Config.AngleMin;
float angle_pid_kp = upp.hangle.pid.Kp;
float angle_pid_ki = upp.hangle.pid.Ki/((float)PM_SLOW_PERIOD_US/1000000);
float angle_pid_kd = upp.hangle.pid.Kd;
// временная переменная для параметров каналов АЦП
float adc_channel_max[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
uint16_t adc_channel_zero[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
// временная переменная для параметров перехода через ноль
float zc_hysteresis = upp.pm.zc.Config.Hysteresis;
uint16_t zc_debounce = upp.pm.zc.Config.DebounceSamples;
// временная переменная для параметров ШИМ
uint8_t pwm_phase_mask = upp.hpwm.Config.PhaseMask.all;
uint16_t pwm_freq = upp.hpwm.Config.Frequency;
float pwm_duty = upp.hpwm.Config.Duty;
float pwm_pulse_len = upp.hpwm.Config.PulseLength;
// временная переменная для параметров Мониторинга сети
uint16_t pm_rms_widnow_size = upp.pm.rms[0].window_size;
float pm_rms_exp_alpha = upp.pm.rms_exp[0].alpha;
// Параметры регулятора Угла открытия
if(__CheckParamF(&angle_max, PARAM_INTERNAL->angle.Angle_Max, 65535))
{
alpha_update = 1;
}
if(__CheckParamF(&angle_min, PARAM_INTERNAL->angle.Angle_Min, 65535))
{
alpha_update = 1;
}
if(__CheckParamF(&angle_pid_kp, PARAM_INTERNAL->angle.PID_Kp, 10000))
{
alpha_update = 1;
}
if(__CheckParamF(&angle_pid_ki, PARAM_INTERNAL->angle.PID_Ki, 10000))
{
alpha_update = 1;
}
if(__CheckParamF(&angle_pid_kd, PARAM_INTERNAL->angle.PID_Kd, 10000))
{
alpha_update = 1;
}
// Параметры АЦП
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
{
adc_channel_max[i] = upp.pm.adc.Coefs[i].vMax;
adc_channel_zero[i] = upp.pm.adc.Coefs[i].lZero;
// Максимальное измеряемое напряжение
if(__CheckParamF(&adc_channel_max[i], PARAM_INTERNAL->adc.ADC_Max[i], 10))
{
adc_channel_update[i] = 1;
}
// Значение АЦП при нулевом входе
if(__CheckParamU16(&adc_channel_zero[i], PARAM_INTERNAL->adc.ADC_Zero[i]))
{
adc_channel_update[i] = 1;
}
}
// Параметры алгоритма перехода через ноль
if(__CheckParamF(&zc_hysteresis, PARAM_INTERNAL->zc.Hysteresis, 10000))
{
zc_update = 1;
}
if(__CheckParamU16(&zc_debounce, PARAM_INTERNAL->zc.DebouneCouner))
{
zc_update = 1;
}
// Параметры ШИМ
if(__CheckParamU8(&pwm_phase_mask, PARAM_INTERNAL->pwm.PhaseMask, 1))
{
pwm_update = 1;
}
if(__CheckParamU16(&pwm_freq, PARAM_INTERNAL->pwm.Frequency))
{
pwm_update = 1;
}
if(__CheckParamF(&pwm_duty, PARAM_INTERNAL->pwm.Duty, 100))
{
pwm_update = 1;
}
if(__CheckParamF(&pwm_pulse_len, PARAM_INTERNAL->pwm.PulseLength, 65535))
{
pwm_update = 1;
}
// Параметры мониторинга
if(__CheckParamU16(&pm_rms_widnow_size, PARAM_INTERNAL->pm.rms_window_size))
{
for(int i = 0; i < RMS_ALL; i++)
{
Filter_ReInit(&upp.pm.rms[i], pm_rms_widnow_size);
Filter_Start(&upp.pm.rms[i]);
}
}
if(__CheckParamF(&pm_rms_exp_alpha, PARAM_INTERNAL->pm.rms_exp_alpha, 65535))
{
for(int i = 0; i < RMS_EXP_ALL; i++)
{
Filter_ReInit(&upp.pm.rms_exp[i], pm_rms_exp_alpha);
Filter_Start(&upp.pm.rms_exp[i]);
}
}
// Обновление регулятора угла открытия
__AngleSetLimit();
if(alpha_update)
{
if(Angle_SetRange(&upp.hangle, angle_min, angle_max) == HAL_OK)
{
if(Angle_PID_Init(&upp.hangle, angle_pid_kp,
angle_pid_ki*((float)PM_SLOW_PERIOD_US/1000000),
angle_pid_kd,
upp.hangle.refFilter.alpha) == HAL_OK)
{
alpha_update = 0;
}
else
ERR_PRIVATE_CNT->angle_reinit_err++;
}
else
ERR_PRIVATE_CNT->angle_reinit_err++;
}
// Обновление АЦП конфигов
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
{
if(adc_channel_update[i])
{
if(ADC_ConfigChannel(&upp.pm.adc, i, adc_channel_zero[i], adc_channel_max[i], 4095) == HAL_OK)
adc_channel_update[i] = 0;
else
ERR_PRIVATE_CNT->adc_reinit_err++;
}
}
// Обновление Zero-Cross конфигов
if(zc_update)
{
if(ZC_Init(&upp.pm.zc, upp.pm.zc.Config.NumChannels, zc_hysteresis, zc_debounce) == HAL_OK)
zc_update = 0;
else
ERR_PRIVATE_CNT->zc_reinit_err++;
}
// Обновление ШИМ конфигов
if(pwm_update)
{
if(PWM_SetConfig(&upp.hpwm, pwm_phase_mask, pwm_freq, pwm_duty, pwm_pulse_len) == HAL_OK)
{
pwm_update = 0;
}
else
ERR_PRIVATE_CNT->pwm_reinit_err++;
}
}
/**
* @brief Инициализация параметров УПП.
* @return HAL Status.
*/
HAL_StatusTypeDef UPP_Params_Init(void)
{
/*====== ИНИЦИАЛИЗАЦИЯ МОДУЛЯ angle_control ======*/
// Инициализация ПИД
if(Angle_PID_Init(&upp.hangle,
u2f(PARAM_INTERNAL->angle.PID_Kp, 10000),
u2f(PARAM_INTERNAL->angle.PID_Ki, 10000)*((float)PM_SLOW_PERIOD_US/1000000),
u2f(PARAM_INTERNAL->angle.PID_Kd, 10000),
PUI_Tnt_CalcAlpha(u2f(PARAM_PUI->Tnt, 1000), PM_SLOW_PERIOD_US)) != HAL_OK)
return HAL_ERROR;
// Инициализация углов
if(Angle_SetRange(&upp.hangle,
u2f(PARAM_INTERNAL->angle.Angle_Min, 65535),
u2f(PARAM_INTERNAL->angle.Angle_Max, 65535)) != HAL_OK)
return HAL_ERROR;
/*===== ИНИЦИАЛИЗАЦИЯ МОДУЛЯ power_monitor ======*/
/* Инициализация каналов АЦП */
if(ADC_ConfigChannel(&upp.pm.adc, ADC_CHANNEL_UBA,
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_UBA],
u2f(PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_UBA], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&upp.pm.adc, ADC_CHANNEL_UAC,
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_UAC],
u2f(PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_UAC], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&upp.pm.adc, ADC_CHANNEL_IC,
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_IC],
u2f(PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_IC], 10),
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&upp.pm.adc, ADC_CHANNEL_IA,
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_IA],
u2f(PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_IA], 10),
4095) != HAL_OK)
return HAL_ERROR;
/* Инициализация алгоритма перехода через ноль */
if(ZC_Init(&upp.pm.zc, 3, u2f(PARAM_INTERNAL->zc.Hysteresis, 100), PARAM_INTERNAL->zc.DebouneCouner) != HAL_OK)
return HAL_ERROR;
/* Инициализация RMS фильтра медленного алга */
for(int i = 0; i < RMS_ALL; i++)
{
if(FilterRMS_Init(&upp.pm.rms[i], PARAM_INTERNAL->pm.rms_window_size))
return HAL_ERROR;
Filter_Start(&upp.pm.rms[i]);
}
/* Инициализация экпоненциального фильтра медленного алга */
for(int i = 0; i < RMS_EXP_ALL; i++)
{
if(FilterExp_Init(&upp.pm.rms_exp[i], u2f(PARAM_INTERNAL->pm.rms_exp_alpha, 65535)))
return HAL_ERROR;
Filter_Start(&upp.pm.rms_exp[i]);
}
/*====== ИНИЦИАЛИЗАЦИЯ МОДУЛЯ pwm_thyristors ======*/
if(PWM_SetConfig(&upp.hpwm, PARAM_INTERNAL->pwm.PhaseMask,
PARAM_INTERNAL->pwm.Frequency,
u2f(PARAM_INTERNAL->pwm.Duty, 100),
PARAM_INTERNAL->pwm.PulseLength) != HAL_OK)
return HAL_ERROR;
return HAL_OK;
}
/**
* @brief Контроль параметров УПП на корректные значения.
* @return HAL Status.
*/
void UPP_Params_Saturate(void)
{
SATURATE_U16(PARAM_PUI->Iref, 100, 500);
// SATURATE_U16(PARAM_PUI->Tnt, 50, 5000);
SATURATE_U16(PARAM_PUI->Umin, 5, 99);
SATURATE_U16(PARAM_PUI->Umax, 100, 120);
SATURATE_U16(PARAM_PUI->Imax, 5, 99);
SATURATE_U16(PARAM_PUI->Imin, 0, 40);
SATURATE_U16(PARAM_PUI->TiMax, 500, 10000);
SATURATE_U16(PARAM_PUI->Tdelay, 5, 60);
SATURATE_U16(PARAM_PUI->Interlace, 0, 1);
SATURATE_U16(PARAM_INTERNAL->setpoints.TemperatureWarn, 0, 90);
SATURATE_U16(PARAM_INTERNAL->setpoints.TemperatureErr, 0, 90);
SATURATE_U16(PARAM_INTERNAL->nominal.PhaseNumber, 0, 3);
SATURATE_U16(PARAM_INTERNAL->nominal.U, 0, ADC_U_MAX_V_DEFAULT*10);
SATURATE_U16(PARAM_INTERNAL->nominal.U_deviation_plus, 0, 100*100);
SATURATE_U16(PARAM_INTERNAL->nominal.U_deviation_minus, 0, 100*100);
SATURATE_U16(PARAM_INTERNAL->nominal.F, 40*100, 60*100);
SATURATE_U16(PARAM_INTERNAL->nominal.F_deviation_plus, 0, 100*100);
SATURATE_U16(PARAM_INTERNAL->nominal.F_deviation_minus, 0, 100*100);
SATURATE_U16(PARAM_INTERNAL->nominal.I, 0, ADC_I_MAX_A_DEFAULT*10);
SATURATE_U16(PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_UBA], 0, 5000*10);
SATURATE_U16(PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_UAC], 0, 5000*10);
SATURATE_U16(PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_IC], 0, 1000*10);
SATURATE_U16(PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_IA], 0, 1000*10);
SATURATE_U16(PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_UBA], 1848, 2248);
SATURATE_U16(PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_UAC], 1848, 2248);
SATURATE_U16(PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_IC], 1848, 2248);
SATURATE_U16(PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_IA], 1848, 2248);
SATURATE_U16(PARAM_INTERNAL->pwm.PhaseMask, 0, 7);
SATURATE_U16(PARAM_INTERNAL->pwm.Frequency, 1000, 40000);
SATURATE_U16(PARAM_INTERNAL->zc.Hysteresis, 0, 0.1*100);
SATURATE_U16(PARAM_INTERNAL->zc.DebouneCouner, 0, 1000);
SATURATE_U16(PARAM_INTERNAL->angle.PulseLengthReserve, 50, 1000);
}
/**
* @brief Установка параметров на дефолтные значения @ref UPP_PARAMS_DEFAULT.
* @param pui_default Сбросить параметры ПУИ
* @param internal_default Сбросить внутренние параметры
* @return HAL Status.
*/
void UPP_Params_SetDefault(int pui_default, int internal_default)
{
if(pui_default)
{
PARAM_PUI->Iref = PUI_Iref_PERCENT_DEFAULT*100;
PARAM_PUI->Tnt = PUI_Tnt_MS_DEFAULT;
PARAM_PUI->Umin = PUI_Umin_PERCENT_DEFAULT*100;
PARAM_PUI->Umax = PUI_Umax_PERCENT_DEFAULT*100;
PARAM_PUI->Imax = PUI_Imax_PERCENT_DEFAULT*100;
PARAM_PUI->Imin = PUI_Imin_PERCENT_DEFAULT*100;
PARAM_PUI->TiMax = PUI_TiMax_US_DEFAULT;
PARAM_PUI->Tdelay = PUI_Tdelay_SECONDS_DEFAULT;
PARAM_PUI->Interlace = PUI_Interlace_EN_DEFAULT;
}
if(internal_default)
{
PARAM_INTERNAL->setpoints.TemperatureWarn = SETPOINT_TEMP_WARN*10;
PARAM_INTERNAL->setpoints.TemperatureErr = SETPOINT_TEMP_ERR*10;
PARAM_INTERNAL->nominal.PhaseNumber = NOM_PHASE_NUMB;
PARAM_INTERNAL->nominal.U = NOM_U_V_DEFAULT*10;
PARAM_INTERNAL->nominal.U_deviation_plus = NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT*100;
PARAM_INTERNAL->nominal.U_deviation_minus = NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT*100;
PARAM_INTERNAL->nominal.F = NOM_F_HZ_DEFAULT*100;
PARAM_INTERNAL->nominal.F_deviation_plus = NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT*100;
PARAM_INTERNAL->nominal.F_deviation_minus = NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT*100;
PARAM_INTERNAL->nominal.I = NOM_I_A_DEFAULT*10;
PARAM_INTERNAL->pm.rms_window_size = PM_RMS_WINDOW_PERIOD_US_DEFAULT/PM_SLOW_PERIOD_US;
PARAM_INTERNAL->pm.rms_exp_alpha = FilterExp_CalcAlpha98(PM_RMS_EXT_TAU_US_DEFAULT, PM_SLOW_PERIOD_US)*65535;
PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10;
PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_UAC] = ADC_U_MAX_V_DEFAULT*10;
PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_IC] = ADC_I_MAX_A_DEFAULT*10;
PARAM_INTERNAL->adc.ADC_Max[ADC_CHANNEL_IA] = ADC_I_MAX_A_DEFAULT*10;
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_UBA] = ADC_U_ZERO_DEFAULT;
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_UAC] = ADC_U_ZERO_DEFAULT;
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_IC] = ADC_I_ZERO_DEFAULT;
PARAM_INTERNAL->adc.ADC_Zero[ADC_CHANNEL_IA] = ADC_I_ZERO_DEFAULT;
PARAM_INTERNAL->pwm.PhaseMask = 7; // (все три фазы)
PARAM_INTERNAL->pwm.Frequency = PWM_THYR_FREQUENCY_HZ_DEFAULT;
PARAM_INTERNAL->pwm.Duty = PWM_THYR_DUTY_PERCENT_DEFAULT*100;
PARAM_INTERNAL->pwm.PulseLength = PWM_THYR_PULSE_LENGTH_DEFAULT*65535;
PARAM_INTERNAL->zc.Hysteresis = ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT*100;
PARAM_INTERNAL->zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_CNT_DEFAULT;
PARAM_INTERNAL->angle.PID_Kp = ANGLE_PID_KP_COEF_DEFAULT*10000;
PARAM_INTERNAL->angle.PID_Ki = ANGLE_PID_KI_COEF_DEFAULT*10000;
PARAM_INTERNAL->angle.PID_Kd = ANGLE_PID_KD_COEF_DEFAULT*10000;
PARAM_INTERNAL->angle.Angle_Max = ANGLE_MAX_PERCENT_DEFAULT*65535;
PARAM_INTERNAL->angle.Angle_Min = ANGLE_MIN_PERCENT_DEFAULT*65535;
PARAM_INTERNAL->angle.PulseLengthReserve = ANGLE_PULSE_LENGTH_RESERVE_PERCENT_DEFAULT*100;
//__AngleSetLimit();
}
}
#define ANGLE_PERIOD_MS(_freq_) (((float)1/(_freq_*2))*1000)
// Перерасчет максимально допустимого угла
static void __AngleSetLimit(void)
{ // Сколько пачка ипульсов занимает процентов от всего периода
float pulses_percent_of_period = (((float)PARAM_INTERNAL->pwm.PulseLength / PARAM_INTERNAL->pwm.Frequency) * 1000) / ANGLE_PERIOD_MS(upp.pm.measured.final.Fmean);
// Вычитаем этот процент из 1 - получаем максимально безопасный угол
float angle_limit = 1;
angle_limit -= pulses_percent_of_period*u2f(PARAM_INTERNAL->angle.PulseLengthReserve, 100); // добавляем запас в PulseLengthReserve процентов от пачки импульсов
Angle_SetLimit(&upp.hangle, angle_limit);
}
/**
* @brief Сверить и обновить float параметр из uint16_t.
* @param paramDist Указатель на float параметр
* @param paramSrc Значение для сравнения с float параметром
* @param Coef Коэффициент для приведения float к uint16_t: uint16_t = float*coef, float = uint16_t/coef
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckParamF(float *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;
uint16_t expected_mb_param = *paramDist*Coef;
if(expected_mb_param != paramSrc)
{
*paramDist = (float)paramSrc/Coef;
return 1;
}
else
{
return 0;
}
}
/**
* @brief Сверить и обновить uint32_t параметр из uint16_t.
* @param paramDist Указатель на uint32_t параметр
* @param paramSrc Значение для сравнения с uint32_t параметром
* @param Coef Коэффициент для приведения uint32_t к uint16_t: uint16_t = uint32_t*coef, uint32_t = uint16_t/coef
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;
uint16_t expected_mb_param = *paramDist*Coef;
if(expected_mb_param != paramSrc)
{
*paramDist = (uint32_t)paramSrc/Coef;
return 1;
}
else
{
return 0;
}
}
/**
* @brief Сверить и обновить uint16_t параметр из uint16_t.
* @param paramDist Указатель на uint16_t параметр
* @param paramSrc Значение для сравнения с uint16_t параметром
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckParamU16(uint16_t *paramDist, uint16_t paramSrc)
{
if(paramDist == NULL)
return 0;
uint16_t expected_mb_param = *paramDist;
if(expected_mb_param != paramSrc)
{
*paramDist = (uint16_t)paramSrc;
return 1;
}
else
{
return 0;
}
}
/**
* @brief Сверить и обновить uint8_t параметр из uint16_t.
* @param paramDist Указатель на uint8_t параметр
* @param paramSrc Значение для сравнения с uint32_t параметром
* @param Coef Коэффициент для приведения uint32_t к uint16_t: uint16_t = uint8_t*coef, uint8_t = uint16_t/coef
* @return 0 - параметры совпадают, 1 - параметр был обновлен на paramSrc.
*/
static int __CheckParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef)
{
if(paramDist == NULL)
return 0;
uint16_t expected_mb_param = *paramDist*Coef;
if(expected_mb_param != paramSrc)
{
*paramDist = (uint8_t)paramSrc/Coef;
return 1;
}
else
{
return 0;
}
}