Compare commits

...

4 Commits

47 changed files with 1792 additions and 544 deletions

View File

@ -1,5 +1,7 @@
#include "mcu_wrapper_conf.h"
#ifdef ARM_MATH_LOOPUNROLL
#include "dsp/none.h"
#endif
#define __disable_irq()

View File

@ -9,7 +9,7 @@
#endif
#ifdef STM32F4
#define ADC_NOISE_LSB 10 // Шум в LSB (квантах АЦП)
#define ADC_NOISE_LSB 3 // Шум в LSB (квантах АЦП)
#endif
/////////////////////////////---STRUCTURES---///////////////////////////

View File

@ -131,13 +131,14 @@ void CC_PWM_Ch1_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
}
if (TIMx->DIER & TIM_IT_CC1)
{
TIMx->SR |= TIM_SR_CC1IF;
if (((TIMS->tx_cnt - TIMS->tx_step) < TIMx->CCR1) && (TIMS->tx_cnt >= TIMx->CCR1))
{
TIMx->SR |= TIM_SR_CC1IF;
TIM_Call_IRQHandller(TIMx);
}
else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR1) && (TIMS->tx_cnt <= TIMx->CCR1))
{
TIMx->SR |= TIM_SR_CC1IF;
TIM_Call_IRQHandller(TIMx);
}
}
@ -184,20 +185,21 @@ void CC_PWM_Ch2_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
}
if (TIMx->DIER & TIM_IT_CC2)
{
TIMx->SR |= TIM_SR_CC2IF;
if (((TIMS->tx_cnt - TIMS->tx_step) < TIMx->CCR2) && (TIMS->tx_cnt >= TIMx->CCR2))
{
TIMx->SR |= TIM_SR_CC2IF;
TIM_Call_IRQHandller(TIMx);
}
else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR2) && (TIMS->tx_cnt <= TIMx->CCR2))
{
TIMx->SR |= TIM_SR_CC2IF;
TIM_Call_IRQHandller(TIMx);
}
}
}
void CC_PWM_Ch3_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
{ // определяет режим канала
switch (TIMx->CCMR2 & TIM_CCMR1_OC1M)
switch (TIMx->CCMR2 & TIM_CCMR2_OC3M)
{
case (TIM_OCMODE_ACTIVE): // ACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step)
@ -237,20 +239,21 @@ void CC_PWM_Ch3_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
}
if (TIMx->DIER & TIM_IT_CC3)
{
TIMx->SR |= TIM_SR_CC3IF;
if (((TIMS->tx_cnt - TIMS->tx_step) < TIMx->CCR3) && (TIMS->tx_cnt >= TIMx->CCR3))
{
TIMx->SR |= TIM_SR_CC3IF;
TIM_Call_IRQHandller(TIMx);
}
else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR3) && (TIMS->tx_cnt <= TIMx->CCR3))
{
TIMx->SR |= TIM_SR_CC3IF;
TIM_Call_IRQHandller(TIMx);
}
}
}
void CC_PWM_Ch4_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
{ // определяет режим канала
switch (TIMx->CCMR1 & TIM_CCMR1_OC2M)
switch (TIMx->CCMR2 & TIM_CCMR2_OC4M)
{
case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode
if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step)
@ -290,13 +293,14 @@ void CC_PWM_Ch4_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
}
if (TIMx->DIER & TIM_IT_CC4)
{
TIMx->SR |= TIM_SR_CC4IF;
if (((TIMS->tx_cnt - TIMS->tx_step) < TIMx->CCR4) && (TIMS->tx_cnt >= TIMx->CCR4))
{
TIMx->SR |= TIM_SR_CC4IF;
TIM_Call_IRQHandller(TIMx);
}
else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR4) && (TIMS->tx_cnt <= TIMx->CCR4))
{
TIMx->SR |= TIM_SR_CC4IF;
TIM_Call_IRQHandller(TIMx);
}
}
@ -649,9 +653,13 @@ __weak void TIM8_BRK_TIM12_IRQHandler(void) {}
__weak void TIM8_TRG_COM_TIM14_IRQHandler(void) {}
//#endif
/* Вызов прерывания */
void TIM_Call_IRQHandller(TIM_TypeDef* TIMx)
{ // calling HANDLER
SR_STORE(TIMx, SR);
if ((TIMx == TIM1) || (TIMx == TIM10))
TIM1_UP_TIM10_IRQHandler();
else if (TIMx == TIM2)
@ -676,5 +684,7 @@ void TIM_Call_IRQHandller(TIM_TypeDef* TIMx)
TIM8_BRK_TIM12_IRQHandler();
else if ((TIMx == TIM8) || (TIMx == TIM14))
TIM8_TRG_COM_TIM14_IRQHandler();
SR_PROCESS(TIMx, SR);
}
//------------------------------------------------------------------//

View File

@ -16,6 +16,7 @@ MCU_CortexMemoryTypeDef MCU_CORTEX_MEM;
// MCU PERIPH INIT
void Initialize_Periph_Sim(void)
{
uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000);
Init_TIM_SIM();
Init_ADC_SIM();
}
@ -43,8 +44,10 @@ void deInitialize_MCU(void)
memset(&MCU_CORTEX_MEM, 0, sizeof(MCU_CORTEX_MEM));
memset(&htim1, 0, sizeof(htim1));
ClearStruct(upp);
ClearStruct(htim1);
ClearStruct(htim2);
ClearStruct(htim3);
ClearStruct(htim8);
ClearStruct(htim11);
@ -107,7 +110,7 @@ struct TIM_Sim tim14s;
void Init_TIM_SIM(void)
{
#ifdef USE_TIM1
memset(&tim1s, 0, sizeof(tim1s));
memset(&tim1s, 0, sizeof(tim1s));
tim1s.tx_cnt = TIM1->CNT;
tim1s.tx_step = hmcu.sSimSampleTime * ABP2_TIMS_Value;
@ -121,7 +124,7 @@ void Init_TIM_SIM(void)
tim1s.Channels.OC4_PIN_SHIFT = 11;
#endif
#ifdef USE_TIM2
memset(&tim2s, 0, sizeof(tim2s));
memset(&tim2s, 0, sizeof(tim2s));
tim2s.tx_cnt = TIM2->CNT;
tim2s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
@ -135,7 +138,7 @@ void Init_TIM_SIM(void)
tim2s.Channels.OC4_PIN_SHIFT = 3;
#endif
#ifdef USE_TIM3
memset(&tim3s, 0, sizeof(tim3s));
memset(&tim3s, 0, sizeof(tim3s));
tim3s.tx_cnt = TIM3->CNT;
tim3s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
@ -149,7 +152,7 @@ void Init_TIM_SIM(void)
tim3s.Channels.OC4_PIN_SHIFT = 9;
#endif
#ifdef USE_TIM4
memset(&tim4s, 0, sizeof(tim4s));
memset(&tim4s, 0, sizeof(tim4s));
tim4s.tx_cnt = TIM4->CNT;
tim4s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
@ -163,7 +166,7 @@ void Init_TIM_SIM(void)
tim4s.Channels.OC4_PIN_SHIFT = 9;
#endif
#ifdef USE_TIM5
memset(&tim5s, 0, sizeof(tim5s));
memset(&tim5s, 0, sizeof(tim5s));
tim5s.tx_cnt = TIM5->CNT;
tim5s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
@ -177,7 +180,7 @@ void Init_TIM_SIM(void)
tim5s.Channels.OC4_PIN_SHIFT = 3;
#endif
#ifdef USE_TIM6
memset(&tim6s, 0, sizeof(tim6s));
memset(&tim6s, 0, sizeof(tim6s));
tim6s.tx_cnt = TIM6->CNT;
tim6s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;

View File

@ -147,4 +147,14 @@ static void ADC_SIM_DEINIT() {}
//-----------------------------------------------------------------------//
#define SR_STORE(periph, srname) \
uint32_t sr_origin = periph->srname; \
uint32_t sr_new = periph->srname;
#define SR_PROCESS(periph, srname) \
sr_new = sr_origin & periph->srname; \
periph->srname = sr_new;
#endif // _MATLAB_SETUP_H_

View File

@ -15,7 +15,6 @@
"Initialize_Periph_Sim()"
],
"PeriphSimulation": [
"uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000)",
"Simulate_Periph_Sim()"
],
"PeriphDeinit": [

View File

@ -55,11 +55,11 @@
// INPUT/OUTPUTS PARAMS START
#define IN_PORT_NUMB 2
#define ADC_PORT_1_WIDTH 6
#define IN_PORT_2_WIDTH 1
#define IN_PORT_2_WIDTH 16
#define OUT_PORT_NUMB 3
#define THYR_PORT_1_WIDTH 6
#define PM_PORT_2_WIDTH 16
#define PM_PORT_2_WIDTH 32
#define OUT_PORT_3_WIDTH 16
// INPUT/OUTPUTS PARAMS END
@ -79,7 +79,7 @@
* @param _arr_ind_ Индекс выходного порта
* @param _val_ind_ Индекс элемента в выходном массиве
*/
#define WriteOutputArray(_var_, _arr_ind_, _val_ind_) __WriteOutputArray(Buffer, (float)_var_, _arr_ind_, _val_ind_)
#define WriteOutputArray(_var_, _arr_ind_, _val_ind_) __WriteOutputArray(Buffer, (float)(_var_), _arr_ind_, _val_ind_)
/** @brief Считывает значение из входного массива блока S-Function
* @param _var_ Значение, которое необходимо записать (будет преобразовано в float)

View File

@ -54,33 +54,6 @@ set code_PERIPH=.\MCU_STM32_Matlab\stm32_matlab_conf.c^
.\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_matlab_gpio.c^
.\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_matlab_dma.c^
.\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_periph_registers.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BasicMathFunctions\BasicMathFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BasicMathFunctions\BasicMathFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BayesFunctions\BayesFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BayesFunctions\BayesFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\CommonTables\CommonTables.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\CommonTables\CommonTablesF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ComplexMathFunctions\ComplexMathFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ComplexMathFunctions\ComplexMathFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ControllerFunctions\ControllerFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\DistanceFunctions\DistanceFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FastMathFunctions\FastMathFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FastMathFunctions\FastMathFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FilteringFunctions\FilteringFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FilteringFunctions\FilteringFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\InterpolationFunctions\InterpolationFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\InterpolationFunctions\InterpolationFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\MatrixFunctions\MatrixFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\MatrixFunctions\MatrixFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\QuaternionMathFunctions\QuaternionMathFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\StatisticsFunctions\StatisticsFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\StatisticsFunctions\StatisticsFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SupportFunctions\SupportFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SupportFunctions\SupportFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SVMFunctions\SVMFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SVMFunctions\SVMFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\TransformFunctions\TransformFunctions.c^
.\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\TransformFunctions\TransformFunctionsF16.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c^
@ -102,24 +75,7 @@ set includes_PERIPH=-I".\MCU_STM32_Matlab\."^
-I".\MCU_STM32_Matlab\Drivers\CMSIS"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\Device\STM32F4xx"^
-I".\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc"^
-I".\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Include"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\PrivateInclude"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BasicMathFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\BayesFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\CommonTables"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ComplexMathFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\ControllerFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\DistanceFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FastMathFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\FilteringFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\InterpolationFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\MatrixFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\QuaternionMathFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\StatisticsFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SupportFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\SVMFunctions"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\DSP\Source\TransformFunctions"
-I".\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy"
:: PERIPH BAT END
::-------------------------------------------------------------------------

View File

@ -24,6 +24,7 @@ void app_init(void) {
MX_TIM8_Init();
MX_TIM5_Init();
MX_ADC3_Init();
UPP_SetDefault(1, 1);
UPP_Init();
UPP_PreWhile();

View File

@ -6,6 +6,8 @@
#include "mcu_wrapper_conf.h"
#include "app_wrapper.h"
float dbg[16];
#define PIN_READ(_verbname_) (_verbname_##_GPIO_Port->ODR & (_verbname_##_Pin)) ? 1 : 0
void Write_Thyristors(real_T* Buffer, int ind_port)
@ -30,25 +32,31 @@ void Write_PowerMonitor(real_T* Buffer, int ind_port)
{
int nn = 0;
for (int i = 0; i < 3; i++)
{
WriteOutputArray(upp.pm.U[i], ind_port, nn++);
{ //0-2
WriteOutputArray(upp.pm.measured.Ureal[i], ind_port, nn++);
}
for (int i = 0; i < 3; i++)
{
{ //3-5
WriteOutputArray(upp.pm.zc.Channel[i].HalfWave, ind_port, nn++);
}
for (int i = 0; i < 3; i++)
{
WriteOutputArray(upp.pm.F[i], ind_port, nn++);
{ //6-8
WriteOutputArray(upp.pm.measured.F[i], ind_port, nn++);
}
for (int i = 0; i < 3; i++)
{
WriteOutputArray(upp.pm.I[i], ind_port, nn++);
{ //9-11
WriteOutputArray(upp.pm.measured.Ireal[i], ind_port, nn++);
}
for (int i = 0; i < 2; i++)
{
WriteOutputArray(upp.pm.T[i], ind_port, nn++);
{ //12-13
WriteOutputArray(upp.pm.measured.T[i], ind_port, nn++);
}
{ //14-16
WriteOutputArray(upp.pm.measured.U_mean, ind_port, nn++);
WriteOutputArray(upp.pm.measured.I_mean, ind_port, nn++);
WriteOutputArray(upp.pm.measured.F_mean, ind_port, nn++);
}
}
/**
* @brief Функция для записи входов в приложение МК
@ -64,6 +72,7 @@ void app_readInputs(const real_T* Buffer) {
ADC_Set_Channel_Value(ADC3, 10, ReadInputArray(0,5));
alpha_dbg = ReadInputArray(1, 0);
upp.call->go = ReadInputArray(1, 1);
// USER APP INPUT END
}
@ -75,11 +84,25 @@ void app_readInputs(const real_T* Buffer) {
void app_writeOutputBuffer(real_T* Buffer) {
// USER APP OUTPUT START
Write_Thyristors(Buffer, 0);
Write_PowerMonitor(Buffer, 1);
WriteOutputArray(TIM2->CNT, 2, 0);
WriteOutputArray(TIM2->CCR1, 2, 1);
int nn = 0;
//WriteOutputArray(upp.hangle.htim->Instance->CNT, 2, nn++);
WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR1) - upp.hangle.htim->Instance->CNT, 2, nn++);
WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR2) - upp.hangle.htim->Instance->CNT, 2, nn++);
WriteOutputArray((long long)(upp.hangle.htim->Instance->CCR3) - upp.hangle.htim->Instance->CNT, 2, nn++);
//WriteOutputArray(dbg[0], 2, nn++);
//WriteOutputArray(dbg[1], 2, nn++);
//WriteOutputArray(dbg[2], 2, nn++);
WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_POS].State, 2, nn++);
WriteOutputArray(upp.hpwm.AllPhases[PHASE_A_NEG].State, 2, nn++);
WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_POS].State, 2, nn++);
WriteOutputArray(upp.hpwm.AllPhases[PHASE_B_NEG].State, 2, nn++);
WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_POS].State, 2, nn++);
WriteOutputArray(upp.hpwm.AllPhases[PHASE_C_NEG].State, 2, nn++);
// USER APP OUTPUT END
}

View File

@ -9,7 +9,15 @@
void app_step(void)
{
// USER APP STEP START
UPP_While();
static uint32_t uwTickPrev = 0;
if (uwTickPrev != uwTick)
{
uwTickPrev = uwTick;
UPP_Tick();
}
// USER APP STEP END
}

Binary file not shown.

View File

@ -1,7 +1,7 @@
clear all
Ts = 5e-6;
Vnom = 380;
Vnom = 690;
Fnom = 50;
Temperature1 = 2.22; % 20 градусов

Binary file not shown.

@ -1 +1 @@
Subproject commit 3aa279736d9383a06613f72d7b7462f0f23d7d4d
Subproject commit e0ce0e6dbf35d035175d30971442bc8d99f3bdd7

@ -1 +1 @@
Subproject commit 99652a9ad5ea0686ad9242b165508a9d92ac80a1
Subproject commit 9bff9ad44dd625819ef654e98ca351d5bc5568a9

@ -1 +1 @@
Subproject commit b3f118b074951fa827e5a692e9da7637b5397a98
Subproject commit 272642b310043355b0af95e0410afbbcb74d17b7

View File

@ -16,7 +16,7 @@
******************************************************************************/
#ifndef __SPI_MEMORY_CONFIG_H_
#define __SPI_MEMORY_CONFIG_H_
#include "upp_config.h"
#include "upp_defs.h"
/////////////////////////---USER SETTINGS---/////////////////////////

View File

@ -19,7 +19,7 @@
******************************************************************************/
#ifndef _MODBUS_CONFIG_H_
#define _MODBUS_CONFIG_H_
#include "upp_config.h"
#include "upp_defs.h"
// Общие параметры
#define MODBUS_DEVICE_ID 1 ///< Адрес устройства в сети Modbus

View File

@ -22,6 +22,9 @@
#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.
@ -78,6 +81,10 @@ MB_ExceptionTypeDef MB_DefineRegistersAddress(uint16_t **pRegs, uint16_t Addr, u
{
*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
{

View File

@ -50,20 +50,24 @@
#ifndef _MODBUS_DATA_H_
#define _MODBUS_DATA_H_
#include "upp_defs.h"
#include "upp_control.h"
#include "stdint.h"
//--------------SIZES OF DATA---------------
#define R_HOLDING_PRVT_PARAMS_ADR 555
#define R_HOLDING_PRVT_PARAMS_QNT (sizeof(UPP_PrvtParams_t)/sizeof(uint16_t))
// DEFINES FOR INPUT REGISTERS ARRAYS
#define R_INPUT_ADDR 0 ///< Начальный адрес входных регистров
#define R_INPUT_QNT 16 ///< Количество входных регистров
#define R_INPUT_QNT (sizeof(UPP_PUI_Values_t)/sizeof(uint16_t)) ///< Количество входных регистров
// DEFINES FOR HOLDING REGISTERS ARRAYS
#define R_HOLDING_ADDR 0 ///< Начальный адрес регистров хранения
#define R_HOLDING_QNT 16 ///< Количество регистров хранения
#define R_HOLDING_QNT (sizeof(UPP_PUI_Params_t)/sizeof(uint16_t)) ///< Количество регистров хранения
// DEFINES FOR COIL ARRAYS
#define C_COILS_ADDR 0 ///< Начальный адрес коилов
@ -89,7 +93,7 @@
*/
typedef struct //MB_DataInRegsTypeDef
{
uint16_t in[16];
UPP_PUI_Values_t pui;
}MB_DataInRegsTypeDef;
@ -98,7 +102,7 @@ typedef struct //MB_DataInRegsTypeDef
*/
typedef struct //MB_DataInRegsTypeDef
{
uint16_t out[16];
UPP_PUI_Params_t pui_params;
}MB_DataHoldRegsTypeDef;
@ -153,6 +157,13 @@ typedef struct // tester modbus data
extern MB_DataStructureTypeDef MB_DATA;
typedef struct
{
UPP_FuncCalls_t FuncCalls;
UPP_PrvtParams_t param;
}MB_DataInternalTypeDef;
extern MB_DataInternalTypeDef MB_INTERNAL;
#endif //_MODBUS_DATA_H_
/////////////////////////////////////////////////////////////

View File

@ -10,7 +10,7 @@
*************************************************************************/
#ifndef __MYLIBS_CONFIG_H_
#define __MYLIBS_CONFIG_H_
#include "upp_config.h"
#include "upp_defs.h"
// user includes
/**
@ -65,7 +65,7 @@
//#define FILTER_MEDIAN_MAX_SIZE ///< Максимальный размер окна медианного фильтра (по умолчанию 5)
//#define FILTER_AVERAGE_MAX_SIZE ///< Максимальный размер окна усредняющего фильтра (по умолчанию 8)
//#define FILTER_POLY_MAX_ORDER ///< Максимальный порядок полинома (по умолчанию 4)
#define FILTERS_DISABLE_MOVING_AVERAGE
/** GEN_CONFIG
* @}
*/
@ -96,9 +96,12 @@
*/
//#define BENCH_TIME_ENABLE ///< Включить бенч времени
#define BENCH_TIME_MAX_CHANNELS 16 ///< Максимальное количество каналов измерения
#define BENCH_TIME_ENABLE ///< Включить бенч времени
#define BENCH_TIME_MAX_CHANNELS 5 ///< Максимальное количество каналов измерения
#define BT_ADC 0
#define BT_PWM 1
#define BT_SYSTICK 2
/** GEN_CONFIG
* @}
*/
@ -126,13 +129,14 @@
#else
extern float dbg[16];
#define local_time() uwTick ///< Локальное время
//#define INCLUDE_GEN_OPTIMIZER ///< Подключить библиотеку для оптимизации параметров
#define INCLUDE_BIT_ACCESS_LIB ///< Подключить библиотеку с typedef с битовыми полями
#define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами
//#define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами
#define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией
//#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени
#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени
#define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами
#endif //MATLAB

View File

@ -18,48 +18,80 @@
#define assert_upp(_struct_) check_null_ptr_2(_struct_, (_struct_)->f.Initialized)
/* Дефайны для индексов */
#define U_BA 0
#define U_AC 1
#define U_BC 2
#define I_C 0
#define I_A 1
#define I_B 2
#define U_BA 0
#define U_AC 1
#define U_BC 2
#define I_C 0
#define I_A 1
#define I_B 2
#define TEMP_1 0
#define TEMP_2 1
/* Дефайны для базовых величин */
#define PM_U_BASE 1216.0
#define PM_I_BASE 53.0
/* Дефайны для настройки мониторинга питания */
#define PM_ADC_PERIOD_MKS 10
#define PM_ZERO_CROSS_HYSTERESIS_V 10
#define PM_ZERO_CROSS_DEBOUNCE_10US 2.5*100 // (2.5 * 100 = 2.5 мс)
/* Рассчитанные дефайны */
#define PM_ADC_PERIOD (180*PM_ADC_PERIOD_MKS)-1
/* Общие для всего проекта структуры*/
/**
* @brief Состояния полуволны
* @addtogroup UPP_DEFAULT_PARAMS Default params for external flash
* @ingroup UPP_CONFIG
* @brief Дефолтные параметры для внешней памяти. Они применятся по команде или по ошибке
* @{
*/
typedef enum {
UPP_WAVE_UNKNOWED = 0,
UPP_WAVE_POSITIVE,
UPP_WAVE_NEGATIVE
} UPP_HalfWave_t;
/* Параметри мониторинга сети */
#define PM_EXP_ALPHA_COEF_DEFAULT 0.01
/**
* @brief Названия Фаз
/* Номинальные параметры */
#define NOM_PHASE_NUMB 3
#define NOM_U_V_DEFAULT 690
#define NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT 6
#define NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT 10
#define NOM_F_HZ_DEFAULT 50
#define NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT 5
#define NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT 5
#define NOM_I_A_DEFAULT 5
/* Параметры ПУИ */
#define PUI_Iref_PERCENT_DEFAULT 150
#define PUI_Tnt_MS_DEFAULT 300
#define PUI_Umin_PERCENT_DEFAULT 80
#define PUI_Umax_PERCENT_DEFAULT 120
#define PUI_Imax_PERCENT_DEFAULT 99
#define PUI_Imin_PERCENT_DEFAULT 7
#define PUI_TiMax_US_DEFAULT 5000
#define PUI_Tdelay_SECONDS_DEFAULT 30
#define PUI_Interlace_EN_DEFAULT 5000
/* Параметры АЦП */
#define ADC_U_MAX_V_DEFAULT 1216.0
#define ADC_I_MAX_A_DEFAULT 53.0
#define ADC_U_ZERO_DEFAULT 2048
#define ADC_I_ZERO_DEFAULT 2048
/* Параметры определения перехода через ноль */
#define ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT 2.0
#define ZERO_CROSS_DEBOUNCE_10US_DEFAULT 2*100 // (2.5 * 100 = 2.5 мс)
/* Параметры ШИМ для тиристоров */
#define PWM_THYR_FREQUENCY_HZ_DEFAULT 20000
#define PWM_THYR_PULSE_NUMBER_DEFAULT 20
/** //UPP_DEFAULT_PARAMS
* @}
*/
typedef enum {
UPP_PHASE_A = 0,
UPP_PHASE_B = 1,
UPP_PHASE_C = 2,
UPP_PHASE_UNKNOWN = 3
} UPP_Phase_t;
/**
* @addtogroup UPP_COMPILED_PARAMS Fixed params
* @ingroup UPP_CONFIG
* @brief Параметры устанавливаемые на этапе компиляции. Без перепрошивки их не поменять
* @{
*/
/* Периоды вызова всякого */
#define PM_ADC_PERIOD_US 10 ///< Период опроса АЦП в мкс
#define PM_SLOW_PERIOD_10US 50 ///< Период обновление медленных расчетов в 10мкс
#define PM_TEMP_PERIOD_10US 5000 ///< Период обновление датчиков температуры в 10мкс
/* Частоты таймеров в МГц*/
#define ADC_TIM8_FREQ_MZH 180 ///< Частота тиков таймера АЦП
#define PWM_TIM1_FREQ_MHZ 180 ///< Частота тиков таймера ШИМ (1-4 каналы)
#define PWM_TIM3_FREQ_MHZ 90 ///< Частота тиков таймера ШИМ (5-6 каналы)
#define ANGLE_TIM2_FREQ_MHZ 90 ///< Частота тиков таймера отсчета угла открытия тиристоров
#endif //_UPP_CONFIG_H_

180
UPP/Core/Configs/upp_defs.h Normal file
View File

@ -0,0 +1,180 @@
/**
******************************************************************************
* @file upp_defs.h
* @brief Общие дефайны УПП
******************************************************************************
@addtogroup UPP_DEFS UPP defines
@ingroup UPP_MAIN
@brief Общие дефайны для всего проекта УПП
@{
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_DEFS_H_
#define _UPP_DEFS_H_
#include "upp_config.h"
/**
* @addtogroup UPP_HIGHLEVEL Defines for high-level
* @ingroup UPP_DEFS
* @brief Дефайны УПП которые определяют коды ошибок и параметры для общения с верхним уровнем
* @{
*/
/**
* @brief Список аварий УПП
*/
typedef enum {
WM_Not_Init = 0, ///< УПП не инициализирован
WM_Ready = 1, ///< УПП в готовности
WM_Running = 2, ///< УПП в работе, управляет тиристорами
WM_Done = 3, ///< УПП закончил свою работу
WM_Error = 4, ///< УПП в аварии
} UPP_WorkModeType_t;
/**
* @brief Список аварий УПП
*/
typedef enum {
Err_None = 0, ///< Неисправность отсутствует
/* Програмные ошибки */
Err_Internal_1 = 1, ///< Внутренняя неисправность УПП 1
Err_Internal_2 = 2, ///< Внутренняя неисправность УПП 2
Err_Internal_3 = 3, ///< Внутренняя неисправность УПП 3
Err_Internal_4 = 4, ///< Внутренняя неисправность УПП 4
Err_Internal_5 = 5, ///< Внутренняя неисправность УПП 5
Err_Internal_6 = 6, ///< Внутренняя неисправность УПП 6
/* Ошибки по питанию */
Err_Power_Digit_5V = 7, ///< Неисправность цифрового источника питания (5 В)
Err_Power_24V = 8, ///< Неисправность источника питания 24 В
Err_Power_Analog_5V = 9, ///< Неисправность аналогового источника питания микроконтроллера (± 5 В)
Err_Power_SCI_5V = 10, ///< Неисправность источника питания последовательных интерфейсов микроконтроллера (5 В)
Err_Power_DIO_24V = 11, ///< Неисправность источника питания дискретных входов/выходов (24 В)
/* Ошибки по допустимым пределам Наряжений/Токов/Температуры */
Err_OverCurrent = 12, ///< Ток выше допустимого (см. Imax и TiMax в @ref UPP_PUI_Params_t)
Err_OverVoltage = 13, ///< Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t)
Err_OverTemperature = 14, ///< Температура выше допустимой (плюс 85 °C)
Err_UnderVoltage = 15, ///< Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t)
/* Ошибки по обрывам фаз */
Err_LossPhaseAll = 16, ///< Обрыв трёх фаз (см. Imin в @ref UPP_PUI_Params_t)
Err_LossPhaseA = 17, ///< Обрыв фазы A (см. Imin в @ref UPP_PUI_Params_t)
Err_LossPhaseB = 18, ///< Обрыв фазы B (см. Imin в @ref UPP_PUI_Params_t)
Err_LossPhaseC = 19, ///< Обрыв фазы C (см. Imin в @ref UPP_PUI_Params_t)
/* Другие ошибки */
Err_LongStart = 20, ///< Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t)
Err_Interlace = 21, ///< Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t)
Err_OverFrequency = 22, ///< Частота сети выше допустимой
Err_UnderFrequency = 23, ///< Частота сети ниже допустимой
} UPP_ErrorType_t;
/**
* @brief Структура данных от УПП передаваемых в ПУИ
*/
typedef struct {
uint16_t Error; /** @brief Текущая авария
@details В случае срабатывания защиты */
uint16_t WorkMode; /** @brief Режим работы
@details «Готовность» или «Работа» */
uint16_t Voltage; /** @brief Напряжение на входе УПП, Вольты */
uint16_t Current; /** @brief Ток на входе УПП, Амперы */
uint16_t Frequency; /** @brief Частота напряжения на входе УПП */
uint16_t Temperature; /** @brief Температура радиатора тиристоров, Градусы Цельсия */
} UPP_PUI_Values_t;
/**
* @brief Структура параметров УПП от ПУИ
* @details Параметры по умолчанию приведены в @ref UPP_DEFAULT_PARAMS
* @note Защиты X приведены в @ref UPP_ErrorType_t
*/
typedef struct {
uint16_t Iref; /** @brief Уставка ограничения тока УПП
@details В диапазоне от 100 % до 500 % от = 5 А
По умолчанию @ref PUI_Iref_PERCENT_DEFAULT */
uint16_t Tnt; /** @brief Уставка времени нарастания заданного тока
@details В диапазоне от 50 до 5000 мс.
По умолчанию @ref PUI_Tnt_MS_DEFAULT */
uint16_t Umin; /** @brief Уставка защиты №15 от понижения напряжения входной сети
@details В диапазоне от 5% до 99 % от = 690 В.
По умолчанию @ref PUI_Umin_PERCENT_DEFAULT */
uint16_t Umax; /** @brief Уставка защиты №13 от повышения напряжения входной сети
@details В диапазоне от 100% до 120 % от = 690 В.
По умолчанию @ref PUI_Umax_PERCENT_DEFAULT */
uint16_t Imax; /** @brief Уставка защиты №12 по току
@details В диапазоне от 5 % до 99 % от 50 А.
По умолчанию @ref PUI_Imax_PERCENT_DEFAULT */
uint16_t Imin; /** @brief Уставка защит № 16 №19 от обрыва фаз(ы)
@details В диапазоне от 0 % до 40 % от = 5 А. При задании нуля эти защиты отключаются.
По умолчанию @ref PUI_Imin_PERCENT_DEFAULT */
uint16_t TiMax; /** @brief Выдержка времени на срабатывание защиты № 12 по току
@details В диапазоне от 500 до 10000 мкс.
По умолчанию @ref PUI_TiMax_US_DEFAULT */
uint16_t Tdelay; /** @brief Выдержка времени защиты № 20 от затянутого пуска
@details В диапазоне от 5 до 60 с.
По умолчанию @ref PUI_Tdelay_SECONDS_DEFAULT */
uint16_t Interlace; /** @brief Разрешение защиты № 21 от обратного порядка чередования фаз;
@details 0 нет защиты, 1 есть защита.
По умолчанию @ref PUI_Interlace_EN_DEFAULT */
} UPP_PUI_Params_t;
/** //UPP_HIGHLEVEL
* @}
*/
/**
* @addtogroup UPP_INTERNAL_DEFS Defines for internal use
* @ingroup UPP_DEFS
* @brief Дефайны УПП которые используютяс исключительно внутри программы
* @{
*/
#define ANGLE_PERIOD_MS(_freq_) (((float)1/(_freq_*2))*1000)
/**
* @brief Состояния полуволны
*/
typedef enum {
UPP_WAVE_UNKNOWED = 0,
UPP_WAVE_POSITIVE,
UPP_WAVE_NEGATIVE
} UPP_HalfWave_t;
/**
* @brief Названия Фаз
*/
typedef enum {
UPP_PHASE_A = 0,
UPP_PHASE_B = 1,
UPP_PHASE_C = 2,
UPP_PHASE_UNKNOWN = 3
} UPP_Phase_t;
/** //UPP_INTERNAL_DEFS
* @}
*/
#endif //_UPP_DEFS_H_
/** //UPP_DEFS
* @}
*/

View File

@ -31,11 +31,10 @@ extern "C" {
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "upp_config.h"
#include "upp_defs.h"
#include "upp_errors.h"
#include "mylibs_include.h"
#ifndef MATLAB
#include "modbus.h"
#endif
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
@ -56,7 +55,7 @@ extern "C" {
void Error_Handler(void);
/* USER CODE BEGIN EFP */
extern __IO uint32_t micros;
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/

View File

@ -7,32 +7,6 @@
******************************************************************************/
#include "adc_tools.h"
//Полосовой фильтр 45-55 Гц
static float coefs_biquad_U[5] = {
0.000010f, // b0
0.000020f, // b1
0.000010f, // b2
-1.900000f, // a1
0.950000f // a2
};
// ФНЧ 100 Гц
static float coefs_biquad_I[5] = {
0.000010f, // b0
0.000020f, // b1
0.000010f, // b2
-1.900000f, // a1
0.950000f // a2
};
// ФНЧ 10 Гц
static float coefs_biquad_T[5] = {
0.0002f, // b0
0.0004f, // b1
0.0002f, // b2
-1.98f, // a1
0.980f // a2
};
static void ADC_EnableAllFilters(ADC_Periodic_t *adc)
{
for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++)
@ -106,6 +80,8 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t le
adc->Coefs[ChNumb].lMax = levelMax;
adc->Coefs[ChNumb].vMax = valueMax;
adc->Coefs[ChNumb].lZero = levelZero;
ADC_ResetStatistics(adc, ChNumb);
return HAL_OK;
}
@ -116,16 +92,16 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t le
* @return HAL Status.
* @details Запускает АЦП с частотой дискретизации на которую настроен таймер adc_tim.
*/
HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period)
HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, float PeriodUs)
{
HAL_StatusTypeDef res;
if(assert_upp(adc))
return HAL_ERROR;
if(Period == 0)
if(PeriodUs == 0)
return HAL_ERROR;
// Запускаем таймер который будет запускать опрос АЦП с заданным периодом
__HAL_TIM_SET_AUTORELOAD(adc->htim, Period);
__HAL_TIM_SET_AUTORELOAD(adc->htim, TIM_MicrosToTick(PeriodUs, ADC_TIM8_FREQ_MZH));
res = HAL_TIM_Base_Start(adc->htim);
if(res != HAL_OK)
{
@ -180,7 +156,7 @@ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc)
{
ADC_Coefs_t *coefs = &adc->Coefs[i];
data[i] = ((float)(raw[i])-coefs->lZero) * coefs->vMax / (coefs->lMax-coefs->lZero);
ADC_UpdateStatistics(adc, i, ADC_LEVEL_AC);
// ADC_UpdateStatistics(adc, i, ADC_LEVEL_AC);
}
// Фильтрация от шумов для всех каналов
@ -193,19 +169,15 @@ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc)
}
}
// Преобразования температуры по таблице
for (int i = ADC_TEMP_CHANNELS_START; i < ADC_NUMB_OF_CHANNELS; i++)
{
data[i] = Filter_Process(&adc->temp_map[i-ADC_TEMP_CHANNELS_START], raw[i]);
ADC_UpdateStatistics(adc, i, ADC_LEVEL_BASE);
// ADC_UpdateStatistics(adc, i, ADC_LEVEL_BASE);
}
adc->f.DataReady = 1;
if(Filter_isDataReady(&adc->filter[0]))
adc->f.DataReady = 1;
return HAL_OK;
}
@ -245,7 +217,7 @@ void ADC_UpdateStatistics(ADC_Periodic_t *adc, uint8_t channel, ADC_StatLevel_t
}
// Накопление для Avg/RMS
stat->Sum += value;
stat->Sum += ABS(value);
stat->SumSquares += value * value;
stat->SampleCount++;

View File

@ -67,7 +67,7 @@ typedef struct
typedef enum
{
ADC_LEVEL_DISABLE=0, ///< Базовая статистика - Max/Min
ADC_LEVEL_DISABLE=0, ///< Статистика отключена
ADC_LEVEL_BASE, ///< Базовая статистика - Max/Min
ADC_LEVEL_AC, ///< Статистика для переменных сигналов - AVG, RMS
}ADC_StatLevel_t;
@ -123,7 +123,7 @@ HAL_StatusTypeDef ADC_Init(ADC_Periodic_t *adc, TIM_HandleTypeDef *htim, ADC_Han
/* Конфигуарция канала АЦП. */
HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax);
/* Запуск АЦП. */
HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period);
HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, float PeriodUs);
/* Остановка АЦП. */
HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc);

View File

@ -12,22 +12,44 @@
HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
{
if(hpm == NULL)
return HAL_ERROR;
/* Инициализация АЦП */
if(ADC_Init(&hpm->adc, &adc_tim, &hadc3) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA, 2048, PM_U_BASE, 4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UAC, 2048, PM_U_BASE, 4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IC, 2048, PM_I_BASE, 4095) != HAL_OK)
/* Инициализация каналов АЦП */
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UBA,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA],
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IA, 2048, PM_I_BASE, 4095) != HAL_OK)
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_UAC,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UAC],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC],
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IC,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IC],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC],
4095) != HAL_OK)
return HAL_ERROR;
if(ADC_ConfigChannel(&hpm->adc, ADC_CHANNEL_IA,
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IA],
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA],
4095) != HAL_OK)
return HAL_ERROR;
if(ZC_Init(&hpm->zc, 3, PM_ZERO_CROSS_HYSTERESIS_V, PM_ZERO_CROSS_DEBOUNCE_10US) != HAL_OK)
/* Инициализация алгоритма перехода через ноль */
if(ZC_Init(&hpm->zc, 3, (float)MB_INTERNAL.param.zc.Hysteresis/100, MB_INTERNAL.param.zc.DebouneCouner) != HAL_OK)
return HAL_ERROR;
/* Инициализация каналов алгоритма перехода через ноль */
if(ZC_ConfigChannel(&hpm->zc, U_BA, ZC_BOTH_EDGES) != HAL_OK)
return HAL_ERROR;
if(ZC_ConfigChannel(&hpm->zc, U_AC, ZC_BOTH_EDGES) != HAL_OK)
@ -35,40 +57,136 @@ HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm)
if(ZC_ConfigChannel(&hpm->zc, U_BC, ZC_BOTH_EDGES) != HAL_OK)
return HAL_ERROR;
/* Инициализация экпоненциального фильтра медленного алга */
for(int i = 0; i < 3; i++)
{
if(FilterExp_Init(&hpm->measured.exp[i], (float)MB_INTERNAL.param.pm.mean_alpha/65535))
return HAL_ERROR;
Filter_Start(&hpm->measured.exp[i]);
}
/* Инициализация среднего фильтра медленного алга */
for(int i = 0; i < ADC_NUMB_OF_REGULAR_CHANNELS; i++)
{
if(FilterAverage_Init(&hpm->measured.avg[i], PM_SLOW_PERIOD_10US, FILTER_MODE_DEFAULT))
return HAL_ERROR;
Filter_Start(&hpm->measured.avg[i]);
}
for(int i = 0; i < ADC_NUMB_OF_T_CHANNELS; i++)
{
if(FilterAverage_Init(&hpm->measured.avg[ADC_TEMP_CHANNELS_START+i], PM_TEMP_PERIOD_10US, FILTER_MODE_DEFAULT))
return HAL_ERROR;
Filter_Start(&hpm->measured.avg[ADC_TEMP_CHANNELS_START+i]);
}
return HAL_OK;
}
HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm)
{
if(ADC_Start(&hpm->adc, PM_ADC_PERIOD) != HAL_OK)
return HAL_ERROR;
if(hpm == NULL)
return HAL_ERROR;
if(ADC_Start(&hpm->adc, PM_ADC_PERIOD_US) != HAL_OK)
return HAL_ERROR;
return HAL_OK;
}
void PowerMonitor_SlowHandle(PowerMonitor_t *hpm)
{
if(hpm == NULL)
return;
if(!hpm->f.runSlow)
return;
hpm->f.runSlow = 0;
PowerMonitor_Measured_t *meas = &hpm->measured;
meas->Uslow[U_BC] = -meas->Uslow[U_BA] - meas->Uslow[U_AC];
meas->Islow[I_B] = -meas->Islow[I_A] - meas->Islow[I_C];
float umean = 0;
float imean = 0;
float fmean = 0;
for(int i = 0; i < 3; i++)
{
umean += ABS(meas->Uslow[i]);
imean += ABS(meas->Islow[i]);
fmean += ABS(meas->F[i]);
}
umean /=3;
imean /=3;
fmean /=3;
meas->U_mean = Filter_Process(&meas->exp[0], umean);
meas->I_mean = Filter_Process(&meas->exp[1], imean);
meas->F_mean = Filter_Process(&meas->exp[2], fmean);
}
void PowerMonitor_Handle(PowerMonitor_t *hpm)
{
static uint32_t last_zc_cnt[ADC_NUMB_OF_U_CHANNELS] = {0};
if(hpm == NULL)
return;
/* Считываем АЦП */
ADC_Handle(&hpm->adc);
hpm->U[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA];
hpm->U[U_AC] = hpm->adc.Data[ADC_CHANNEL_UAC];
hpm->U[U_BC] = -hpm->U[U_BA] - hpm->U[U_AC];
hpm->I[I_C] = hpm->adc.Data[ADC_CHANNEL_IC];
hpm->I[I_A] = hpm->adc.Data[ADC_CHANNEL_IA];
hpm->I[I_B] = -hpm->I[I_A] - hpm->I[I_C];
/* Заполняем величины */
PowerMonitor_Measured_t *meas = &hpm->measured;
meas->Ureal[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA];
meas->Ureal[U_AC] = hpm->adc.Data[ADC_CHANNEL_UAC];
meas->Ureal[U_BC] = -meas->Ureal[U_BA] - meas->Ureal[U_AC];
meas->Ireal[I_C] = hpm->adc.Data[ADC_CHANNEL_IC];
meas->Ireal[I_A] = hpm->adc.Data[ADC_CHANNEL_IA];
meas->Ireal[I_B] = -meas->Ireal[I_A] - meas->Ireal[I_C];
meas->T[TEMP_1] = hpm->adc.Data[ADC_CHANNEL_TEMP1];
meas->T[TEMP_2] = hpm->adc.Data[ADC_CHANNEL_TEMP2];
hpm->T[TEMP_1] = hpm->adc.Data[ADC_CHANNEL_TEMP1];
hpm->T[TEMP_2] = hpm->adc.Data[ADC_CHANNEL_TEMP2];
ZC_ProcessAllChannels(&hpm->zc, hpm->U, usTick);
/* Преобразуем в относительные единицы (о.е.) */
for(int i = 0; i < 3; i++)
{
hpm->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2;
meas->U[i] = 10*meas->Ureal[i]/MB_INTERNAL.param.nominal.U;
meas->I[i] = 10*meas->Ireal[i]/MB_INTERNAL.param.nominal.I;
}
/* Ищем переход через ноль */
ZC_ProcessAllChannels(&hpm->zc, meas->U, usTick);
for(int i = 0; i < 3; i++)
{
meas->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2;
}
/* Накопление Average для медленной фильтрации */
meas->Uslow[U_BA] = Filter_Process(&meas->avg[0], meas->U[U_BA]);
meas->Uslow[U_AC] = Filter_Process(&meas->avg[1], meas->U[U_AC]);
meas->Islow[I_C] = Filter_Process(&meas->avg[2], meas->I[I_C]);
meas->Islow[I_A] = Filter_Process(&meas->avg[3], meas->I[I_A]);
meas->T[TEMP_1] = Filter_Process(&meas->avg[4], meas->T[TEMP_1]);
meas->T[TEMP_2] = Filter_Process(&meas->avg[5], meas->T[TEMP_2]);
/* Запускаем медленную обработку через slow_period прерываний */
// if(hpm->isr_cnt == PM_SLOW_PERIOD_10US)
/* Запускаем медленную когда фильтры среднего зациклились */
if(Filter_isDataReady(&meas->avg[0]))
{
hpm->isr_cnt = 0;
if(!hpm->f.runSlow)
{
hpm->f.runSlow = 1;
}
else // если уже запущена - ставим overrun slow calc
{
errors.prvt.f.err.slow_calc_overrun = 1;
errors.prvt.cnt.slow_calc_overrun++;
}
}
else
{
hpm->isr_cnt++;
}
}

View File

@ -13,14 +13,55 @@
typedef struct
{
ADC_Periodic_t adc;
ZeroCross_Handle_t zc;
UPP_HalfWave_t CurrentHalfWave[3];
unsigned runSlow:1; ///< Запустить медленный алгоритм в while(1)
float U[3];
float F[3];
float I[3];
float T[2];
unsigned isU:1; ///< Есть ли напряжение
unsigned isI:1; ///< Есть ли ток
unsigned protectUmax:1; ///< Отработка защиты по макс. напряжению
unsigned protectUmin:1; ///< Отработка защиты по мак с. напряжению
unsigned protectImax:1; ///< Отработка защиты по макс. току
unsigned protectImin:1; ///< Отработка защиты по мин. току
}PowerMonitor_Flags_t;
typedef struct
{
float U_mean; ///< Среднее Напряжение по трем фазам
float I_mean; ///< Средний Ток по трем фазам
float F_mean; ///< Средняя Частота по трем фазам
float Uslow[3]; ///< Напряжение от АЦП (в о.е.)
float Islow[3]; ///< Ток от АЦП (в о.е.)
float U[3]; ///< Напряжение от АЦП (в о.е.)
float I[3]; ///< Ток от АЦП (в о.е.)
float F[3]; ///< Частота от Zero Cross
float T[2]; ///< Температура от АЦП
float Ureal[3]; ///< Напряжение от АЦП
float Ireal[3]; ///< Ток от АЦП
FilterExp_t exp[3]; ///< Фильтры для mean
FilterAverage_t avg[6]; ///< Фильтры для avg
}PowerMonitor_Measured_t;
typedef struct
{
}PowerMonitor_Filters_t;
typedef struct
{
ADC_Periodic_t adc; ///< Хендл периодического АЦП
ZeroCross_Handle_t zc; ///< Хендл перехода через ноль
PowerMonitor_Filters_t fltr;
PowerMonitor_Measured_t measured; ///< Измеренные/рассчитанные величины
PowerMonitor_Flags_t f; ///< Флаги мониторинга
uint32_t slow_period;
uint32_t isr_cnt;
}PowerMonitor_t;
extern PowerMonitor_t pm;
@ -28,6 +69,7 @@ extern PowerMonitor_t pm;
HAL_StatusTypeDef PowerMonitor_Init(PowerMonitor_t *hpm);
HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm);
void PowerMonitor_SlowHandle(PowerMonitor_t *hpm);
void PowerMonitor_Handle(PowerMonitor_t *hpm);
#endif /* _POWER_MONITOR_H_ */

View File

@ -28,9 +28,9 @@ HAL_StatusTypeDef ZC_Init(ZeroCross_Handle_t *zc, uint8_t num_channels,
memset(zc, 0, sizeof(ZeroCross_Handle_t));
// Установка параметров хендла
zc->NumChannels = num_channels;
zc->Hysteresis = hysteresis;
zc->DebounceSamples = debounce_samples;
zc->Config.NumChannels = num_channels;
zc->Config.Hysteresis = hysteresis;
zc->Config.DebounceSamples = debounce_samples;
// Инициализация каналов
for (int i = 0; i < num_channels; i++) {
@ -63,7 +63,7 @@ HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel,
if (assert_upp(zc)){
return HAL_ERROR;
}
if (channel >= zc->NumChannels) {
if (channel >= zc->Config.NumChannels) {
return HAL_ERROR;
}
@ -94,7 +94,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
if (!zc->f.Monitoring) {
return;
}
if (channel >= zc->NumChannels) {
if (channel >= zc->Config.NumChannels) {
return;
}
int zc_detected = 0;
@ -111,16 +111,16 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
}
// Детектирование rising edge (отрицательное -> положительное)
if ((zc_ch->LastValue <= -zc->Hysteresis) &&
(value >= zc->Hysteresis))
if ((zc_ch->LastValue <= -zc->Config.Hysteresis) &&
(value >= zc->Config.Hysteresis))
{
if (zc_ch->EdgeType == ZC_RISING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) {
if(zc->DebounceSamples)
if(zc->Config.DebounceSamples)
{
if(zc_ch->DebounceCounter == 0)
{
zc_ch->DebounceCounter = zc->DebounceSamples;
zc_ch->DebounceCounter = zc->Config.DebounceSamples;
}
}
@ -128,16 +128,16 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
}
}
// Детектирование falling edge (положительное -> отрицательное)
else if ((zc_ch->LastValue >= zc->Hysteresis) &&
(value <= -zc->Hysteresis))
else if ((zc_ch->LastValue >= zc->Config.Hysteresis) &&
(value <= -zc->Config.Hysteresis))
{
if (zc_ch->EdgeType == ZC_FALLING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) {
if(zc->DebounceSamples)
if(zc->Config.DebounceSamples)
{
if(zc_ch->DebounceCounter == 0)
{
zc_ch->DebounceCounter = zc->DebounceSamples;
zc_ch->DebounceCounter = zc->Config.DebounceSamples;
}
}
@ -149,7 +149,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
{
zc_ch->HalfWave = zc_detected == 1 ? UPP_WAVE_POSITIVE : UPP_WAVE_NEGATIVE;
zc_ch->Occurred = 1;
uint32_t RealTimeShift = 0;//zc->DebounceSamples*(timestamp - zc->LastTick); // коло-во тиков * период вызова функции
uint32_t RealTimeShift = 0;//zc->Config.DebounceSamples*(timestamp - zc->LastTick); // коло-во тиков * период вызова функции
// Переход подтвержден сразу
uint32_t RealTimestamp = timestamp-RealTimeShift;
@ -166,7 +166,7 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin
}
// Сохраняем текущее значение для следующей итерации в случае если оно не в мертвой зоне
if((value > zc->Hysteresis) || (value < -zc->Hysteresis))
if((value > zc->Config.Hysteresis) || (value < -zc->Config.Hysteresis))
{
zc_ch->LastValue = value;
}
@ -188,7 +188,7 @@ void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float *values, uint32_t times
return;
}
for (int ch = 0; ch < zc->NumChannels; ch++) {
for (int ch = 0; ch < zc->Config.NumChannels; ch++) {
ZC_ProcessChannel(zc, ch, values[ch], timestamp);
}
@ -238,7 +238,7 @@ float ZC_GetFrequency(ZeroCross_Handle_t *zc, uint8_t channel)
if (assert_upp(zc)){
return 0.0f;
}
if (channel >= zc->NumChannels) {
if (channel >= zc->Config.NumChannels) {
return 0.0f;
}
@ -273,7 +273,7 @@ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel)
return;
}
if (channel < zc->NumChannels) {
if (channel < zc->Config.NumChannels) {
zc->Channel[channel].LastValue = 0.0f;
zc->Channel[channel].CurrentValue = 0.0f;
zc->Channel[channel].DebounceCounter = 0;
@ -284,7 +284,7 @@ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel)
}
else {
// Сброс всех каналов
for (int i = 0; i < zc->NumChannels; i++) {
for (int i = 0; i < zc->Config.NumChannels; i++) {
zc->Channel[i].LastValue = 0.0f;
zc->Channel[i].CurrentValue = 0.0f;
zc->Channel[i].DebounceCounter = 0;

View File

@ -100,15 +100,22 @@ typedef struct {
ZC_EdgeType_t EdgeType; ///< Тип детектируемого перехода
} ZC_Channel_t;
/**
* @brief Параметры перехода через ноль
*/
typedef struct {
uint8_t NumChannels; ///< Количество используемых каналов для этого хендла
float Hysteresis; ///< Гистерезис для избежания дребезга
uint16_t DebounceSamples; ///< Количество samples для антидребезга
} ZC_Config_t;
/**
* @brief Хендл детектора нуля
*/
typedef struct {
ZC_Channel_t Channel[ZC_MAX_CHANNELS]; ///< Каналы @ref ZC_Channel_t
uint8_t NumChannels; ///< Количество используемых каналов для этого хендла
float Hysteresis; ///< Гистерезис для избежания дребезга
uint16_t DebounceSamples; ///< Количество samples для антидребезга
ZC_Channel_t Channel[ZC_MAX_CHANNELS]; ///< Каналы @ref ZC_Channel_t
ZC_Config_t Config;
struct {
unsigned Initialized:1; ///< Флаг инициализации
unsigned Monitoring:1; ///< Флаг активности мониторинга

View File

@ -34,7 +34,7 @@
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
__IO uint32_t micros;
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/

View File

@ -246,6 +246,7 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void)
HAL_TIM_IRQHandler(&htim14);
/* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 1 */
#endif
UPP_Tick();
/* USER CODE END TIM8_TRG_COM_TIM14_IRQn 1 */
}

View File

@ -1,7 +1,7 @@
/**
******************************************************************************
* @file pwm_thyristors.c
* @brief Модуль для управления тиристорами
* @file angle_control.c
* @brief Модуль для формирования и отсчитывания угла открытия
******************************************************************************
* @details
******************************************************************************/
@ -10,22 +10,16 @@
/**
* @brief Инициализация ШИМ тиристоров.
* @brief Инициализация таймера для расчета угла открытия.
* @param hangle Указатель на таймер
* @return HAL Status.
*/
HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float AngleMax)
HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle)
{
if(hangle == NULL)
return HAL_ERROR;
if(AngleMax < 0 || AngleMax > 1)
return HAL_ERROR;
if(AngleMin < 0 || AngleMin > 1)
return HAL_ERROR;
hangle->htim = &angletim;
hangle->AngleMax = AngleMax;
hangle->AngleMin = AngleMin;
HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_1);
@ -36,9 +30,65 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float Angle
Angle_Reset(hangle, UPP_PHASE_B);
Angle_Reset(hangle, UPP_PHASE_C);
hangle->f.Initialized = 1;
return HAL_OK;
}
/**
* @brief Инициализация углов открытия.
* @param hangle Указатель на таймер
* @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ
* @param AngleMin Минимально возможный угол открытия
* @param AngleMax Максимально возможный угол открытия
* @return HAL Status.
*/
HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax)
{
if(assert_upp(hangle))
return HAL_ERROR;
if(hangle->f.Running)
return HAL_BUSY;
if(AngleMax < 0 || AngleMax > 1)
return HAL_ERROR;
if(AngleMin < 0 || AngleMin > 1)
return HAL_ERROR;
if(AngleMax > hangle->Config.AngleLimit)
AngleMax = hangle->Config.AngleLimit;
if(AngleMin > hangle->Config.AngleLimit)
AngleMin = hangle->Config.AngleLimit;
if(AngleMin >= AngleMax)
return HAL_ERROR;
hangle->Config.AngleMax = AngleMax;
hangle->Config.AngleMin = AngleMin;
return HAL_OK;
}
/**
* @brief Инициализация предельного угла открытия.
* @param hangle Указатель на таймер
* @param AngleLimit Лимит AngleMax, рассчитывается от параметров ШИМ
* @param AngleMin Минимально возможный угол открытия
* @param AngleMax Максимально возможный угол открытия
* @return HAL Status.
*/
HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float AngleLimit)
{
if(assert_upp(hangle))
return HAL_ERROR;
if(hangle->f.Running)
return HAL_BUSY;
if(AngleLimit < 0 || AngleLimit > 1)
return HAL_ERROR;
hangle->Config.AngleLimit = AngleLimit;
return HAL_OK;
}
/**
* @brief Хендл таймера для рассчета угла открытия.
* @param hangle Указатель на таймер
@ -46,7 +96,7 @@ HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float Angle
*/
UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle)
{
if(hangle == NULL)
if(assert_upp(hangle))
return UPP_PHASE_UNKNOWN;
@ -79,9 +129,9 @@ UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle)
* @param Phase Для какой фазы надо установить угол открытия
* @return HAL Status.
*/
HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float Freq)
HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float PeriodMs)
{
if(hangle == NULL)
if(assert_upp(hangle))
return HAL_ERROR;
// Если канал дурацкий - возвращаем ошибку
@ -89,33 +139,36 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A
{
return HAL_ERROR;
}
if(Angle > hangle->AngleMax)
if(Angle > hangle->Config.AngleMax)
{
Angle = hangle->AngleMax;
Angle = hangle->Config.AngleMax;
}
if(Angle < hangle->AngleMin)
if(Angle < hangle->Config.AngleMin)
{
Angle = hangle->AngleMin;
Angle = hangle->Config.AngleMin;
}
uint32_t timer_ticks = TIM_FreqToTick(Freq/Angle, ANGLE_TIM2_FREQ_MHZ);
uint32_t timer_ticks = TIM_MillisToTick(PeriodMs*Angle, ANGLE_TIM2_FREQ_MHZ);
uint32_t ccr_ticks = __HAL_TIM_GET_COUNTER(hangle->htim) + timer_ticks;
switch(Phase)
{
case UPP_PHASE_A:
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC1);
__HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_1, ccr_ticks);
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC1);
hangle->f.Running++;
break;
case UPP_PHASE_B:
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC2);
__HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_2, ccr_ticks);
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC2);
hangle->f.Running++;
break;
case UPP_PHASE_C:
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC3);
__HAL_TIM_SET_COMPARE(hangle->htim, ANGLE_CHANNEL_3, ccr_ticks);
__HAL_TIM_ENABLE_IT(hangle->htim, TIM_IT_CC3);
hangle->f.Running++;
break;
case UPP_PHASE_UNKNOWN:
@ -136,7 +189,7 @@ HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float A
*/
HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase)
{
if(hangle == NULL)
if(assert_upp(hangle))
return HAL_ERROR;
// Если канал дурацкий - возвращаем ошибку
@ -149,14 +202,20 @@ HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase)
{
case UPP_PHASE_A:
__HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC1);
if(hangle->f.Running)
hangle->f.Running--;
break;
case UPP_PHASE_B:
__HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC2);
if(hangle->f.Running)
hangle->f.Running--;
break;
case UPP_PHASE_C:
__HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC3);
if(hangle->f.Running)
hangle->f.Running--;
break;
case UPP_PHASE_UNKNOWN:

View File

@ -1,27 +1,39 @@
/**
******************************************************************************
* @file pwm_thyristors.h
* @brief Модуль для управления тиристорами (объединённый 6-канальный)
* @file angle_control.h
* @brief Модуль для формирования и отсчитывания угла открытия
******************************************************************************
*/
#ifndef _ANGLE_CONTROL_H_
#define _ANGLE_CONTROL_H_
#include "main.h"
#define ANGLE_TIM2_FREQ_MHZ 90
typedef struct
{
float AngleLimit; ///< Лимит AngleMax, рассчитывается от параметров ШИМ
float AngleMin; ///< Минимально возможный угол открытия
float AngleMax; ///< Максимально возможный угол открытия
}Angle_Config_t;
typedef struct
{
TIM_HandleTypeDef *htim;
Angle_Config_t Config;
float AngleMin;
float AngleMax;
struct {
unsigned Initialized : 1;
unsigned Running : 3; ///< Сколько каналов запущено сейчас
} f;
}Angle_Handle_t;
/* Инициализация Таймера для рассчета угла открытия. */
HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float AngleMax);
HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle);
/* Инициализация углов открытия. */
HAL_StatusTypeDef Angle_SetRange(Angle_Handle_t *hangle, float AngleMin, float AngleMax);
/* Инициализация предельного угла открытия. */
HAL_StatusTypeDef Angle_SetLimit(Angle_Handle_t *hangle, float AngleLimit);
/* Установка угла открытия в таймер. */
HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float Freq);
HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float PeriodMs);
/* Сброс угла открытия у таймера. */
HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase);

View File

@ -9,12 +9,15 @@
#include "angle_control.h"
#include "tim.h"
static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint32_t state);
static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Channel_t *hCh, uint32_t state);
/**
* @brief Инициализация ШИМ тиристоров.
* @param hpwm Указатель на хендл ШИМ тиристоров
* @return HAL Status.
* @details Инициализируется 6 структур на каждый канал ШИМ для тиристора.
* И одна dummy структура для безопасной инициализации неизвестной фазы.
* В конце запускаются все каналы ШИМ (с запрещенным выходом).
*/
HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
{
@ -56,7 +59,7 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
PWM_SetHalfWave(hpwm, UPP_PHASE_B, UPP_WAVE_UNKNOWED);
PWM_SetHalfWave(hpwm, UPP_PHASE_C, UPP_WAVE_UNKNOWED);
PWM_SetFrequency(hpwm, hpwm->Config.Frequency);
PWM_SetConfig(hpwm, MB_INTERNAL.param.pwm.PhaseMask, MB_INTERNAL.param.pwm.Frequency, MB_INTERNAL.param.pwm.PulseNumber);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2);
@ -65,6 +68,7 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
HAL_TIM_PWM_Start(&hpwm2, PWM_CHANNEL_5);
HAL_TIM_PWM_Start(&hpwm2, PWM_CHANNEL_6);
HAL_TIM_Base_Start_IT(&hpwm1);
return HAL_OK;
}
@ -74,35 +78,37 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm)
* @param hpwm Указатель на хендл ШИМ тиристоров
* @param Phase На какой фазе надо запустить ШИМ
* @return HAL Status.
* @details Переводит автомат канала ШИМ в состояние запуска ШИМ.
*/
HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
{
if(assert_upp(hpwm))
return HAL_ERROR;
if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
return HAL_ERROR;
// Если канал дурацкий - возвращаем ошибку
if(Phase >= 3)
{
return HAL_ERROR;
}
if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
return HAL_ERROR;
switch(hpwm->Phase[Phase]->State)
{
// Если мы НЕ в режиме ожидание - ошибка
case PWM_THYR_DISABLED:
case PWM_THYR_TIM_START:
case PWM_THYR_TIM_ACTIVE:
case PWM_THYR_TIM_DONE:
return HAL_BUSY;
case PWM_THYR_DISABLED:
case PWM_THYR_TIM_WAIT_ZERO:
// переходим в состояние старта ШИМ
// Запуск только если таймер в режиме ожидания
case PWM_THYR_TIM_WAIT:
hpwm->Phase[Phase]->State = PWM_THYR_TIM_START;
return HAL_OK;
default:
return HAL_ERROR;;
return HAL_ERROR;
}
return HAL_ERROR;
@ -112,98 +118,155 @@ HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
* @brief Остановить ШИМ.
* @param hpwm Указатель на хендл ШИМ тиристоров
* @param Phase На какой фазе надо остановить ШИМ
* @param force_stop_all Принудительно остановить ВЕСЬ ШИМ
* @return HAL Status.
* @details Переводит автомат канала ШИМ в состояние отключенного ШИМ и
* включает канал в режим форсированного неактивного выхода.
* При передаче 1 в force_stop_all, отключаются все каналы ШИМ и выдается дискрет на запрет ШИМ
*/
HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop)
HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all)
{
if(assert_upp(hpwm))
return HAL_ERROR;
if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
return HAL_ERROR;
// Если канал дурацкий - возвращаем ошибку
if(Phase >= 3)
{
return HAL_ERROR;
}
if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
return HAL_ERROR;
hpwm->Phase[Phase]->State = PWM_THYR_TIM_WAIT_ZERO;
hpwm->Phase[Phase]->State = PWM_THYR_DISABLED;
if(force_stop)
// Если не force_stop_all - сбрасываем только текущий канал
if (!force_stop_all)
{
__PWM_SetOutputState(hpwm, Phase, PWM_DISABLE);
__PWM_SetOutputState(hpwm->Phase[Phase], PWM_DISABLE);
}
// Если force_stop_all - сбрасываем ВСЕ КАНАЛЫ
else {
for(int ch = 0; ch < 6; ch++)
{
__PWM_SetOutputState(&hpwm->AllPhases[ch], PWM_DISABLE);
}
}
return HAL_ERROR;
return HAL_OK;
}
/**
* @brief Хендл ШИМ тиристоров.
* @param hpwm Указатель на хендл ШИМ тиристоров
* @return HAL Status.
* @details Автомат состояний, который определяет поведение каналов ШИМ
*/
HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm)
{
if(assert_upp(hpwm))
return HAL_ERROR;
for(int phase = 0; phase < 3; phase++)
uint8_t phase = 0;
PWM_Channel_t *hPhase = NULL;
for(int ch = 0; ch < 6; ch++)
{
if(!read_bit(hpwm->Config.PhaseMask.all, phase))
hPhase = &hpwm->AllPhases[ch];
if (hPhase->htim == NULL)
continue;
if (hpwm->Phase[phase] == NULL || hpwm->Phase[phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
continue;
switch(hpwm->Phase[phase]->State)
switch (hPhase->State)
{
case PWM_THYR_DISABLED:
__PWM_SetOutputState(hpwm, phase, PWM_DISABLE);
case PWM_THYR_DISABLED: // канал отключен
__PWM_SetOutputState(hPhase, PWM_DISABLE);
break;
case PWM_THYR_TIM_WAIT_ZERO:
__PWM_SetOutputState(hpwm, phase, PWM_DISABLE);
case PWM_THYR_TIM_WAIT: // канал ожидает команды
__PWM_SetOutputState(hPhase, PWM_DISABLE);
break;
case PWM_THYR_TIM_START:
__PWM_SetOutputState(hpwm, phase, PWM_ENABLE);
hpwm->Phase[phase]->PulseCnt = hpwm->Config.PulseNumber;
hpwm->Phase[phase]->State = PWM_THYR_TIM_ACTIVE;
case PWM_THYR_TIM_START: // начать ШИМ (пачка импульсов)
__PWM_SetOutputState(hPhase, PWM_ENABLE);
hPhase->PulseCnt = hpwm->Config.PulseNumber;
hPhase->State = PWM_THYR_TIM_ACTIVE;
hpwm->f.Running++;
break;
case PWM_THYR_TIM_ACTIVE:
hpwm->Phase[phase]->PulseCnt--;
if(hpwm->Phase[phase]->PulseCnt <= 0)
case PWM_THYR_TIM_ACTIVE: // управление пачкой импульсов ШИМ
hPhase->PulseCnt--;
if (hPhase->PulseCnt <= 0)
{
hpwm->Phase[phase]->PulseCnt = 0;
hpwm->Phase[phase]->State = PWM_THYR_TIM_DONE;
hPhase->PulseCnt = 0;
hPhase->State = PWM_THYR_TIM_DONE;
}
break;
case PWM_THYR_TIM_DONE:
hpwm->Phase[phase]->State = PWM_THYR_TIM_WAIT_ZERO;
case PWM_THYR_TIM_DONE: // пачка импульсов отправлена - отключение
hPhase->State = PWM_THYR_TIM_WAIT;
if(hpwm->f.Running)
hpwm->f.Running--;
break;
default:
__PWM_SetOutputState(hpwm, phase, PWM_DISABLE);
default: // чзх
__PWM_SetOutputState(hPhase, PWM_DISABLE);
break;
}
}
return HAL_OK;
}
/**
* @brief Установка параметров ШИМ.
* @param hpwm Указатель на хендл ШИМ тиристоров
* @param Frequency Частота в ГЦ
* @return HAL Status.
*/
HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber)
{
if(assert_upp(hpwm))
return HAL_ERROR;
if(hpwm->f.Running) // Если есть активные каналы - ниче не меняем
return HAL_BUSY;
// Остановка таймера
HAL_TIM_Base_Stop_IT(&hpwm1);
hpwm->Config.PhaseMask.all = PhaseMask;
hpwm->Config.PulseNumber = PulseNumber;
hpwm->Config.Frequency = Frequency;
// Высставление периодов
__HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(Frequency, PWM_TIM1_FREQ_MHZ));
__HAL_TIM_SET_AUTORELOAD(&hpwm2, TIM_FreqToTick(Frequency, PWM_TIM3_FREQ_MHZ));
// Скважности 50/50
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_2, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_3, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_4, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2);
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2);
// Сброс счетчиков таймера и запуск заного
__HAL_TIM_SET_COUNTER(&hpwm1, 0);
__HAL_TIM_SET_COUNTER(&hpwm2, 0);
return HAL_TIM_Base_Start_IT(&hpwm1);
}
/**
* @brief Установка полуволны для слежения.
* @param hpwm Указатель на хендл ШИМ тиристоров
* @param Phase Для какой фазы надо установить полуволну
* @param halfwave Какую полуволну установить
* @return HAL Status.
* @details Меняет указатель канала фазы на канал соответствующей полуволны
*/
HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave)
{
if(assert_upp(hpwm))
return HAL_ERROR;
// Сбрасываем текущий канал
__PWM_SetOutputState(hpwm, Phase, PWM_DISABLE);
PWM_Stop(hpwm, Phase, 0);
// Если канал дурацкий - выставляем заглушку
if(Phase >= 3)
{
@ -213,12 +276,14 @@ HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_Hal
// Выставляем канал
switch(halfwave)
{
case UPP_WAVE_POSITIVE:
case UPP_WAVE_POSITIVE:
hpwm->Phase[Phase] = &hpwm->AllPhases[Phase];
hpwm->Phase[Phase]->State = PWM_THYR_TIM_WAIT;
return HAL_OK;
case UPP_WAVE_NEGATIVE:
hpwm->Phase[Phase] = &hpwm->AllPhases[Phase+3];
hpwm->Phase[Phase]->State = PWM_THYR_TIM_WAIT;
return HAL_OK;
default:
@ -234,70 +299,36 @@ HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_Hal
* @param state Какое состояние установить
* @return HAL Status.
*/
static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint32_t state)
static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Channel_t *hCh, uint32_t state)
{
if(hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
if(hCh == NULL)
return HAL_ERROR;
if (hCh->htim == NULL)
return HAL_ERROR;
uint32_t ch_mode = state;
switch(hpwm->Phase[Phase]->ChMask)
switch(hCh->ChMask)
{
case TIM_CHANNEL_1:
hpwm->Phase[Phase]->htim->Instance->CCMR1 &= ~TIM_OCMODE_PWM2;
hpwm->Phase[Phase]->htim->Instance->CCMR1 |= ch_mode;
hCh->htim->Instance->CCMR1 &= ~TIM_OCMODE_PWM2;
hCh->htim->Instance->CCMR1 |= ch_mode;
break;
case TIM_CHANNEL_2:
hpwm->Phase[Phase]->htim->Instance->CCMR1 &= ~(TIM_OCMODE_PWM2 << 8);
hpwm->Phase[Phase]->htim->Instance->CCMR1 |= (ch_mode << 8);
hCh->htim->Instance->CCMR1 &= ~(TIM_OCMODE_PWM2 << 8);
hCh->htim->Instance->CCMR1 |= (ch_mode << 8);
break;
case TIM_CHANNEL_3:
hpwm->Phase[Phase]->htim->Instance->CCMR2 &= ~TIM_OCMODE_PWM2;
hpwm->Phase[Phase]->htim->Instance->CCMR2 |= ch_mode;
hCh->htim->Instance->CCMR2 &= ~TIM_OCMODE_PWM2;
hCh->htim->Instance->CCMR2 |= ch_mode;
break;
case TIM_CHANNEL_4:
hpwm->Phase[Phase]->htim->Instance->CCMR2 &= ~(TIM_OCMODE_PWM2 << 8);
hpwm->Phase[Phase]->htim->Instance->CCMR2 |= (ch_mode << 8);
hCh->htim->Instance->CCMR2 &= ~(TIM_OCMODE_PWM2 << 8);
hCh->htim->Instance->CCMR2 |= (ch_mode << 8);
break;
default:
break;
}
return HAL_OK;
}
/**
* @brief Установка полуволны для слежения.
* @param hpwm Указатель на хендл ШИМ тиристоров
* @param Phase Для какой фазы надо установить полуволну
* @param halfwave Какую полуволну установить
* @return HAL Status.
*/
UPP_HalfWave_t PWM_GetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase)
{
if(assert_upp(hpwm))
return UPP_WAVE_UNKNOWED;
if (hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN])
return UPP_WAVE_UNKNOWED;
// Если канал дурацкий - возвращаем UNKNOWED
if(Phase >= 3)
{
return UPP_WAVE_UNKNOWED;
}
// Выставляем канал
if(hpwm->Phase[Phase] == &hpwm->AllPhases[Phase])
{
return UPP_WAVE_POSITIVE;
}
else if(hpwm->Phase[Phase] == &hpwm->AllPhases[Phase+3])
{
return UPP_WAVE_NEGATIVE;
}
else
{
return UPP_WAVE_UNKNOWED;
}
}

View File

@ -1,7 +1,7 @@
/**
******************************************************************************
* @file pwm_thyristors.h
* @brief Модуль для управления тиристорами (объединённый 6-канальный)
* @brief Модуль для управления тиристорами
******************************************************************************
*/
#ifndef _PWM_THYRISTORS_H
@ -12,23 +12,11 @@
#define PWM_TIM1_FREQ_MHZ 180
#define PWM_TIM3_FREQ_MHZ 90
#define PWM_ENABLE TIM_OCMODE_PWM1
#define PWM_DISABLE TIM_OCMODE_FORCED_ACTIVE
#define PWM_ENABLE TIM_OCMODE_PWM2
#define PWM_DISABLE TIM_OCMODE_FORCED_INACTIVE
#define PWM_SetFrequency(_hpwm_, _freq_) \
do { _hpwm_->Config.Frequency = _freq_; \
__HAL_TIM_SET_AUTORELOAD(&hpwm1, TIM_FreqToTick(_freq_, PWM_TIM1_FREQ_MHZ)); \
__HAL_TIM_SET_AUTORELOAD(&hpwm2, TIM_FreqToTick(_freq_, PWM_TIM3_FREQ_MHZ)); \
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_2, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_3, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_4, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2); \
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_5, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); \
__HAL_TIM_SET_COMPARE(&hpwm2, PWM_CHANNEL_6, __HAL_TIM_GET_AUTORELOAD(&hpwm2)/2); }while(0);
// Индексы для структур каналов @ref PWM_Handle_t
@ -46,7 +34,7 @@ do { _hpwm_->Config.Frequency = _freq_; \
*/
typedef enum {
PWM_THYR_DISABLED = 0, ///< Канал отключен
PWM_THYR_TIM_WAIT_ZERO, ///< Таймер ждет пересечения нуля
PWM_THYR_TIM_WAIT, ///< Таймер ждет команды
PWM_THYR_TIM_START, ///< Запуск таймера для ШИМ
PWM_THYR_TIM_ACTIVE, ///< Таймер активен и формирует ШИМ
PWM_THYR_TIM_DONE ///< Таймер закончил свою работу в полупериоде
@ -67,7 +55,7 @@ typedef struct {
} PWM_Channel_t;
/**
* @brief Канал PWM (один тиристор)
* @brief Параметры ШИМ
*/
typedef struct {
union
@ -81,7 +69,7 @@ typedef struct {
};
}PhaseMask; ///< Какими каналами управлять
uint8_t PulseNumber; ///< Сколько импульсов отправить в пакете для открытия тиристоров
uint32_t Frequency; ///< Частота импульсов
uint16_t Frequency; ///< Частота импульсов
} PWM_ThyrConfig_t;
/**
@ -93,7 +81,7 @@ typedef struct {
struct {
unsigned Initialized : 1;
unsigned Running : 1; ///< true если оба таймера запущены
unsigned Running : 3; ///< Сколько каналов запущено сейчас
} f;
} PWM_Handle_t;
@ -103,11 +91,11 @@ HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm);
/* Запуск ШИМ. */
HAL_StatusTypeDef PWM_Start(PWM_Handle_t *hpwm, UPP_Phase_t Phase);
/* Остановить ШИМ. */
HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop);
HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop_all);
/* Установка частоты ШИМ. */
HAL_StatusTypeDef PWM_SetConfig(PWM_Handle_t *hpwm, uint8_t PhaseMask, uint16_t Frequency, uint8_t PulseNumber);
/* Установка полуволны для слежения. */
HAL_StatusTypeDef PWM_SetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase, UPP_HalfWave_t halfwave);
/* Установка полуволны для слежения. */
UPP_HalfWave_t PWM_GetHalfWave(PWM_Handle_t *hpwm, UPP_Phase_t Phase);
/* Хендл ШИМ тиристоров. */
HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm);

289
UPP/Core/UPP/upp_control.c Normal file
View File

@ -0,0 +1,289 @@
/**
******************************************************************************
* @file upp_control.c
* @brief Модуль определябщий поведение УПП
******************************************************************************
* @details
******************************************************************************/
#include "upp_main.h" // всё остальное по работе с УПП
static int __CheckSimpleParamF(float *paramDist, uint16_t paramSrc, float Coef);
static int __CheckSimpleParamU32(uint32_t *paramDist, uint16_t paramSrc, float Coef);
static int __CheckSimpleParamU16(uint16_t *paramDist, uint16_t paramSrc);
static int __CheckSimpleParamU8(uint8_t *paramDist, uint16_t paramSrc, float Coef);
static void __AngleSetLimit(void);
/**
* @brief Контроль внутренних параметров УПП.
* @return HAL Status.
*/
void UPP_Control_InternalParams(void)
{
if(upp.call->go) // при запущеном УПП ничего не меняем
return;
// флаги обновились ли конфиги
static int adc_channel_update[ADC_NUMB_OF_REGULAR_CHANNELS] = {0};
static int zc_update = 0;
static int pwm_update = 0;
// временная переменная для параметров каналов АЦП
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;
uint8_t pwm_pulse_num = upp.hpwm.Config.PulseNumber;
// временная переменная для параметров Мониторинга сети
float pm_alpha = upp.pm.measured.exp[0].alpha;
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(__CheckSimpleParamF(&adc_channel_max[i], MB_INTERNAL.param.adc.ADC_Max[i], 10))
{
adc_channel_update[i] = 1;
}
// Значение АЦП при нулевом входе
if(__CheckSimpleParamU16(&adc_channel_zero[i], MB_INTERNAL.param.adc.ADC_Zero[i]))
{
adc_channel_update[i] = 1;
}
}
// Параметры алгоритма перехода через ноль
if(__CheckSimpleParamF(&zc_hysteresis, MB_INTERNAL.param.zc.Hysteresis, 10000))
{
zc_update = 1;
}
if(__CheckSimpleParamU16(&zc_debounce, MB_INTERNAL.param.zc.DebouneCouner))
{
zc_update = 1;
}
// Параметры ШИМ токов
if(__CheckSimpleParamU8(&pwm_phase_mask, MB_INTERNAL.param.pwm.PhaseMask, 1))
{
pwm_update = 1;
}
if(__CheckSimpleParamU16(&pwm_freq, MB_INTERNAL.param.pwm.Frequency))
{
pwm_update = 1;
}
if(__CheckSimpleParamU8(&pwm_pulse_num, MB_INTERNAL.param.pwm.PulseNumber, 1))
{
pwm_update = 1;
}
// Параметры мониторинга
if(__CheckSimpleParamF(&pm_alpha, MB_INTERNAL.param.pm.mean_alpha, 65535))
{
for(int i = 0; i < 3; i++)
{
Filter_ReInit(&upp.pm.measured.exp[i], pm_alpha);
}
}
// Обновление АЦП конфигов
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
errors.prvt.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
errors.prvt.cnt.zc_reinit_err++;
}
// Обновление ШИМ конфигов
if(pwm_update)
{
if(PWM_SetConfig(&upp.hpwm, pwm_phase_mask, pwm_freq, pwm_pulse_num) == HAL_OK)
{
pwm_update = 0;
__AngleSetLimit();
}
else
errors.prvt.cnt.pwm_reinit_err++;
}
if (upp.hangle.Config.AngleLimit == 0)
{
__AngleSetLimit();
}
}
/**
* @brief Установка параметров на дефолтные значения @ref UPP_DEFAULT_PARAMS.
* @param pui_default Сбросить параметры ПУИ
* @param internal_default Сбросить внутренние параметры
* @return HAL Status.
*/
void UPP_SetDefault(int pui_default, int internal_default)
{
if(pui_default)
{
MB_DATA.HoldRegs.pui_params.Iref = PUI_Iref_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.Tnt = PUI_Tnt_MS_DEFAULT;
MB_DATA.HoldRegs.pui_params.Umin = PUI_Umin_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.Umax = PUI_Umax_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.Imax = PUI_Imax_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.Imin = PUI_Imin_PERCENT_DEFAULT;
MB_DATA.HoldRegs.pui_params.TiMax = PUI_TiMax_US_DEFAULT;
MB_DATA.HoldRegs.pui_params.Tdelay = PUI_Tdelay_SECONDS_DEFAULT;
MB_DATA.HoldRegs.pui_params.Interlace = PUI_Interlace_EN_DEFAULT;
}
if(internal_default)
{
MB_INTERNAL.param.nominal.PhaseNumber = NOM_PHASE_NUMB;
MB_INTERNAL.param.nominal.U = NOM_U_V_DEFAULT*10;
MB_INTERNAL.param.nominal.U_deviation_plus = NOM_U_DEVIATION_PLUS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.nominal.U_deviation_minus = NOM_U_DEVIATION_MINUS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.nominal.F = NOM_F_HZ_DEFAULT*100;
MB_INTERNAL.param.nominal.F_deviation_plus = NOM_F_DEVIATION_PLUS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.nominal.F_deviation_minus = NOM_F_DEVIATION_MINUS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.nominal.I = NOM_I_A_DEFAULT*10;
MB_INTERNAL.param.pm.mean_alpha = PM_EXP_ALPHA_COEF_DEFAULT*65535;
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UBA] = ADC_U_MAX_V_DEFAULT*10;
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_UAC] = ADC_U_MAX_V_DEFAULT*10;
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IC] = ADC_I_MAX_A_DEFAULT*10;
MB_INTERNAL.param.adc.ADC_Max[ADC_CHANNEL_IA] = ADC_I_MAX_A_DEFAULT*10;
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UBA] = ADC_U_ZERO_DEFAULT;
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_UAC] = ADC_U_ZERO_DEFAULT;
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IC] = ADC_I_ZERO_DEFAULT;
MB_INTERNAL.param.adc.ADC_Zero[ADC_CHANNEL_IA] = ADC_I_ZERO_DEFAULT;
MB_INTERNAL.param.pwm.PhaseMask = 0x7; // (все три фазы)
MB_INTERNAL.param.pwm.Frequency = (float)PWM_THYR_FREQUENCY_HZ_DEFAULT;
MB_INTERNAL.param.pwm.PulseNumber = PWM_THYR_PULSE_NUMBER_DEFAULT;
MB_INTERNAL.param.zc.Hysteresis = ZERO_CROSS_HYSTERESIS_PERCENT_DEFAULT*100;
MB_INTERNAL.param.zc.DebouneCouner = ZERO_CROSS_DEBOUNCE_10US_DEFAULT;
//__AngleSetLimit();
}
}
static void __AngleSetLimit(void)
{
// Перерасчет максимально допустимого угла
float pulses_percent_of_period = ((MB_INTERNAL.param.pwm.PulseNumber / MB_INTERNAL.param.pwm.Frequency) * 1000) / ANGLE_PERIOD_MS(NOM_F_HZ_DEFAULT);
float angle_limit = 1 - pulses_percent_of_period;
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 __CheckSimpleParamF(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 __CheckSimpleParamU32(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 __CheckSimpleParamU16(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 __CheckSimpleParamU8(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;
}
}

View File

@ -0,0 +1,85 @@
/**
******************************************************************************
* @file upp_control.h
* @brief Модуль определябщий поведение УПП
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_CONTROL_H
#define _UPP_CONTROL_H
#include "upp_defs.h"
typedef struct
{
unsigned set_default_pui:1; ///< Выставить настройки ПУИ в дефолтные
unsigned set_default_internal:1;///< Выставить внутренние настройки в дефолтные
unsigned go:1; ///< Запустить УПП
unsigned stop:1; ///< Выставить внутренние настройки в дефолтные
unsigned reserved:11;
unsigned reset_mcu:1;
}UPP_FuncCalls_t;
typedef struct
{
struct
{
uint16_t mean_alpha; ///< Коэф альфа x10000 для эксп. фильтра Umean, Imean, Fmean
}pm;
struct
{
uint16_t PhaseNumber; ///< Количество
uint16_t U; ///< В x 10
uint16_t U_deviation_plus; ///< Проценты x 100
uint16_t U_deviation_minus; ///< Проценты x 100
uint16_t F; ///< Гц x 100
uint16_t F_deviation_plus; ///< Проценты x 100
uint16_t F_deviation_minus; ///< Проценты x 100
uint16_t I; ///< Амперы x 10
}nominal;
/* Параметры АЦП */
struct
{
uint16_t ADC_Max[4]; ///< В x 10
uint16_t ADC_Zero[4]; ///< Кванты АЦП
}adc;
/* Параметры ШИМ */
struct
{
uint16_t PhaseMask; ///< Битовяя маска на какие фазы подавать ШИМ: 0 бит - a, 1 бит - b, 2 бит - c
uint16_t Frequency; ///< Частота ШИМ для пачки импульсов на тиристоры
uint16_t PulseNumber; ///< Количесво импульсов в пачке
}pwm;
/* Параметры Угла */
struct
{
uint16_t Hysteresis; ///< Гистерезис для определения перехода через ноль
uint16_t DebouneCouner; ///< Защита от дребезга: через сколько тактов снова начать фиксировать переход через ноль
}zc;
/* Параметры Угла */
struct
{
uint16_t Angle_Max; ///< Максимальный угол открытия тиристора
uint16_t Angle_Min; ///< Минимальный угол открытия тиристора
}angle;
}UPP_PrvtParams_t;
/* Контроль внутренних параметров УПП. */
void UPP_Control_InternalParams(void);
/* Установка параметров на дефолтные значения */
void UPP_SetDefault(int pui_default, int internal_default);
#endif //_UPP_CONTROL_H

44
UPP/Core/UPP/upp_errors.c Normal file
View File

@ -0,0 +1,44 @@
/**
******************************************************************************
* @file upp_errors.c
* @brief Ошибки УПП и их обработка
******************************************************************************
* @details
******************************************************************************/
#include "upp_errors.h" // всё остальное по работе с УПП
UPP_Errors_t errors;
static UPP_ErrorType_t UPP_SelectCommonError(void)
{
// Пока нет ошибки
UPP_ErrorType_t best = Err_None;
// Приоритет отсутствия ошибок
uint8_t best_prio = UPP_ErrorPriority[Err_None];
// Перебираем все возможные ошибки по enum
for (int e = Err_None + 1; e <= Err_UnderFrequency; e++)
{
// Проверяем: установлен ли соответствующий бит в pui.all
// e-1, потому что ошибка №1 = бит 0, ошибка №2 = бит 1 и т.д.
if (errors.pui.all & (1u << (e - 1)))
{
// Получаем приоритет этой ошибки
uint8_t pr = UPP_ErrorPriority[e];
// Если её приоритет лучше (меньше число) — запоминаем
if (pr < best_prio)
{
best_prio = pr;
best = (UPP_ErrorType_t)e;
}
}
}
// Возвращаем самую важную (наивысшего приоритета) ошибку
return best;
}
void UPP_ErrorsHandle(void)
{
errors.common = UPP_SelectCommonError();
}

125
UPP/Core/UPP/upp_errors.h Normal file
View File

@ -0,0 +1,125 @@
/**
******************************************************************************
* @file upp_errors.h
* @brief Ошибки УПП и их обработка
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_ERRORS_H
#define _UPP_ERRORS_H
#include "upp_defs.h"
/**
* @brief Приоритет ПУИ ошибок
*/
static const uint8_t UPP_ErrorPriority[] =
{
[Err_None] = 255,
/* Фатальные ошибки */
[Err_LossPhaseAll] = 1,
[Err_OverCurrent] = 2,
[Err_OverVoltage] = 3,
[Err_OverTemperature] = 4,
[Err_Power_24V] = 5,
[Err_Power_Digit_5V] = 6,
[Err_Power_DIO_24V] = 7,
[Err_Power_Analog_5V] = 8,
/* Критичные */
[Err_LossPhaseA] = 10,
[Err_LossPhaseB] = 11,
[Err_LossPhaseC] = 12,
[Err_LongStart] = 13,
[Err_Interlace] = 14,
/* Пограничные параметры */
[Err_UnderVoltage] = 20,
[Err_OverFrequency] = 21,
[Err_UnderFrequency] = 22,
/* Внутренние */
[Err_Internal_1] = 40,
[Err_Internal_2] = 41,
[Err_Internal_3] = 42,
[Err_Internal_4] = 43,
[Err_Internal_5] = 44,
[Err_Internal_6] = 45,
};
/**
* @brief Структура с всеми ошибками УПП
*/
typedef struct
{
UPP_ErrorType_t common; ///< Общая ошибка @ref UPP_ErrorType_t;
union
{
uint32_t all;
struct
{
/* Програмные ошибки */
unsigned Internal_1:1; ///< Внутренняя неисправность УПП 1
unsigned Internal_2:1; ///< Внутренняя неисправность УПП 2
unsigned Internal_3:1; ///< Внутренняя неисправность УПП 3
unsigned Internal_4:1; ///< Внутренняя неисправность УПП 4
unsigned Internal_5:1; ///< Внутренняя неисправность УПП 5
unsigned Internal_6:1; ///< Внутренняя неисправность УПП 6
/* Ошибки по питанию */
unsigned Power_Digit_5V:1; ///< Неисправность цифрового источника питания (5 В)
unsigned Power_24V:1; ///< Неисправность источника питания 24 В
unsigned Power_Analog_5V:1; ///< Неисправность аналогового источника питания микроконтроллера (± 5 В)
unsigned Power_SCI_5V:1; ///< Неисправность источника питания последовательных интерфейсов микроконтроллера (5 В)
unsigned Power_DIO_24V:1; ///< Неисправность источника питания дискретных входов/выходов (24 В)
/* Ошибки по допустимым пределам Наряжений/Токов/Температуры */
unsigned OverCurrent:1; ///< Ток выше допустимого (см. Imax и TiMax в @ref UPP_PUI_Params_t)
unsigned OverVoltage:1; ///< Напряжение сети выше допустимого (см. Umах в @ref UPP_PUI_Params_t)
unsigned OverTemperature:1; ///< Температура выше допустимой (плюс 85 °C)
unsigned UnderVoltage:1; ///< Напряжение сети ниже допустимого (см. Umin в @ref UPP_PUI_Params_t)
/* Ошибки по обрывам фаз */
unsigned LossPhaseA:1; ///< Обрыв фазы A (см. Imin в @ref UPP_PUI_Params_t)
unsigned LossPhaseB:1; ///< Обрыв фазы B (см. Imin в @ref UPP_PUI_Params_t)
unsigned LossPhaseC:1; ///< Обрыв фазы C (см. Imin в @ref UPP_PUI_Params_t)
/* Другие ошибки */
unsigned LongStart:1; ///< Затянутый пуск (ток не спадает за установленное время) (см. Tdelay в @ref UPP_PUI_Params_t)
unsigned Interlace:1; ///< Неправильный порядок чередования фаз (см. Interlace в @ref UPP_PUI_Params_t)
unsigned OverFrequency:1; ///< Частота сети выше допустимой
unsigned UnderFrequency:1; ///< Частота сети ниже допустимой
}err;
}pui;
struct
{
union
{
uint64_t all;
struct
{
unsigned slow_calc_overrun:1;
}err;
}f;
struct
{
uint16_t adc_reinit_err;
uint16_t zc_reinit_err;
uint16_t pwm_reinit_err;
uint16_t slow_calc_overrun;
}cnt;
}prvt; ///< Приватные ошибки, не идущие напрямую в ПУИ
}UPP_Errors_t;
extern UPP_Errors_t errors;
void UPP_ErrorsHandle(void);
#endif //_UPP_ERRORS_H

View File

@ -6,6 +6,8 @@
* @details
******************************************************************************/
#include "upp_main.h" // всё остальное по работе с УПП
#include "tim.h"
UPP_t upp;
float alpha_dbg = 0.5;
// ОСНОВНОЙ ЦИКЛ main.c
@ -16,12 +18,19 @@ float alpha_dbg = 0.5;
*/
int UPP_Init(void)
{
BenchTime_Init();
// Подключение указателей
upp.errors = &errors;
upp.PUI.params = &MB_DATA.HoldRegs.pui_params;
upp.PUI.values = &MB_DATA.InRegs.pui;
upp.call = &MB_INTERNAL.FuncCalls;
HAL_TIM_Base_Start(&ustim);
PowerMonitor_Init(&upp.pm);
upp.hpwm.Config.Frequency = 20000;
upp.hpwm.Config.PulseNumber = 20;
PWM_Init(&upp.hpwm);
Angle_Init(&upp.hangle, 0, 0.8);
Angle_Init(&upp.hangle);
upp.workmode = WM_Ready;
return 0;
}
@ -31,8 +40,9 @@ int UPP_Init(void)
*/
int UPP_PreWhile(void)
{
UPP_Control_InternalParams();
Angle_SetRange(&upp.hangle, 0.0, 0.8);
PowerMonitor_Start(&upp.pm);
upp.hpwm.Config.PhaseMask.all = 0x7;
return 0;
}
@ -41,15 +51,98 @@ int UPP_PreWhile(void)
* @return 0 - если ОК, >1 если ошибка.
*/
int UPP_While(void)
{
{
// если ошибка вызываем СТОП
if(errors.pui.all)
{
upp.call->stop = 1;
}
// иначе снимаем СТОП
else
{
upp.call->stop = 0;
}
// Сброс на дефолтные по запросу
if(upp.call->set_default_pui)
{
UPP_SetDefault(1, 0);
}
if(upp.call->set_default_internal)
{
UPP_SetDefault(0, 1);
}
PowerMonitor_SlowHandle(&upp.pm);
// Если СТОП - переходим в ошибку
if (upp.call->stop)
upp.workmode = WM_Error;
// Автомат состояний УПП
switch(upp.workmode)
{
case WM_Ready:
// если пришла команда на запуск
if (upp.call->go)
{
upp.workmode = WM_Running;
upp.StartTick = local_time();
}
break;
case WM_Running:
// если пришла команда на остановку
if (!upp.call->go)
upp.workmode = WM_Ready;
// если слишком долгий запуск
if((local_time() - upp.StartTick) > (upp.PUI.params->Tdelay*1000))
{
errors.pui.err.LongStart = 1;
}
break;
case WM_Error:
if(errors.common == Err_None)
upp.workmode = WM_Ready;
PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ
break;
case WM_Done:
PWM_Stop(&upp.hpwm, 0, 1); // Останавливаем ВЕСЬ ШИМ
break;
default:
break;
}
return 0;
}
/**
* @brief Всякое что будет делатся каждую 1 мс.
*/
void UPP_Tick(void)
{
if(upp.workmode == WM_Not_Init)
return;
UPP_ErrorsHandle();
UPP_Control_InternalParams();
}
// ПРЕРЫВАНИЯ stm32f4xx_it.c
void UPP_ADC_Handle(void)
{
BenchTime_Start(BT_ADC, angletim.Instance->CNT, HAL_MAX_DELAY);
PowerMonitor_Handle(&upp.pm);
for(int phase = 0; phase < 3; phase++)
@ -57,41 +150,59 @@ void UPP_ADC_Handle(void)
// Если произошел Zero Cross
if(ZC_isOccurred(&upp.pm.zc, phase))
{
// Меняем полуволну тиристора
UPP_HalfWave_t curr_halfwave = ZC_GetHalfWave(&upp.pm.zc, phase);
PWM_SetHalfWave(&upp.hpwm, phase, curr_halfwave);
Angle_Start(&upp.hangle, phase, alpha_dbg, upp.hpwm.Config.Frequency);
// Если УПП в работе
if(upp.workmode == WM_Running)
{
// Меняем полуволну тиристора
UPP_HalfWave_t curr_halfwave = ZC_GetHalfWave(&upp.pm.zc, phase);
PWM_SetHalfWave(&upp.hpwm, phase, curr_halfwave);
// Начинаем отсчитывать угол
Angle_Start(&upp.hangle, phase, alpha_dbg, 10);
}
}
}
// Проверяем на ошибки
upp.Timings.isr_adc = BenchTime_End(BT_ADC, angletim.Instance->CNT);
}
void UPP_PWM_Handle(void)
{
BenchTime_Start(BT_PWM, angletim.Instance->CNT, HAL_MAX_DELAY);
PWM_Handle(&upp.hpwm);
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim)
{
if (htim == upp.hangle.htim)
{
UPP_Angle_Handle();
}
upp.Timings.isr_pwm = BenchTime_End(BT_PWM, angletim.Instance->CNT);
}
void UPP_Angle_Handle(void)
{
UPP_Phase_t phase = Angle_Handle(&upp.hangle);
switch(phase)
Angle_Reset(&upp.hangle, phase);
// Если УПП в работе
if(upp.workmode == WM_Running)
{
case UPP_PHASE_A:
PWM_Start(&upp.hpwm, UPP_PHASE_A);
break;
case UPP_PHASE_B:
PWM_Start(&upp.hpwm, UPP_PHASE_B);
break;
case UPP_PHASE_C:
PWM_Start(&upp.hpwm, UPP_PHASE_C);
break;
default:
break;
switch(phase)
{
case UPP_PHASE_A:
PWM_Start(&upp.hpwm, UPP_PHASE_A);
break;
case UPP_PHASE_B:
PWM_Start(&upp.hpwm, UPP_PHASE_B);
break;
case UPP_PHASE_C:
PWM_Start(&upp.hpwm, UPP_PHASE_C);
break;
default:
break;
}
}
}
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim)
{
if (htim == upp.hangle.htim)
{
BenchTime_Start(BT_SYSTICK, angletim.Instance->CNT, HAL_MAX_DELAY);
UPP_Angle_Handle();
upp.Timings.isr_systick = BenchTime_End(BT_SYSTICK, angletim.Instance->CNT);
}
}

View File

@ -1,6 +1,6 @@
/**
******************************************************************************
* @file modbus_data.h
* @file upp_main.h
* @brief Определения структур данных Modbus устройства
******************************************************************************
* @details
@ -9,19 +9,42 @@
#ifndef _UPP_MAIN_H
#define _UPP_MAIN_H
#include "main.h" // либы из AllLibs и вербальные имена из CubeMX
#include "upp_config.h"
#include "main.h" // общие библиотеки, конфигурации и вербальные имена из CubeMX
#include "power_monitor.h" // статистика сети и АЦП
#include "pwm_thyristors.h" // Управление тиристорами
#include "angle_control.h" // Управление углом открытия
#include "upp_status.h" // статус упп
#include "upp_control.h" // управление упп
extern float alpha_dbg;
typedef struct
{
PowerMonitor_t pm;
PWM_Handle_t hpwm;
Angle_Handle_t hangle;
UPP_WorkModeType_t workmode; ///< Режим УПП
UPP_FuncCalls_t *call; ///< Вызов функций УПП
PowerMonitor_t pm; ///< Мониторинг сети
PWM_Handle_t hpwm; ///< Хендл ШИМ тиристоров
Angle_Handle_t hangle; ///< Хендл отсчитывания угла открытия
struct
{
UPP_PUI_Params_t *params; ///< Параметры от ПУИ
UPP_PUI_Values_t *values; ///< Данные для ПУИ
} PUI; ///< Общение с ПУИ
UPP_Errors_t *errors; ///< Ошибки УПП
uint32_t StartTick;
struct
{
uint32_t isr_adc;
uint32_t isr_pwm;
uint32_t isr_systick;
}Timings;
}UPP_t;
extern UPP_t upp;
@ -32,7 +55,10 @@ int UPP_Init(void);
int UPP_PreWhile(void);
/* Основной цикл УПП. */
int UPP_While(void);
/* Всякое что будет делатся каждую 1 мс. */
void UPP_Tick(void);
// Прерывания
void UPP_ADC_Handle(void);
void UPP_PWM_Handle(void);
void UPP_Angle_Handle(void);

12
UPP/Core/UPP/upp_status.c Normal file
View File

@ -0,0 +1,12 @@
/**
******************************************************************************
* @file upp_status.c
* @brief Модуль определяющий состояние УПП
******************************************************************************
* @details
******************************************************************************/
#include "upp_main.h" // всё остальное по работе с УПП
void UPP_Status_Handler(void)
{
}

13
UPP/Core/UPP/upp_status.h Normal file
View File

@ -0,0 +1,13 @@
/**
******************************************************************************
* @file upp_status.h
* @brief Модуль определяющий состояние УПП
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_STATUS_H
#define _UPP_STATUS_H
#endif //_UPP_STATUS_H

View File

@ -206,6 +206,18 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\Configs\upp_defs.h</PathWithFileName>
<FilenameWithoutPath>upp_defs.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>3</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\Inc\main.h</PathWithFileName>
<FilenameWithoutPath>main.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
@ -213,7 +225,7 @@
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>3</FileNumber>
<FileNumber>4</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -225,7 +237,7 @@
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>4</FileNumber>
<FileNumber>5</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -237,7 +249,7 @@
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>5</FileNumber>
<FileNumber>6</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -249,7 +261,7 @@
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>6</FileNumber>
<FileNumber>7</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -261,7 +273,7 @@
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>7</FileNumber>
<FileNumber>8</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -273,7 +285,7 @@
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>8</FileNumber>
<FileNumber>9</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -285,7 +297,7 @@
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>9</FileNumber>
<FileNumber>10</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -305,7 +317,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>10</FileNumber>
<FileNumber>11</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -317,7 +329,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>11</FileNumber>
<FileNumber>12</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -329,7 +341,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>12</FileNumber>
<FileNumber>13</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -341,7 +353,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>13</FileNumber>
<FileNumber>14</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -353,7 +365,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>14</FileNumber>
<FileNumber>15</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -365,7 +377,7 @@
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>15</FileNumber>
<FileNumber>16</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -375,6 +387,78 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>17</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_control.c</PathWithFileName>
<FilenameWithoutPath>upp_control.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>18</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_control.h</PathWithFileName>
<FilenameWithoutPath>upp_control.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_status.c</PathWithFileName>
<FilenameWithoutPath>upp_status.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>20</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_status.h</PathWithFileName>
<FilenameWithoutPath>upp_status.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>21</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_errors.c</PathWithFileName>
<FilenameWithoutPath>upp_errors.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>22</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_errors.h</PathWithFileName>
<FilenameWithoutPath>upp_errors.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
@ -385,7 +469,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>16</FileNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -397,7 +481,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>17</FileNumber>
<FileNumber>24</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -409,7 +493,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>18</FileNumber>
<FileNumber>25</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -421,7 +505,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>19</FileNumber>
<FileNumber>26</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -433,7 +517,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>20</FileNumber>
<FileNumber>27</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -445,7 +529,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>21</FileNumber>
<FileNumber>28</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -465,7 +549,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>22</FileNumber>
<FileNumber>29</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -477,7 +561,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>23</FileNumber>
<FileNumber>30</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -489,7 +573,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>24</FileNumber>
<FileNumber>31</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -501,7 +585,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>25</FileNumber>
<FileNumber>32</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -513,7 +597,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>26</FileNumber>
<FileNumber>33</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -525,7 +609,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>27</FileNumber>
<FileNumber>34</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -537,7 +621,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>28</FileNumber>
<FileNumber>35</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -549,7 +633,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>29</FileNumber>
<FileNumber>36</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -561,7 +645,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>30</FileNumber>
<FileNumber>37</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -573,7 +657,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>31</FileNumber>
<FileNumber>38</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -585,7 +669,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>32</FileNumber>
<FileNumber>39</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -597,7 +681,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>33</FileNumber>
<FileNumber>40</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -609,7 +693,7 @@
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>34</FileNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -629,7 +713,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>35</FileNumber>
<FileNumber>42</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -641,7 +725,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>36</FileNumber>
<FileNumber>43</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -653,7 +737,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>37</FileNumber>
<FileNumber>44</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -665,7 +749,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>38</FileNumber>
<FileNumber>45</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -677,7 +761,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>39</FileNumber>
<FileNumber>46</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -689,7 +773,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>40</FileNumber>
<FileNumber>47</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -701,7 +785,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>41</FileNumber>
<FileNumber>48</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -713,7 +797,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>42</FileNumber>
<FileNumber>49</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -733,7 +817,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>43</FileNumber>
<FileNumber>50</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -745,7 +829,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>44</FileNumber>
<FileNumber>51</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -757,7 +841,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>45</FileNumber>
<FileNumber>52</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -769,7 +853,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>46</FileNumber>
<FileNumber>53</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -781,7 +865,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>47</FileNumber>
<FileNumber>54</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -793,7 +877,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>48</FileNumber>
<FileNumber>55</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -805,7 +889,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>49</FileNumber>
<FileNumber>56</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -817,7 +901,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>50</FileNumber>
<FileNumber>57</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -829,7 +913,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>51</FileNumber>
<FileNumber>58</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -841,7 +925,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>52</FileNumber>
<FileNumber>59</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -853,7 +937,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>53</FileNumber>
<FileNumber>60</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -865,7 +949,7 @@
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>54</FileNumber>
<FileNumber>61</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -885,7 +969,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>55</FileNumber>
<FileNumber>62</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -897,7 +981,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>56</FileNumber>
<FileNumber>63</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -917,7 +1001,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>57</FileNumber>
<FileNumber>64</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -929,7 +1013,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>58</FileNumber>
<FileNumber>65</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -941,7 +1025,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>59</FileNumber>
<FileNumber>66</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -953,7 +1037,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>60</FileNumber>
<FileNumber>67</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -965,7 +1049,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>61</FileNumber>
<FileNumber>68</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -985,7 +1069,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>62</FileNumber>
<FileNumber>69</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -997,7 +1081,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>63</FileNumber>
<FileNumber>70</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1009,7 +1093,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>64</FileNumber>
<FileNumber>71</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1021,7 +1105,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>65</FileNumber>
<FileNumber>72</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1033,7 +1117,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>66</FileNumber>
<FileNumber>73</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1045,7 +1129,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>67</FileNumber>
<FileNumber>74</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1057,7 +1141,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>68</FileNumber>
<FileNumber>75</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1069,7 +1153,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>69</FileNumber>
<FileNumber>76</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1081,7 +1165,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>70</FileNumber>
<FileNumber>77</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1093,7 +1177,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>71</FileNumber>
<FileNumber>78</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1105,7 +1189,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>72</FileNumber>
<FileNumber>79</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1117,7 +1201,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>73</FileNumber>
<FileNumber>80</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1129,7 +1213,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>74</FileNumber>
<FileNumber>81</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1141,7 +1225,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>75</FileNumber>
<FileNumber>82</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1153,7 +1237,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>76</FileNumber>
<FileNumber>83</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1165,7 +1249,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>77</FileNumber>
<FileNumber>84</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1177,7 +1261,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>78</FileNumber>
<FileNumber>85</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1189,7 +1273,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>79</FileNumber>
<FileNumber>86</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1201,7 +1285,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>80</FileNumber>
<FileNumber>87</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1213,7 +1297,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>81</FileNumber>
<FileNumber>88</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1225,7 +1309,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>82</FileNumber>
<FileNumber>89</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1237,7 +1321,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>83</FileNumber>
<FileNumber>90</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1249,7 +1333,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>84</FileNumber>
<FileNumber>91</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1261,7 +1345,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>85</FileNumber>
<FileNumber>92</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1281,7 +1365,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>10</GroupNumber>
<FileNumber>86</FileNumber>
<FileNumber>93</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1301,7 +1385,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>11</GroupNumber>
<FileNumber>87</FileNumber>
<FileNumber>94</FileNumber>
<FileType>2</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>

View File

@ -17,8 +17,8 @@
<TargetCommonOption>
<Device>STM32F427ZGTx</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.2.17.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<PackID>Keil.STM32F4xx_DFP.2.16.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>
@ -390,6 +390,11 @@
<FileType>5</FileType>
<FilePath>..\Core\Configs\upp_config.h</FilePath>
</File>
<File>
<FileName>upp_defs.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\Configs\upp_defs.h</FilePath>
</File>
<File>
<FileName>main.h</FileName>
<FileType>5</FileType>
@ -465,6 +470,36 @@
<FileType>5</FileType>
<FilePath>..\Core\UPP\angle_control.h</FilePath>
</File>
<File>
<FileName>upp_control.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\UPP\upp_control.c</FilePath>
</File>
<File>
<FileName>upp_control.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\UPP\upp_control.h</FilePath>
</File>
<File>
<FileName>upp_status.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\UPP\upp_status.c</FilePath>
</File>
<File>
<FileName>upp_status.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\UPP\upp_status.h</FilePath>
</File>
<File>
<FileName>upp_errors.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\UPP\upp_errors.c</FilePath>
</File>
<File>
<FileName>upp_errors.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\UPP\upp_errors.h</FilePath>
</File>
</Files>
</Group>
<Group>
@ -529,57 +564,6 @@
<FileName>dma.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/dma.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>iwdg.c</FileName>