diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c index 46b9f21..c8210a1 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c @@ -91,167 +91,215 @@ void Channels_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS) /* Выбор режима CaptureCompare или PWM и симуляция для каждого канала */ void CC_PWM_Ch1_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) { // определяет режим канала -switch (TIMx->CCMR1 & TIM_CCMR1_OC1M) -{ - case (TIM_OCMODE_ACTIVE): // ACTIVE mode - if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step) - TIMS->Channels.OC1REF = 1; - break; + switch (TIMx->CCMR1 & TIM_CCMR1_OC1M) + { + case (TIM_OCMODE_ACTIVE): // ACTIVE mode + if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step) + TIMS->Channels.OC1REF = 1; + break; - case (TIM_OCMODE_INACTIVE): // INACTIVE mode - if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step) - TIMS->Channels.OC1REF = 0; - break; + case (TIM_OCMODE_INACTIVE): // INACTIVE mode + if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step) + TIMS->Channels.OC1REF = 0; + break; - case (TIM_OCMODE_TOGGLE): // TOOGLE mode - if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step) - TIMS->Channels.OC1REF = ~TIMS->Channels.OC1REF; - break; + case (TIM_OCMODE_TOGGLE): // TOOGLE mode + if (abs(TIMx->CNT - TIMx->CCR1) < 2*TIMS->tx_step) + TIMS->Channels.OC1REF = ~TIMS->Channels.OC1REF; + break; - case (TIM_OCMODE_PWM1): // PWM MODE 1 mode - if (TIMx->CNT < TIMx->CCR1) - TIMS->Channels.OC1REF = 1; - else - TIMS->Channels.OC1REF = 0; - break; + case (TIM_OCMODE_PWM1): // PWM MODE 1 mode + if (TIMx->CNT < TIMx->CCR1) + TIMS->Channels.OC1REF = 1; + else + TIMS->Channels.OC1REF = 0; + break; - case (TIM_OCMODE_PWM2): // PWM MODE 2 mode - if (TIMx->CNT < TIMx->CCR1) - TIMS->Channels.OC1REF = 0; - else - TIMS->Channels.OC1REF = 1; - break; + case (TIM_OCMODE_PWM2): // PWM MODE 2 mode + if (TIMx->CNT < TIMx->CCR1) + TIMS->Channels.OC1REF = 0; + else + TIMS->Channels.OC1REF = 1; + break; - case (TIM_OCMODE_FORCED_ACTIVE): // FORCED ACTIVE mode - TIMS->Channels.OC1REF = 1; break; + case (TIM_OCMODE_FORCED_ACTIVE): // FORCED ACTIVE mode + TIMS->Channels.OC1REF = 1; break; - case (TIM_OCMODE_FORCED_INACTIVE): // FORCED INACTIVE mode - TIMS->Channels.OC1REF = 0; break; + case (TIM_OCMODE_FORCED_INACTIVE): // FORCED INACTIVE mode + TIMS->Channels.OC1REF = 0; break; -} + } + 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)) + { + TIM_Call_IRQHandller(TIMx); + } + else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR1) && (TIMS->tx_cnt <= TIMx->CCR1)) + { + TIM_Call_IRQHandller(TIMx); + } + } } void CC_PWM_Ch2_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) { // определяет режим канала -switch (TIMx->CCMR1 & TIM_CCMR1_OC2M) -{ - case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode - if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step) - TIMS->Channels.OC2REF = 1; - break; + switch (TIMx->CCMR1 & TIM_CCMR1_OC2M) + { + case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode + if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step) + TIMS->Channels.OC2REF = 1; + break; - case ((TIM_OCMODE_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // INACTIVE mode - if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step) - TIMS->Channels.OC2REF = 0; - break; + case ((TIM_OCMODE_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // INACTIVE mode + if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step) + TIMS->Channels.OC2REF = 0; + break; - case ((TIM_OCMODE_TOGGLE) << (TIM_OCMODE_SECOND_SHIFT)): // Toogle mode - if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step) - TIMS->Channels.OC2REF = ~TIMS->Channels.OC2REF; - break; + case ((TIM_OCMODE_TOGGLE) << (TIM_OCMODE_SECOND_SHIFT)): // Toogle mode + if (abs(TIMx->CNT - TIMx->CCR2) < 2*TIMS->tx_step) + TIMS->Channels.OC2REF = ~TIMS->Channels.OC2REF; + break; - case ((TIM_OCMODE_PWM1) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 1 mode - if (TIMx->CNT < TIMx->CCR2) - TIMS->Channels.OC2REF = 1; - else - TIMS->Channels.OC2REF = 0; - break; + case ((TIM_OCMODE_PWM1) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 1 mode + if (TIMx->CNT < TIMx->CCR2) + TIMS->Channels.OC2REF = 1; + else + TIMS->Channels.OC2REF = 0; + break; - case ((TIM_OCMODE_PWM2) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 2 mode - if (TIMx->CNT < TIMx->CCR2) - TIMS->Channels.OC2REF = 0; - else - TIMS->Channels.OC2REF = 1; - break; + case ((TIM_OCMODE_PWM2) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 2 mode + if (TIMx->CNT < TIMx->CCR2) + TIMS->Channels.OC2REF = 0; + else + TIMS->Channels.OC2REF = 1; + break; - case ((TIM_OCMODE_FORCED_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED ACTIVE mode - TIMS->Channels.OC2REF = 1; break; + case ((TIM_OCMODE_FORCED_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED ACTIVE mode + TIMS->Channels.OC2REF = 1; break; - case ((TIM_OCMODE_FORCED_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED INACTIVE mode - TIMS->Channels.OC2REF = 0; break; + case ((TIM_OCMODE_FORCED_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED INACTIVE mode + TIMS->Channels.OC2REF = 0; break; -} + } + 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)) + { + TIM_Call_IRQHandller(TIMx); + } + else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR2) && (TIMS->tx_cnt <= TIMx->CCR2)) + { + TIM_Call_IRQHandller(TIMx); + } + } } void CC_PWM_Ch3_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) { // определяет режим канала -switch (TIMx->CCMR2 & TIM_CCMR1_OC1M) -{ - case (TIM_OCMODE_ACTIVE): // ACTIVE mode - if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step) - TIMS->Channels.OC3REF = 1; - break; + switch (TIMx->CCMR2 & TIM_CCMR1_OC1M) + { + case (TIM_OCMODE_ACTIVE): // ACTIVE mode + if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step) + TIMS->Channels.OC3REF = 1; + break; - case (TIM_OCMODE_INACTIVE): // INACTIVE mode - if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step) - TIMS->Channels.OC3REF = 0; - break; + case (TIM_OCMODE_INACTIVE): // INACTIVE mode + if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step) + TIMS->Channels.OC3REF = 0; + break; - case (TIM_OCMODE_TOGGLE): // Toogle mode - if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step) - TIMS->Channels.OC3REF = ~TIMS->Channels.OC3REF; - break; + case (TIM_OCMODE_TOGGLE): // Toogle mode + if (abs(TIMx->CNT - TIMx->CCR3) < 2*TIMS->tx_step) + TIMS->Channels.OC3REF = ~TIMS->Channels.OC3REF; + break; - case (TIM_OCMODE_PWM1): // PWM mode 1 mode - if (TIMx->CNT < TIMx->CCR3) - TIMS->Channels.OC3REF = 1; - else - TIMS->Channels.OC3REF = 0; - break; + case (TIM_OCMODE_PWM1): // PWM mode 1 mode + if (TIMx->CNT < TIMx->CCR3) + TIMS->Channels.OC3REF = 1; + else + TIMS->Channels.OC3REF = 0; + break; - case (TIM_OCMODE_PWM2): // PWM mode 2 mode - if (TIMx->CNT < TIMx->CCR3) - TIMS->Channels.OC3REF = 0; - else - TIMS->Channels.OC3REF = 1; - break; + case (TIM_OCMODE_PWM2): // PWM mode 2 mode + if (TIMx->CNT < TIMx->CCR3) + TIMS->Channels.OC3REF = 0; + else + TIMS->Channels.OC3REF = 1; + break; - case (TIM_OCMODE_FORCED_ACTIVE): // FORCED ACTIVE mode - TIMS->Channels.OC3REF = 1; break; + case (TIM_OCMODE_FORCED_ACTIVE): // FORCED ACTIVE mode + TIMS->Channels.OC3REF = 1; break; - case (TIM_OCMODE_FORCED_INACTIVE): // FORCED INACTIVE mode - TIMS->Channels.OC3REF = 0; break; + case (TIM_OCMODE_FORCED_INACTIVE): // FORCED INACTIVE mode + TIMS->Channels.OC3REF = 0; break; -} + } + 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)) + { + TIM_Call_IRQHandller(TIMx); + } + else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR3) && (TIMS->tx_cnt <= TIMx->CCR3)) + { + TIM_Call_IRQHandller(TIMx); + } + } } void CC_PWM_Ch4_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) { // определяет режим канала -switch (TIMx->CCMR1 & TIM_CCMR1_OC2M) -{ - case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode - if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step) - TIMS->Channels.OC4REF = 1; - break; + switch (TIMx->CCMR1 & TIM_CCMR1_OC2M) + { + case ((TIM_OCMODE_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // ACTIVE mode + if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step) + TIMS->Channels.OC4REF = 1; + break; - case ((TIM_OCMODE_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // INACTIVE mode - if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step) - TIMS->Channels.OC4REF = 0; - break; + case ((TIM_OCMODE_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // INACTIVE mode + if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step) + TIMS->Channels.OC4REF = 0; + break; - case ((TIM_OCMODE_TOGGLE) << (TIM_OCMODE_SECOND_SHIFT)): // Toogle mode - if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step) - TIMS->Channels.OC4REF = ~TIMS->Channels.OC4REF; - break; + case ((TIM_OCMODE_TOGGLE) << (TIM_OCMODE_SECOND_SHIFT)): // Toogle mode + if (abs(TIMx->CNT - TIMx->CCR4) < 2*TIMS->tx_step) + TIMS->Channels.OC4REF = ~TIMS->Channels.OC4REF; + break; - case ((TIM_OCMODE_PWM1) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 1 mode - if (TIMx->CNT < TIMx->CCR4) - TIMS->Channels.OC4REF = 1; - else - TIMS->Channels.OC4REF = 0; - break; + case ((TIM_OCMODE_PWM1) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 1 mode + if (TIMx->CNT < TIMx->CCR4) + TIMS->Channels.OC4REF = 1; + else + TIMS->Channels.OC4REF = 0; + break; - case ((TIM_OCMODE_PWM2) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 2 mode - if (TIMx->CNT < TIMx->CCR4) - TIMS->Channels.OC4REF = 0; - else - TIMS->Channels.OC4REF = 1; - break; + case ((TIM_OCMODE_PWM2) << (TIM_OCMODE_SECOND_SHIFT)): // PWM mode 2 mode + if (TIMx->CNT < TIMx->CCR4) + TIMS->Channels.OC4REF = 0; + else + TIMS->Channels.OC4REF = 1; + break; - case ((TIM_OCMODE_FORCED_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED ACTIVE mode - TIMS->Channels.OC4REF = 1; break; + case ((TIM_OCMODE_FORCED_ACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED ACTIVE mode + TIMS->Channels.OC4REF = 1; break; - case ((TIM_OCMODE_FORCED_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED INACTIVE mode - TIMS->Channels.OC4REF = 0; break; + case ((TIM_OCMODE_FORCED_INACTIVE) << (TIM_OCMODE_SECOND_SHIFT)): // FORCED INACTIVE mode + TIMS->Channels.OC4REF = 0; break; -} + } + 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)) + { + TIM_Call_IRQHandller(TIMx); + } + else if (((TIMS->tx_cnt - TIMS->tx_step) > TIMx->CCR4) && (TIMS->tx_cnt <= TIMx->CCR4)) + { + TIM_Call_IRQHandller(TIMx); + } + } } /* Запись каналов таймера в порты GPIO */ void Write_OC_to_GPIO(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS) @@ -565,70 +613,68 @@ void TIM_SIM_DEINIT(void) // Т.к. в MSVC нет понятия weak function, необходимо объявить все колбеки // И если какой-то колбек не используется, его надо определить //#ifndef USE_TIM1_UP_TIM10_HANDLER -//void TIM1_UP_TIM10_IRQHandler(void) {} +__weak void TIM1_UP_TIM10_IRQHandler(void) {} //#endif //#ifndef USE_TIM2_HANDLER -//void TIM2_IRQHandler(void) {} +__weak void TIM2_IRQHandler(void) {} //#endif //#ifndef USE_TIM3_HANDLER -//void TIM3_IRQHandler(void) {} +__weak void TIM3_IRQHandler(void) {} //#endif //#ifndef USE_TIM4_HANDLER -//void TIM4_IRQHandler(void) {} +__weak void TIM4_IRQHandler(void) {} //#endif //#ifndef USE_TIM5_HANDLER -//void TIM5_IRQHandler(void) {} +__weak void TIM5_IRQHandler(void) {} //#endif //#ifndef USE_TIM6_HANDLER -//void TIM6_DAC_IRQHandler(void) {} +__weak void TIM6_DAC_IRQHandler(void) {} //#endif //#ifndef USE_TIM7_HANDLER -//void TIM7_IRQHandler(void) {} +__weak void TIM7_IRQHandler(void) {} //#endif //#ifndef USE_TIM8_UP_TIM13_HANDLER -//void TIM8_UP_TIM13_IRQHandler(void) {} +__weak void TIM8_UP_TIM13_IRQHandler(void) {} //#endif //#ifndef USE_TIM1_BRK_TIM9_HANDLER -//void TIM1_BRK_TIM9_IRQHandler(void) {} +__weak void TIM1_BRK_TIM9_IRQHandler(void) {} //#endif //#ifndef USE_TIM1_TRG_COM_TIM11_HANDLER -//void TIM1_TRG_COM_TIM11_IRQHandler(void) {} +__weak void TIM1_TRG_COM_TIM11_IRQHandler(void) {} //#endif //#ifndef USE_TIM8_BRK_TIM12_HANDLER -//void TIM8_BRK_TIM12_IRQHandler(void) {} +__weak void TIM8_BRK_TIM12_IRQHandler(void) {} //#endif //#ifndef USE_TIM8_TRG_COM_TIM14_HANDLER -//void TIM8_TRG_COM_TIM14_IRQHandler(void) {} +__weak void TIM8_TRG_COM_TIM14_IRQHandler(void) {} //#endif /* Вызов прерывания */ void TIM_Call_IRQHandller(TIM_TypeDef* TIMx) { // calling HANDLER - //if (TIMx == TIM1) - // TIM1_UP_IRQHandler(); - //if ((TIMx == TIM1) || (TIMx == TIM10)) - // TIM1_UP_TIM10_IRQHandler(); - //else if (TIMx == TIM2) - // TIM2_IRQHandler(); - //else if (TIMx == TIM3) - // TIM3_IRQHandler(); - //else if (TIMx == TIM4) - // TIM4_IRQHandler(); - //else if (TIMx == TIM5) - // TIM5_IRQHandler(); - //else if (TIMx == TIM6) - // TIM6_DAC_IRQHandler(); - //else if (TIMx == TIM7) - // TIM7_IRQHandler(); - //else if ((TIMx == TIM8) || (TIMx == TIM13)) - // TIM8_UP_TIM13_IRQHandler(); - //else if ((TIMx == TIM1) || (TIMx == TIM9)) - // TIM1_BRK_TIM9_IRQHandler(); - //else if ((TIMx == TIM1) || (TIMx == TIM11)) - // TIM1_TRG_COM_TIM11_IRQHandler(); - //else if ((TIMx == TIM8) || (TIMx == TIM12)) - // TIM8_BRK_TIM12_IRQHandler(); - //else if ((TIMx == TIM8) || (TIMx == TIM14)) - // TIM8_TRG_COM_TIM14_IRQHandler(); + if ((TIMx == TIM1) || (TIMx == TIM10)) + TIM1_UP_TIM10_IRQHandler(); + else if (TIMx == TIM2) + TIM2_IRQHandler(); + else if (TIMx == TIM3) + TIM3_IRQHandler(); + else if (TIMx == TIM4) + TIM4_IRQHandler(); + else if (TIMx == TIM5) + TIM5_IRQHandler(); + else if (TIMx == TIM6) + TIM6_DAC_IRQHandler(); + else if (TIMx == TIM7) + TIM7_IRQHandler(); + else if ((TIMx == TIM8) || (TIMx == TIM13)) + TIM8_UP_TIM13_IRQHandler(); + else if ((TIMx == TIM1) || (TIMx == TIM9)) + TIM1_BRK_TIM9_IRQHandler(); + else if ((TIMx == TIM1) || (TIMx == TIM11)) + TIM1_TRG_COM_TIM11_IRQHandler(); + else if ((TIMx == TIM8) || (TIMx == TIM12)) + TIM8_BRK_TIM12_IRQHandler(); + else if ((TIMx == TIM8) || (TIMx == TIM14)) + TIM8_TRG_COM_TIM14_IRQHandler(); } //------------------------------------------------------------------// diff --git a/MATLAB/app_wrapper/app_includes.h b/MATLAB/app_wrapper/app_includes.h index 7f49c25..785ac41 100644 --- a/MATLAB/app_wrapper/app_includes.h +++ b/MATLAB/app_wrapper/app_includes.h @@ -14,8 +14,6 @@ #include "tim.h" #include "adc.h" #include "upp_main.h" -#include "adc_tools.h" -#include "power_monitor.h" // INCLUDES END #endif //_APP_INCLUDES_H_ \ No newline at end of file diff --git a/MATLAB/app_wrapper/app_init.c b/MATLAB/app_wrapper/app_init.c index 176d679..705b1e2 100644 --- a/MATLAB/app_wrapper/app_init.c +++ b/MATLAB/app_wrapper/app_init.c @@ -19,6 +19,7 @@ void app_init(void) { HAL_Init(); MX_DMA_Init(); MX_TIM1_Init(); + MX_TIM2_Init(); MX_TIM3_Init(); MX_TIM8_Init(); MX_TIM5_Init(); diff --git a/MATLAB/app_wrapper/app_io.c b/MATLAB/app_wrapper/app_io.c index f8400cd..8b6e497 100644 --- a/MATLAB/app_wrapper/app_io.c +++ b/MATLAB/app_wrapper/app_io.c @@ -31,23 +31,23 @@ void Write_PowerMonitor(real_T* Buffer, int ind_port) int nn = 0; for (int i = 0; i < 3; i++) { - WriteOutputArray(pm.U[i], ind_port, nn++); + WriteOutputArray(upp.pm.U[i], ind_port, nn++); } for (int i = 0; i < 3; i++) { - WriteOutputArray(pm.ZC_Detected[i], ind_port, nn++); + WriteOutputArray(upp.pm.zc.Channel[i].HalfWave, ind_port, nn++); } for (int i = 0; i < 3; i++) { - WriteOutputArray(pm.F[i], ind_port, nn++); + WriteOutputArray(upp.pm.F[i], ind_port, nn++); } for (int i = 0; i < 3; i++) { - WriteOutputArray(pm.I[i], ind_port, nn++); + WriteOutputArray(upp.pm.I[i], ind_port, nn++); } for (int i = 0; i < 2; i++) { - WriteOutputArray(pm.T[i], ind_port, nn++); + WriteOutputArray(upp.pm.T[i], ind_port, nn++); } } /** @@ -63,6 +63,7 @@ void app_readInputs(const real_T* Buffer) { ADC_Set_Channel_Value(ADC3, 8, ReadInputArray(0,4)); ADC_Set_Channel_Value(ADC3, 10, ReadInputArray(0,5)); + alpha_dbg = ReadInputArray(1, 0); // USER APP INPUT END } @@ -73,13 +74,12 @@ void app_readInputs(const real_T* Buffer) { */ void app_writeOutputBuffer(real_T* Buffer) { // USER APP OUTPUT START - //ThyristorWrite(Buffer, 0); + Write_Thyristors(Buffer, 0); Write_PowerMonitor(Buffer, 1); - WriteOutputArray(hmcu.dSFuncPeriod, 2, 12); - WriteOutputArray(hmcu.dSFuncTime, 2, 13); - WriteOutputArray(hmcu.dMCUStepTime, 2, 14); + WriteOutputArray(TIM2->CNT, 2, 0); + WriteOutputArray(TIM2->CCR1, 2, 1); // USER APP OUTPUT END } \ No newline at end of file diff --git a/MATLAB/upp_init.m b/MATLAB/upp_init.m new file mode 100644 index 0000000..7618676 --- /dev/null +++ b/MATLAB/upp_init.m @@ -0,0 +1,8 @@ +clear all + +Ts = 5e-6; +Vnom = 380; +Fnom = 50; + +Temperature1 = 2.22; % 20 градусов +Temperature2 = 2.99; % 34 градусов \ No newline at end of file diff --git a/MATLAB/upp_r2023.slx b/MATLAB/upp_r2023.slx index 9b886b6..857c684 100644 Binary files a/MATLAB/upp_r2023.slx and b/MATLAB/upp_r2023.slx differ diff --git a/UPP/AllLibs/MyLibs b/UPP/AllLibs/MyLibs index 606058e..99652a9 160000 --- a/UPP/AllLibs/MyLibs +++ b/UPP/AllLibs/MyLibs @@ -1 +1 @@ -Subproject commit 606058ef552c6341c965bc76d3eda6929ca58e13 +Subproject commit 99652a9ad5ea0686ad9242b165508a9d92ac80a1 diff --git a/UPP/AllLibs/PeriphGeneral b/UPP/AllLibs/PeriphGeneral index 50c07cd..b3f118b 160000 --- a/UPP/AllLibs/PeriphGeneral +++ b/UPP/AllLibs/PeriphGeneral @@ -1 +1 @@ -Subproject commit 50c07cd0911d11106670d25d1457c45735eaa4fa +Subproject commit b3f118b074951fa827e5a692e9da7637b5397a98 diff --git a/UPP/Core/Configs/mylibs_config.h b/UPP/Core/Configs/mylibs_config.h index c87e783..cbc013d 100644 --- a/UPP/Core/Configs/mylibs_config.h +++ b/UPP/Core/Configs/mylibs_config.h @@ -131,7 +131,7 @@ #define INCLUDE_BIT_ACCESS_LIB ///< Подключить библиотеку с typedef с битовыми полями #define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами //#define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами -//#define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией +#define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией //#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени #define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами diff --git a/UPP/Core/Configs/upp_config.h b/UPP/Core/Configs/upp_config.h index 5c60f54..1208474 100644 --- a/UPP/Core/Configs/upp_config.h +++ b/UPP/Core/Configs/upp_config.h @@ -14,7 +14,10 @@ #define _UPP_CONFIG_H_ #include "stm32f4xx_hal.h" +// Проверка корректности структуры +#define assert_upp(_struct_) check_null_ptr_2(_struct_, (_struct_)->f.Initialized) +/* Дефайны для индексов */ #define U_BA 0 #define U_AC 1 #define U_BC 2 @@ -24,14 +27,39 @@ #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 Состояния полуволны + */ +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; + #endif //_UPP_CONFIG_H_ diff --git a/UPP/Core/Inc/main.h b/UPP/Core/Inc/main.h index a2211ec..704767c 100644 --- a/UPP/Core/Inc/main.h +++ b/UPP/Core/Inc/main.h @@ -71,11 +71,15 @@ extern __IO uint32_t micros; #define PWM_CHANNEL_6 TIM_CHANNEL_4 #define mb_htim htim12 #define adc_tim htim8 -#define hpwm2 htim2 +#define usTick ustim.Instance->CNT +#define hpwm2 htim3 #define mb_dbg_huart huart6 #define ustim htim5 #define hpwm1 htim1 -#define usTick ustim.Instance->CNT +#define ANGLE_CHANNEL_1 TIM_CHANNEL_1 +#define ANGLE_CHANNEL_2 TIM_CHANNEL_2 +#define ANGLE_CHANNEL_3 TIM_CHANNEL_3 +#define angletim htim2 #define UM_LED_GREEN2_Pin GPIO_PIN_2 #define UM_LED_GREEN2_GPIO_Port GPIOE #define CEN_O_Pin GPIO_PIN_3 diff --git a/UPP/Core/Inc/stm32f4xx_it.h b/UPP/Core/Inc/stm32f4xx_it.h index 52044da..a95542f 100644 --- a/UPP/Core/Inc/stm32f4xx_it.h +++ b/UPP/Core/Inc/stm32f4xx_it.h @@ -55,6 +55,8 @@ void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void TIM1_UP_TIM10_IRQHandler(void); +void TIM2_IRQHandler(void); void TIM8_TRG_COM_TIM14_IRQHandler(void); void DMA2_Stream0_IRQHandler(void); /* USER CODE BEGIN EFP */ diff --git a/UPP/Core/Inc/tim.h b/UPP/Core/Inc/tim.h index 6a9d43b..2b501c6 100644 --- a/UPP/Core/Inc/tim.h +++ b/UPP/Core/Inc/tim.h @@ -34,6 +34,8 @@ extern "C" { extern TIM_HandleTypeDef htim1; +extern TIM_HandleTypeDef htim2; + extern TIM_HandleTypeDef htim3; extern TIM_HandleTypeDef htim5; @@ -49,6 +51,7 @@ extern TIM_HandleTypeDef htim12; /* USER CODE END Private defines */ void MX_TIM1_Init(void); +void MX_TIM2_Init(void); void MX_TIM3_Init(void); void MX_TIM5_Init(void); void MX_TIM8_Init(void); diff --git a/UPP/Core/PowerMonitor/adc_tools.c b/UPP/Core/PowerMonitor/adc_tools.c index dbd81d7..5129c70 100644 --- a/UPP/Core/PowerMonitor/adc_tools.c +++ b/UPP/Core/PowerMonitor/adc_tools.c @@ -32,8 +32,6 @@ static float coefs_biquad_T[5] = { -1.98f, // a1 0.980f // a2 }; -// Проверка корректности структуры АЦП -#define assert_adc(_adc_) check_null_ptr_2(_adc_, (_adc_)->f.Initialized) static void ADC_EnableAllFilters(ADC_Periodic_t *adc) { @@ -100,7 +98,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 res; - if(assert_adc(adc)) + if(assert_upp(adc)) return HAL_ERROR; if((valueMax == 0) || (levelMax == 0)) return HAL_ERROR; @@ -121,7 +119,7 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t le HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period) { HAL_StatusTypeDef res; - if(assert_adc(adc)) + if(assert_upp(adc)) return HAL_ERROR; if(Period == 0) return HAL_ERROR; @@ -154,7 +152,7 @@ HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period) */ HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc) { - if(assert_adc(adc)) + if(assert_upp(adc)) return HAL_ERROR; // Запускаем таймер который будет запускать опрос АЦП @@ -170,7 +168,7 @@ HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc) */ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc) { - if(assert_adc(adc)) + if(assert_upp(adc)) return HAL_ERROR; ADC_Coefs_t *coefs = adc->Coefs; @@ -219,7 +217,7 @@ void ADC_UpdateStatistics(ADC_Periodic_t *adc, uint8_t channel, ADC_StatLevel_t { if (level < ADC_LEVEL_BASE) return; - if(assert_adc(adc)) + if(assert_upp(adc)) return; if (channel >= ADC_NUMB_OF_REGULAR_CHANNELS) return; diff --git a/UPP/Core/PowerMonitor/adc_tools.h b/UPP/Core/PowerMonitor/adc_tools.h index 12da5ae..e61e16b 100644 --- a/UPP/Core/PowerMonitor/adc_tools.h +++ b/UPP/Core/PowerMonitor/adc_tools.h @@ -126,6 +126,7 @@ HAL_StatusTypeDef ADC_ConfigChannel(ADC_Periodic_t *adc, int ChNumb, uint16_t le HAL_StatusTypeDef ADC_Start(ADC_Periodic_t *adc, uint16_t Period); /* Остановка АЦП. */ HAL_StatusTypeDef ADC_Stop(ADC_Periodic_t *adc); + /* Обработка АЦП после получения данных. */ HAL_StatusTypeDef ADC_Handle(ADC_Periodic_t *adc); diff --git a/UPP/Core/PowerMonitor/power_monitor.c b/UPP/Core/PowerMonitor/power_monitor.c index 53f5f3e..f4dcf07 100644 --- a/UPP/Core/PowerMonitor/power_monitor.c +++ b/UPP/Core/PowerMonitor/power_monitor.c @@ -43,7 +43,7 @@ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) { if(ADC_Start(&hpm->adc, PM_ADC_PERIOD) != HAL_OK) return HAL_ERROR; - + return HAL_OK; } @@ -51,8 +51,7 @@ HAL_StatusTypeDef PowerMonitor_Start(PowerMonitor_t *hpm) void PowerMonitor_Handle(PowerMonitor_t *hpm) { - - static uint32_t last_zc_state[ADC_NUMB_OF_U_CHANNELS] = {0}; + static uint32_t last_zc_cnt[ADC_NUMB_OF_U_CHANNELS] = {0}; ADC_Handle(&hpm->adc); hpm->U[U_BA] = hpm->adc.Data[ADC_CHANNEL_UBA]; @@ -69,14 +68,7 @@ void PowerMonitor_Handle(PowerMonitor_t *hpm) ZC_ProcessAllChannels(&hpm->zc, hpm->U, usTick); for(int i = 0; i < 3; i++) { - if(last_zc_state[i] != ZC_GetStableState(&hpm->zc, i)) - { - last_zc_state[i] = ZC_GetStableState(&hpm->zc, i); - hpm->ZC_Detected[i] = !hpm->ZC_Detected[i]; - } + + hpm->F[i] = ZC_GetFrequency(&hpm->zc, i) / 2; } - - hpm->F[U_BA] = (hpm->zc.Channel[U_BA].Frequency) / 2; - hpm->F[U_AC] = (hpm->zc.Channel[U_AC].Frequency) / 2; - hpm->F[U_BC] = (hpm->zc.Channel[U_BC].Frequency) / 2; } \ No newline at end of file diff --git a/UPP/Core/PowerMonitor/power_monitor.h b/UPP/Core/PowerMonitor/power_monitor.h index 54ac6e6..56bf1cd 100644 --- a/UPP/Core/PowerMonitor/power_monitor.h +++ b/UPP/Core/PowerMonitor/power_monitor.h @@ -10,11 +10,12 @@ #include "adc_tools.h" #include "zero_cross.h" + typedef struct { ADC_Periodic_t adc; ZeroCross_Handle_t zc; - uint32_t ZC_Detected[3]; + UPP_HalfWave_t CurrentHalfWave[3]; float U[3]; float F[3]; diff --git a/UPP/Core/PowerMonitor/zero_cross.c b/UPP/Core/PowerMonitor/zero_cross.c index e6ae71f..d587251 100644 --- a/UPP/Core/PowerMonitor/zero_cross.c +++ b/UPP/Core/PowerMonitor/zero_cross.c @@ -38,7 +38,6 @@ HAL_StatusTypeDef ZC_Init(ZeroCross_Handle_t *zc, uint8_t num_channels, zc->Channel[i].LastValue = 0.0f; zc->Channel[i].CurrentValue = 0.0f; zc->Channel[i].DebounceCounter = 0; - zc->Channel[i].StableState = 0; zc->Channel[i].LastCrossTime = 0; zc->Channel[i].Period = 0; zc->Channel[i].Frequency = 0.0f; @@ -61,10 +60,9 @@ HAL_StatusTypeDef ZC_Init(ZeroCross_Handle_t *zc, uint8_t num_channels, HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel, ZC_EdgeType_t edgeType) { - if (zc == NULL || !zc->f.Initialized) { + if (assert_upp(zc)){ return HAL_ERROR; } - if (channel >= zc->NumChannels) { return HAL_ERROR; } @@ -74,7 +72,6 @@ HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel, // Сброс состояния канала при реконфигурации zc->Channel[channel].LastValue = 0.0f; zc->Channel[channel].DebounceCounter = 0; - zc->Channel[channel].StableState = 0; zc->Channel[channel].LastCrossTime = 0; zc->Channel[channel].Period = 0; zc->Channel[channel].Frequency = 0.0f; @@ -91,7 +88,10 @@ HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel, */ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uint32_t timestamp) { - if (zc == NULL || !zc->f.Initialized || !zc->f.Monitoring) { + if (assert_upp(zc)){ + return; + } + if (!zc->f.Monitoring) { return; } if (channel >= zc->NumChannels) { @@ -147,9 +147,9 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin if(zc_detected) { - zc_ch->StableState = zc_detected == 1? 1:0; - - uint32_t RealTimeShift = zc->DebounceSamples*(timestamp - zc->LastTick); // коло-во тиков * период вызова функции + 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 RealTimestamp = timestamp-RealTimeShift; @@ -180,7 +180,11 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uin */ void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float *values, uint32_t timestamp) { - if (zc == NULL || !zc->f.Initialized || !zc->f.Monitoring || values == NULL) { + if (assert_upp(zc)){ + return; + } + + if (!zc->f.Monitoring || values == NULL) { return; } @@ -191,6 +195,38 @@ void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float *values, uint32_t times zc->LastTick = timestamp; } + +/** + * @brief Полученить флаг - переход произошел. + * @param zc Указатель на хендл детектора нуля + * @param channel Номер канала + * @return 1 - переход произошел, 0 - перехода не было. + */ +int ZC_isOccurred(ZeroCross_Handle_t *zc, uint8_t channel) +{ + if (assert_upp(zc)){ + return 0; + } + int occurred = zc->Channel[channel].Occurred; + zc->Channel[channel].Occurred = 0; + return occurred; +} + +/** + * @brief Получение полуволны (после последнего zero-cross). + * @param zc Указатель на хендл детектора нуля + * @param channel Номер канала + * @return Текущая полуволна @ref UPP_HalfWave_t. + */ +UPP_HalfWave_t ZC_GetHalfWave(ZeroCross_Handle_t *zc, uint8_t channel) +{ + if (assert_upp(zc)){ + return UPP_WAVE_UNKNOWED; + } + + return zc->Channel[channel].HalfWave; +} + /** * @brief Получение частоты сигнала. * @param zc Указатель на хендл детектора нуля @@ -199,73 +235,16 @@ void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float *values, uint32_t times */ float ZC_GetFrequency(ZeroCross_Handle_t *zc, uint8_t channel) { - if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) { + if (assert_upp(zc)){ + return 0.0f; + } + if (channel >= zc->NumChannels) { return 0.0f; } return zc->Channel[channel].Frequency; } -/** - * @brief Получение периода сигнала. - * @param zc Указатель на хендл детектора нуля - * @param channel Номер канала - * @return Период в тактах таймера. - */ -uint32_t ZC_GetPeriod(ZeroCross_Handle_t *zc, uint8_t channel) -{ - if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) { - return 0; - } - - return zc->Channel[channel].Period; -} - -/** - * @brief Получение счетчика переходов. - * @param zc Указатель на хендл детектора нуля - * @param channel Номер канала - * @return Количество переходов. - */ -uint32_t ZC_GetCrossCount(ZeroCross_Handle_t *zc, uint8_t channel) -{ - if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) { - return 0; - } - - return zc->Channel[channel].CrossCount; -} - -/** - * @brief Получение текущего состояния канала. - * @param zc Указатель на хендл детектора нуля - * @param channel Номер канала - * @return Состояние (0 - отрицательное, 1 - положительное). - */ -uint8_t ZC_GetStableState(ZeroCross_Handle_t *zc, uint8_t channel) -{ - if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) { - return 0; - } - - return zc->Channel[channel].StableState; -} - -/** - * @brief Получение текущего значения канала. - * @param zc Указатель на хендл детектора нуля - * @param channel Номер канала - * @return Текущее значение сигнала. - */ -float ZC_GetCurrentValue(ZeroCross_Handle_t *zc, uint8_t channel) -{ - if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) { - return 0.0f; - } - - return zc->Channel[channel].CurrentValue; -} - /** * @brief Включение/выключение мониторинга. * @param zc Указатель на хендл детектора нуля @@ -273,6 +252,9 @@ float ZC_GetCurrentValue(ZeroCross_Handle_t *zc, uint8_t channel) */ void ZC_EnableMonitoring(ZeroCross_Handle_t *zc, uint8_t enable) { + if (assert_upp(zc)){ + return; + } if (zc == NULL || !zc->f.Initialized) { return; } @@ -287,7 +269,7 @@ void ZC_EnableMonitoring(ZeroCross_Handle_t *zc, uint8_t enable) */ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel) { - if (zc == NULL || !zc->f.Initialized) { + if (assert_upp(zc)){ return; } @@ -295,7 +277,6 @@ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel) zc->Channel[channel].LastValue = 0.0f; zc->Channel[channel].CurrentValue = 0.0f; zc->Channel[channel].DebounceCounter = 0; - zc->Channel[channel].StableState = 0; zc->Channel[channel].LastCrossTime = 0; zc->Channel[channel].Period = 0; zc->Channel[channel].Frequency = 0.0f; @@ -307,7 +288,6 @@ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel) zc->Channel[i].LastValue = 0.0f; zc->Channel[i].CurrentValue = 0.0f; zc->Channel[i].DebounceCounter = 0; - zc->Channel[i].StableState = 0; zc->Channel[i].LastCrossTime = 0; zc->Channel[i].Period = 0; zc->Channel[i].Frequency = 0.0f; diff --git a/UPP/Core/PowerMonitor/zero_cross.h b/UPP/Core/PowerMonitor/zero_cross.h index fc91202..ba22f79 100644 --- a/UPP/Core/PowerMonitor/zero_cross.h +++ b/UPP/Core/PowerMonitor/zero_cross.h @@ -88,15 +88,16 @@ typedef enum { * @brief Структура канала детектора нуля */ typedef struct { - uint32_t CrossCount; ///< Счетчик переходов - float LastValue; ///< Предыдущее значение - float CurrentValue; ///< Текущее значение - uint16_t DebounceCounter; ///< Счетчик антидребезга - uint8_t StableState; ///< Стабильное состояние (0=отриц, 1=полож) - uint32_t LastCrossTime; ///< Время последнего перехода - uint32_t Period; ///< Период сигнала (в тактах таймера) - float Frequency; ///< Частота - ZC_EdgeType_t EdgeType; ///< Тип детектируемого перехода + uint8_t Occurred; ///< Флаг что пересечение нуля произошло + uint32_t CrossCount; ///< Счетчик переходов + float LastValue; ///< Предыдущее значение + float CurrentValue; ///< Текущее значение + uint16_t DebounceCounter; ///< Счетчик антидребезга + uint32_t LastCrossTime; ///< Время последнего перехода + uint32_t Period; ///< Период сигнала (в тактах таймера) + float Frequency; ///< Частота + UPP_HalfWave_t HalfWave; ///< Текущая полуволна + ZC_EdgeType_t EdgeType; ///< Тип детектируемого перехода } ZC_Channel_t; /** @@ -132,36 +133,17 @@ void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float *values, uint32_t timestamp); +/* Полученить флаг - переход произошел. */ +int ZC_isOccurred(ZeroCross_Handle_t *zc, uint8_t channel); /* Получение частоты сигнала */ float ZC_GetFrequency(ZeroCross_Handle_t *zc, uint8_t channel); - -/* Получение периода сигнала */ -uint32_t ZC_GetPeriod(ZeroCross_Handle_t *zc, uint8_t channel); - -/* Получение счетчика переходов */ -uint32_t ZC_GetCrossCount(ZeroCross_Handle_t *zc, uint8_t channel); - -/* Получение текущего состояния канала */ -uint8_t ZC_GetStableState(ZeroCross_Handle_t *zc, uint8_t channel); - -/* Получение текущего значения канала */ -float ZC_GetCurrentValue(ZeroCross_Handle_t *zc, uint8_t channel); - +/* Получение полуволны (после последнего zero-cross) */ +UPP_HalfWave_t ZC_GetHalfWave(ZeroCross_Handle_t *zc, uint8_t channel); /* Включение/выключение мониторинга */ void ZC_EnableMonitoring(ZeroCross_Handle_t *zc, uint8_t enable); - /* Сброс статистики канала */ void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel); -/* Установка гистерезиса для хендла */ -void ZC_SetHysteresis(ZeroCross_Handle_t *zc, float hysteresis); - -/* Установка дебаунс samples для хендла */ -void ZC_SetDebounceSamples(ZeroCross_Handle_t *zc, uint8_t debounce_samples); - -/* Получение количества каналов хендла */ -uint8_t ZC_GetNumChannels(ZeroCross_Handle_t *zc); - #endif /* _ZERO_CROSS_H_ */ /** diff --git a/UPP/Core/Src/main.c b/UPP/Core/Src/main.c index 16e30e8..9096b23 100644 --- a/UPP/Core/Src/main.c +++ b/UPP/Core/Src/main.c @@ -107,6 +107,7 @@ int main(void) MX_TIM12_Init(); MX_TIM8_Init(); MX_TIM5_Init(); + MX_TIM2_Init(); /* USER CODE BEGIN 2 */ #else //MATLAB #endif //MATLAB diff --git a/UPP/Core/Src/stm32f4xx_it.c b/UPP/Core/Src/stm32f4xx_it.c index ceef07b..f151479 100644 --- a/UPP/Core/Src/stm32f4xx_it.c +++ b/UPP/Core/Src/stm32f4xx_it.c @@ -23,6 +23,8 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "upp_main.h" +#include "pwm_thyristors.h" +#include "angle_control.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -57,6 +59,8 @@ /* External variables --------------------------------------------------------*/ extern DMA_HandleTypeDef hdma_adc3; +extern TIM_HandleTypeDef htim1; +extern TIM_HandleTypeDef htim2; extern TIM_HandleTypeDef htim8; extern TIM_HandleTypeDef htim14; @@ -202,13 +206,41 @@ void SysTick_Handler(void) /* please refer to the startup file (startup_stm32f4xx.s). */ /******************************************************************************/ +/** + * @brief This function handles TIM1 update interrupt and TIM10 global interrupt. + */ +void TIM1_UP_TIM10_IRQHandler(void) +{ + /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 0 */ + + /* USER CODE END TIM1_UP_TIM10_IRQn 0 */ + HAL_TIM_IRQHandler(&htim1); + /* USER CODE BEGIN TIM1_UP_TIM10_IRQn 1 */ + UPP_PWM_Handle(); + /* USER CODE END TIM1_UP_TIM10_IRQn 1 */ +} + +/** + * @brief This function handles TIM2 global interrupt. + */ +void TIM2_IRQHandler(void) +{ + /* USER CODE BEGIN TIM2_IRQn 0 */ + + /* USER CODE END TIM2_IRQn 0 */ + HAL_TIM_IRQHandler(&htim2); + /* USER CODE BEGIN TIM2_IRQn 1 */ + //UPP_Angle_Handle(); + /* USER CODE END TIM2_IRQn 1 */ +} + /** * @brief This function handles TIM8 trigger and commutation interrupts and TIM14 global interrupt. */ void TIM8_TRG_COM_TIM14_IRQHandler(void) { /* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 0 */ -#ifndef MATLAB +#ifndef MATLAB // в матлабе нет htim14, т.к. это систем тики /* USER CODE END TIM8_TRG_COM_TIM14_IRQn 0 */ HAL_TIM_IRQHandler(&htim8); HAL_TIM_IRQHandler(&htim14); diff --git a/UPP/Core/Src/tim.c b/UPP/Core/Src/tim.c index a9cc642..85caab9 100644 --- a/UPP/Core/Src/tim.c +++ b/UPP/Core/Src/tim.c @@ -25,6 +25,7 @@ /* USER CODE END 0 */ TIM_HandleTypeDef htim1; +TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim3; TIM_HandleTypeDef htim5; TIM_HandleTypeDef htim8; @@ -48,7 +49,7 @@ void MX_TIM1_Init(void) /* USER CODE END TIM1_Init 1 */ htim1.Instance = TIM1; - htim1.Init.Prescaler = 180-1; + htim1.Init.Prescaler = 0; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 65535; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; @@ -67,7 +68,11 @@ void MX_TIM1_Init(void) { Error_Handler(); } - sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + if (HAL_TIM_OnePulse_Init(&htim1, TIM_OPMODE_SINGLE) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) { @@ -112,6 +117,67 @@ void MX_TIM1_Init(void) /* USER CODE END TIM1_Init 2 */ HAL_TIM_MspPostInit(&htim1); +} +/* TIM2 init function */ +void MX_TIM2_Init(void) +{ + + /* USER CODE BEGIN TIM2_Init 0 */ + + /* USER CODE END TIM2_Init 0 */ + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_OC_InitTypeDef sConfigOC = {0}; + + /* USER CODE BEGIN TIM2_Init 1 */ + + /* USER CODE END TIM2_Init 1 */ + htim2.Instance = TIM2; + htim2.Init.Prescaler = 0; + htim2.Init.CounterMode = TIM_COUNTERMODE_UP; + htim2.Init.Period = 4294967295; + htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim2) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_OC_Init(&htim2) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + sConfigOC.OCMode = TIM_OCMODE_TIMING; + sConfigOC.Pulse = 0; + sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) + { + Error_Handler(); + } + if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM2_Init 2 */ + + /* USER CODE END TIM2_Init 2 */ + } /* TIM3 init function */ void MX_TIM3_Init(void) @@ -122,6 +188,7 @@ void MX_TIM3_Init(void) /* USER CODE END TIM3_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_SlaveConfigTypeDef sSlaveConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; @@ -147,8 +214,18 @@ void MX_TIM3_Init(void) { Error_Handler(); } + if (HAL_TIM_OnePulse_Init(&htim3, TIM_OPMODE_SINGLE) != HAL_OK) + { + Error_Handler(); + } + sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER; + sSlaveConfig.InputTrigger = TIM_TS_ITR0; + if (HAL_TIM_SlaveConfigSynchro(&htim3, &sSlaveConfig) != HAL_OK) + { + Error_Handler(); + } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; - sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) { Error_Handler(); @@ -325,10 +402,29 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) /* USER CODE END TIM1_MspInit 0 */ /* TIM1 clock enable */ __HAL_RCC_TIM1_CLK_ENABLE(); + + /* TIM1 interrupt Init */ + HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); /* USER CODE BEGIN TIM1_MspInit 1 */ /* USER CODE END TIM1_MspInit 1 */ } + else if(tim_baseHandle->Instance==TIM2) + { + /* USER CODE BEGIN TIM2_MspInit 0 */ + + /* USER CODE END TIM2_MspInit 0 */ + /* TIM2 clock enable */ + __HAL_RCC_TIM2_CLK_ENABLE(); + + /* TIM2 interrupt Init */ + HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM2_IRQn); + /* USER CODE BEGIN TIM2_MspInit 1 */ + + /* USER CODE END TIM2_MspInit 1 */ + } else if(tim_baseHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspInit 0 */ @@ -469,10 +565,27 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle) /* USER CODE END TIM1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM1_CLK_DISABLE(); + + /* TIM1 interrupt Deinit */ + HAL_NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn); /* USER CODE BEGIN TIM1_MspDeInit 1 */ /* USER CODE END TIM1_MspDeInit 1 */ } + else if(tim_baseHandle->Instance==TIM2) + { + /* USER CODE BEGIN TIM2_MspDeInit 0 */ + + /* USER CODE END TIM2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM2_CLK_DISABLE(); + + /* TIM2 interrupt Deinit */ + HAL_NVIC_DisableIRQ(TIM2_IRQn); + /* USER CODE BEGIN TIM2_MspDeInit 1 */ + + /* USER CODE END TIM2_MspDeInit 1 */ + } else if(tim_baseHandle->Instance==TIM3) { /* USER CODE BEGIN TIM3_MspDeInit 0 */ diff --git a/UPP/Core/UPP/angle_control.c b/UPP/Core/UPP/angle_control.c new file mode 100644 index 0000000..de0ee4f --- /dev/null +++ b/UPP/Core/UPP/angle_control.c @@ -0,0 +1,167 @@ +/** +****************************************************************************** +* @file pwm_thyristors.c +* @brief Модуль для управления тиристорами +****************************************************************************** +* @details +******************************************************************************/ +#include "angle_control.h" +#include "tim.h" + + +/** + * @brief Инициализация ШИМ тиристоров. + * @param hangle Указатель на таймер + * @return HAL Status. + */ +HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float AngleMax) +{ + 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); + HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_2); + HAL_TIM_OC_Start_IT(hangle->htim, ANGLE_CHANNEL_3); + + Angle_Reset(hangle, UPP_PHASE_A); + Angle_Reset(hangle, UPP_PHASE_B); + Angle_Reset(hangle, UPP_PHASE_C); + + return HAL_OK; +} + +/** + * @brief Хендл таймера для рассчета угла открытия. + * @param hangle Указатель на таймер + * @return HAL Status. + */ +UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle) +{ + if(hangle == NULL) + return UPP_PHASE_UNKNOWN; + + + switch(hangle->htim->Channel) + { + case HAL_TIM_ACTIVE_CHANNEL_1: + return UPP_PHASE_A; + break; + + case HAL_TIM_ACTIVE_CHANNEL_2: + return UPP_PHASE_B; + break; + + case HAL_TIM_ACTIVE_CHANNEL_3: + return UPP_PHASE_C; + break; + + default: + return UPP_PHASE_UNKNOWN; + break; + } + + + return UPP_PHASE_UNKNOWN; +} + +/** + * @brief Установка угла открытия в таймер. + * @param hangle Указатель на таймер + * @param Phase Для какой фазы надо установить угол открытия + * @return HAL Status. + */ +HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float Freq) +{ + if(hangle == NULL) + return HAL_ERROR; + + // Если канал дурацкий - возвращаем ошибку + if(Phase >= 3) + { + return HAL_ERROR; + } + if(Angle > hangle->AngleMax) + { + Angle = hangle->AngleMax; + } + if(Angle < hangle->AngleMin) + { + Angle = hangle->AngleMin; + } + + uint32_t timer_ticks = TIM_FreqToTick(Freq/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); + 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); + 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); + break; + + case UPP_PHASE_UNKNOWN: + // ПОКА ХЗ + break; + + + } + + return HAL_OK; +} + +/** + * @brief Сброс угла открытия у таймера. + * @param hangle Указатель на таймер + * @param Phase Для какой фазы надо сбросить угол открытия + * @return HAL Status. + */ +HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase) +{ + if(hangle == NULL) + return HAL_ERROR; + + // Если канал дурацкий - возвращаем ошибку + if(Phase >= 3) + { + return HAL_ERROR; + } + + switch(Phase) + { + case UPP_PHASE_A: + __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC1); + break; + + case UPP_PHASE_B: + __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC2); + break; + + case UPP_PHASE_C: + __HAL_TIM_DISABLE_IT(hangle->htim, TIM_IT_CC3); + break; + + case UPP_PHASE_UNKNOWN: + // ПОКА ХЗ + break; + } + return HAL_OK; +} \ No newline at end of file diff --git a/UPP/Core/UPP/angle_control.h b/UPP/Core/UPP/angle_control.h new file mode 100644 index 0000000..4da20e1 --- /dev/null +++ b/UPP/Core/UPP/angle_control.h @@ -0,0 +1,30 @@ +/** +****************************************************************************** +* @file pwm_thyristors.h +* @brief Модуль для управления тиристорами (объединённый 6-канальный) +****************************************************************************** +*/ +#ifndef _ANGLE_CONTROL_H_ +#define _ANGLE_CONTROL_H_ +#include "main.h" + +#define ANGLE_TIM2_FREQ_MHZ 90 + +typedef struct +{ + TIM_HandleTypeDef *htim; + + float AngleMin; + float AngleMax; +}Angle_Handle_t; + +/* Инициализация Таймера для рассчета угла открытия. */ +HAL_StatusTypeDef Angle_Init(Angle_Handle_t *hangle, float AngleMin, float AngleMax); +/* Установка угла открытия в таймер. */ +HAL_StatusTypeDef Angle_Start(Angle_Handle_t *hangle, UPP_Phase_t Phase, float Angle, float Freq); +/* Сброс угла открытия у таймера. */ +HAL_StatusTypeDef Angle_Reset(Angle_Handle_t *hangle, UPP_Phase_t Phase); + +/* Хендл таймера для рассчета угла открытия. */ +UPP_Phase_t Angle_Handle(Angle_Handle_t *hangle); +#endif /* _ANGLE_CONTROL_H_ */ diff --git a/UPP/Core/UPP/pwm_thyristors.c b/UPP/Core/UPP/pwm_thyristors.c new file mode 100644 index 0000000..fc6c643 --- /dev/null +++ b/UPP/Core/UPP/pwm_thyristors.c @@ -0,0 +1,303 @@ +/** +****************************************************************************** +* @file pwm_thyristors.c +* @brief Модуль для управления тиристорами +****************************************************************************** +* @details +******************************************************************************/ +#include "pwm_thyristors.h" +#include "angle_control.h" +#include "tim.h" + +static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint32_t state); + +/** + * @brief Инициализация ШИМ тиристоров. + * @param hpwm Указатель на хендл ШИМ тиристоров + * @return HAL Status. + */ +HAL_StatusTypeDef PWM_Init(PWM_Handle_t *hpwm) +{ + if(hpwm == NULL) + return HAL_ERROR; + + // Фаза A + hpwm->AllPhases[PHASE_A_POS].State = PWM_THYR_DISABLED; + hpwm->AllPhases[PHASE_A_POS].ChMask = PWM_CHANNEL_1; + hpwm->AllPhases[PHASE_A_POS].htim = &hpwm1; + hpwm->AllPhases[PHASE_A_NEG].State = PWM_THYR_DISABLED; + hpwm->AllPhases[PHASE_A_NEG].ChMask = PWM_CHANNEL_2; + hpwm->AllPhases[PHASE_A_NEG].htim = &hpwm1; + + // Фаза B + hpwm->AllPhases[PHASE_B_POS].State = PWM_THYR_DISABLED; + hpwm->AllPhases[PHASE_B_POS].ChMask = PWM_CHANNEL_3; + hpwm->AllPhases[PHASE_B_POS].htim = &hpwm1; + hpwm->AllPhases[PHASE_B_NEG].State = PWM_THYR_DISABLED; + hpwm->AllPhases[PHASE_B_NEG].ChMask = PWM_CHANNEL_4; + hpwm->AllPhases[PHASE_B_NEG].htim = &hpwm1; + + // Фаза C + hpwm->AllPhases[PHASE_C_POS].State = PWM_THYR_DISABLED; + hpwm->AllPhases[PHASE_C_POS].ChMask = PWM_CHANNEL_5; + hpwm->AllPhases[PHASE_C_POS].htim = &hpwm2; + hpwm->AllPhases[PHASE_C_NEG].State = PWM_THYR_DISABLED; + hpwm->AllPhases[PHASE_C_NEG].ChMask = PWM_CHANNEL_6; + hpwm->AllPhases[PHASE_C_NEG].htim = &hpwm2; + + // Фаза неизвестная (чтобы не был указатель в никуда, а был на эту структуру) + hpwm->AllPhases[PHASE_UNKNOWN].State = PWM_THYR_DISABLED; + hpwm->AllPhases[PHASE_UNKNOWN].ChMask = 0; + hpwm->AllPhases[PHASE_UNKNOWN].htim = NULL; + hpwm->f.Initialized = 1; + + // Инициализируем ничем. Потом когда словим сеть - поставим конкретные тиристоры + PWM_SetHalfWave(hpwm, UPP_PHASE_A, UPP_WAVE_UNKNOWED); + PWM_SetHalfWave(hpwm, UPP_PHASE_B, UPP_WAVE_UNKNOWED); + PWM_SetHalfWave(hpwm, UPP_PHASE_C, UPP_WAVE_UNKNOWED); + + PWM_SetFrequency(hpwm, hpwm->Config.Frequency); + + HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1); + HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_2); + HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_3); + HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_4); + 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; +} + +/** + * @brief Запуск ШИМ. + * @param hpwm Указатель на хендл ШИМ тиристоров + * @param Phase На какой фазе надо запустить ШИМ + * @return HAL Status. + */ +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; + } + + + switch(hpwm->Phase[Phase]->State) + { + 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: + // переходим в состояние старта ШИМ + hpwm->Phase[Phase]->State = PWM_THYR_TIM_START; + return HAL_OK; + + default: + return HAL_ERROR;; + } + + return HAL_ERROR; +} + +/** + * @brief Остановить ШИМ. + * @param hpwm Указатель на хендл ШИМ тиристоров + * @param Phase На какой фазе надо остановить ШИМ + * @return HAL Status. + */ +HAL_StatusTypeDef PWM_Stop(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint8_t force_stop) +{ + 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; + } + + hpwm->Phase[Phase]->State = PWM_THYR_TIM_WAIT_ZERO; + + if(force_stop) + { + __PWM_SetOutputState(hpwm, Phase, PWM_DISABLE); + } + + return HAL_ERROR; +} +/** + * @brief Хендл ШИМ тиристоров. + * @param hpwm Указатель на хендл ШИМ тиристоров + * @return HAL Status. + */ +HAL_StatusTypeDef PWM_Handle(PWM_Handle_t *hpwm) +{ + if(assert_upp(hpwm)) + return HAL_ERROR; + + for(int phase = 0; phase < 3; phase++) + { + if(!read_bit(hpwm->Config.PhaseMask.all, phase)) + continue; + if (hpwm->Phase[phase] == NULL || hpwm->Phase[phase] == &hpwm->AllPhases[PHASE_UNKNOWN]) + continue; + + switch(hpwm->Phase[phase]->State) + { + case PWM_THYR_DISABLED: + __PWM_SetOutputState(hpwm, phase, PWM_DISABLE); + break; + + case PWM_THYR_TIM_WAIT_ZERO: + __PWM_SetOutputState(hpwm, phase, 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; + break; + + case PWM_THYR_TIM_ACTIVE: + hpwm->Phase[phase]->PulseCnt--; + if(hpwm->Phase[phase]->PulseCnt <= 0) + { + hpwm->Phase[phase]->PulseCnt = 0; + hpwm->Phase[phase]->State = PWM_THYR_TIM_DONE; + } + break; + + case PWM_THYR_TIM_DONE: + hpwm->Phase[phase]->State = PWM_THYR_TIM_WAIT_ZERO; + break; + + default: + __PWM_SetOutputState(hpwm, phase, PWM_DISABLE); + break; + } + } + return HAL_OK; +} + +/** + * @brief Установка полуволны для слежения. + * @param hpwm Указатель на хендл ШИМ тиристоров + * @param Phase Для какой фазы надо установить полуволну + * @param halfwave Какую полуволну установить + * @return HAL Status. + */ +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); + // Если канал дурацкий - выставляем заглушку + if(Phase >= 3) + { + hpwm->Phase[Phase] = &hpwm->AllPhases[PHASE_UNKNOWN]; + return HAL_ERROR; + } + // Выставляем канал + switch(halfwave) + { + case UPP_WAVE_POSITIVE: + hpwm->Phase[Phase] = &hpwm->AllPhases[Phase]; + return HAL_OK; + + case UPP_WAVE_NEGATIVE: + hpwm->Phase[Phase] = &hpwm->AllPhases[Phase+3]; + return HAL_OK; + + default: + hpwm->Phase[Phase] = &hpwm->AllPhases[PHASE_UNKNOWN]; + return HAL_ERROR; + } +} + +/** + * @brief Установка режима для канала ШИМ. + * @param hpwm Указатель на хендл ШИМ тиристоров + * @param Phase Для какой фазы надо установить состояние + * @param state Какое состояние установить + * @return HAL Status. + */ +static HAL_StatusTypeDef __PWM_SetOutputState(PWM_Handle_t *hpwm, UPP_Phase_t Phase, uint32_t state) +{ + if(hpwm->Phase[Phase] == NULL || hpwm->Phase[Phase] == &hpwm->AllPhases[PHASE_UNKNOWN]) + return HAL_ERROR; + + uint32_t ch_mode = state; + + + switch(hpwm->Phase[Phase]->ChMask) + { + case TIM_CHANNEL_1: + hpwm->Phase[Phase]->htim->Instance->CCMR1 &= ~TIM_OCMODE_PWM2; + hpwm->Phase[Phase]->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); + break; + case TIM_CHANNEL_3: + hpwm->Phase[Phase]->htim->Instance->CCMR2 &= ~TIM_OCMODE_PWM2; + hpwm->Phase[Phase]->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); + 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; + } +} \ No newline at end of file diff --git a/UPP/Core/UPP/pwm_thyristors.h b/UPP/Core/UPP/pwm_thyristors.h new file mode 100644 index 0000000..008f930 --- /dev/null +++ b/UPP/Core/UPP/pwm_thyristors.h @@ -0,0 +1,114 @@ +/** +****************************************************************************** +* @file pwm_thyristors.h +* @brief Модуль для управления тиристорами (объединённый 6-канальный) +****************************************************************************** +*/ +#ifndef _PWM_THYRISTORS_H +#define _PWM_THYRISTORS_H +#include "main.h" + + + + + +#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_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 +#define PHASE_A_POS 0 +#define PHASE_B_POS 1 +#define PHASE_C_POS 2 +#define PHASE_A_NEG 3 +#define PHASE_B_NEG 4 +#define PHASE_C_NEG 5 +#define PHASE_UNKNOWN 6 + + +/** + * @brief Состояния канала + */ +typedef enum { + PWM_THYR_DISABLED = 0, ///< Канал отключен + PWM_THYR_TIM_WAIT_ZERO, ///< Таймер ждет пересечения нуля + PWM_THYR_TIM_START, ///< Запуск таймера для ШИМ + PWM_THYR_TIM_ACTIVE, ///< Таймер активен и формирует ШИМ + PWM_THYR_TIM_DONE ///< Таймер закончил свою работу в полупериоде +} PWM_State_t; + +/** + * @brief Канал PWM (один тиристор) + */ +typedef struct { + PWM_State_t State; ///< Состояние тиристора + TIM_HandleTypeDef *htim; ///< указатель на соответствующий TIM (hpwm1 или hpwm2) + uint32_t PulseCnt; ///< Счетчик кол-ва импульсов. Инициализируется из структуры @ref PWM_ThyrConfig_t + uint32_t ChMask; ///< TIM_CHANNEL_x + + struct { + unsigned Ready:1; ///< Флаг готовности тиристора к работе + } f; +} PWM_Channel_t; + +/** + * @brief Канал PWM (один тиристор) + */ +typedef struct { + union + { + uint8_t all; + struct + { + uint8_t phA:1; + uint8_t phB:1; + uint8_t phC:1; + }; + }PhaseMask; ///< Какими каналами управлять + uint8_t PulseNumber; ///< Сколько импульсов отправить в пакете для открытия тиристоров + uint32_t Frequency; ///< Частота импульсов +} PWM_ThyrConfig_t; + +/** + * @brief Хендл управляюзщий тиристорами */ +typedef struct { + PWM_ThyrConfig_t Config; + PWM_Channel_t *Phase[3]; ///< Текущие каналы для фаз + PWM_Channel_t AllPhases[7]; ///< Все каналы для фаз (+1 для деинициализированного канала) + + struct { + unsigned Initialized : 1; + unsigned Running : 1; ///< true если оба таймера запущены + } f; +} PWM_Handle_t; + +/* ---- API ---- */ +/* Инициализация ШИМ тиристоров. */ +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_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); +#endif /* _PWM_THYRISTORS_H */ diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c index 052684c..729fb6c 100644 --- a/UPP/Core/UPP/upp_main.c +++ b/UPP/Core/UPP/upp_main.c @@ -6,9 +6,9 @@ * @details ******************************************************************************/ #include "upp_main.h" // всё остальное по работе с УПП -#include "power_monitor.h" // статистика сети и АЦП - -PowerMonitor_t pm; +UPP_t upp; +float alpha_dbg = 0.5; +// ОСНОВНОЙ ЦИКЛ main.c /** * @brief Инициализация УПП. @@ -17,7 +17,11 @@ PowerMonitor_t pm; int UPP_Init(void) { HAL_TIM_Base_Start(&ustim); - PowerMonitor_Init(&pm); + 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); return 0; } @@ -27,7 +31,8 @@ int UPP_Init(void) */ int UPP_PreWhile(void) { - PowerMonitor_Start(&pm); + PowerMonitor_Start(&upp.pm); + upp.hpwm.Config.PhaseMask.all = 0x7; return 0; } @@ -41,7 +46,52 @@ int UPP_While(void) return 0; } +// ПРЕРЫВАНИЯ stm32f4xx_it.c + void UPP_ADC_Handle(void) { - PowerMonitor_Handle(&pm); + PowerMonitor_Handle(&upp.pm); + + for(int phase = 0; phase < 3; phase++) + { + // Если произошел 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); + } + } +} +void UPP_PWM_Handle(void) +{ + PWM_Handle(&upp.hpwm); +} + +void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim) +{ + if (htim == upp.hangle.htim) + { + UPP_Angle_Handle(); + } +} + +void UPP_Angle_Handle(void) +{ + UPP_Phase_t phase = Angle_Handle(&upp.hangle); + 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; + } } \ No newline at end of file diff --git a/UPP/Core/UPP/upp_main.h b/UPP/Core/UPP/upp_main.h index 5ba7672..54b3f56 100644 --- a/UPP/Core/UPP/upp_main.h +++ b/UPP/Core/UPP/upp_main.h @@ -11,7 +11,19 @@ #include "main.h" // либы из AllLibs и вербальные имена из CubeMX #include "upp_config.h" +#include "power_monitor.h" // статистика сети и АЦП +#include "pwm_thyristors.h" // Управление тиристорами +#include "angle_control.h" // Управление углом открытия +extern float alpha_dbg; + +typedef struct +{ + PowerMonitor_t pm; + PWM_Handle_t hpwm; + Angle_Handle_t hangle; +}UPP_t; +extern UPP_t upp; /* Инициализация УПП */ @@ -22,4 +34,6 @@ int UPP_PreWhile(void); int UPP_While(void); void UPP_ADC_Handle(void); +void UPP_PWM_Handle(void); +void UPP_Angle_Handle(void); #endif //_UPP_MAIN_H \ No newline at end of file diff --git a/UPP/MDK-ARM/UPP.uvoptx b/UPP/MDK-ARM/UPP.uvoptx index ba12a47..7736db4 100644 --- a/UPP/MDK-ARM/UPP.uvoptx +++ b/UPP/MDK-ARM/UPP.uvoptx @@ -327,6 +327,54 @@ 0 0 + + 2 + 12 + 1 + 0 + 0 + 0 + ..\Core\UPP\pwm_thyristors.c + pwm_thyristors.c + 0 + 0 + + + 2 + 13 + 5 + 0 + 0 + 0 + ..\Core\UPP\pwm_thyristors.h + pwm_thyristors.h + 0 + 0 + + + 2 + 14 + 1 + 0 + 0 + 0 + ..\Core\UPP\angle_control.c + angle_control.c + 0 + 0 + + + 2 + 15 + 5 + 0 + 0 + 0 + ..\Core\UPP\angle_control.h + angle_control.h + 0 + 0 + @@ -337,7 +385,7 @@ 0 3 - 12 + 16 1 0 0 @@ -349,7 +397,7 @@ 3 - 13 + 17 5 0 0 @@ -361,7 +409,7 @@ 3 - 14 + 18 1 0 0 @@ -373,7 +421,7 @@ 3 - 15 + 19 5 0 0 @@ -385,7 +433,7 @@ 3 - 16 + 20 1 0 0 @@ -397,7 +445,7 @@ 3 - 17 + 21 5 0 0 @@ -409,14 +457,6 @@ - - Thyristors - 0 - 0 - 0 - 0 - - Application/User/Core 1 @@ -424,8 +464,8 @@ 0 0 - 5 - 18 + 4 + 22 1 0 0 @@ -436,8 +476,8 @@ 0 - 5 - 19 + 4 + 23 1 0 0 @@ -448,8 +488,8 @@ 0 - 5 - 20 + 4 + 24 1 0 0 @@ -460,8 +500,8 @@ 0 - 5 - 21 + 4 + 25 1 0 0 @@ -472,8 +512,8 @@ 0 - 5 - 22 + 4 + 26 1 0 0 @@ -484,8 +524,8 @@ 0 - 5 - 23 + 4 + 27 1 0 0 @@ -496,8 +536,8 @@ 0 - 5 - 24 + 4 + 28 1 0 0 @@ -508,8 +548,8 @@ 0 - 5 - 25 + 4 + 29 1 0 0 @@ -520,8 +560,8 @@ 0 - 5 - 26 + 4 + 30 1 0 0 @@ -532,8 +572,8 @@ 0 - 5 - 27 + 4 + 31 1 0 0 @@ -544,8 +584,8 @@ 0 - 5 - 28 + 4 + 32 1 0 0 @@ -556,8 +596,8 @@ 0 - 5 - 29 + 4 + 33 1 0 0 @@ -568,8 +608,8 @@ 0 - 5 - 30 + 4 + 34 1 0 0 @@ -588,8 +628,8 @@ 0 0 - 6 - 31 + 5 + 35 5 0 0 @@ -600,8 +640,8 @@ 0 - 6 - 32 + 5 + 36 5 0 0 @@ -612,8 +652,8 @@ 0 - 6 - 33 + 5 + 37 5 0 0 @@ -624,8 +664,8 @@ 0 - 6 - 34 + 5 + 38 5 0 0 @@ -636,8 +676,8 @@ 0 - 6 - 35 + 5 + 39 5 0 0 @@ -648,8 +688,8 @@ 0 - 6 - 36 + 5 + 40 5 0 0 @@ -660,8 +700,8 @@ 0 - 6 - 37 + 5 + 41 1 0 0 @@ -672,8 +712,8 @@ 0 - 6 - 38 + 5 + 42 5 0 0 @@ -692,8 +732,8 @@ 0 0 - 7 - 39 + 6 + 43 1 0 0 @@ -704,8 +744,8 @@ 0 - 7 - 40 + 6 + 44 1 0 0 @@ -716,8 +756,8 @@ 0 - 7 - 41 + 6 + 45 1 0 0 @@ -728,8 +768,8 @@ 0 - 7 - 42 + 6 + 46 1 0 0 @@ -740,8 +780,8 @@ 0 - 7 - 43 + 6 + 47 1 0 0 @@ -752,8 +792,8 @@ 0 - 7 - 44 + 6 + 48 1 0 0 @@ -764,8 +804,8 @@ 0 - 7 - 45 + 6 + 49 1 0 0 @@ -776,8 +816,8 @@ 0 - 7 - 46 + 6 + 50 1 0 0 @@ -788,8 +828,8 @@ 0 - 7 - 47 + 6 + 51 1 0 0 @@ -800,8 +840,8 @@ 0 - 7 - 48 + 6 + 52 1 0 0 @@ -812,8 +852,8 @@ 0 - 7 - 49 + 6 + 53 1 0 0 @@ -824,8 +864,8 @@ 0 - 7 - 50 + 6 + 54 1 0 0 @@ -844,8 +884,8 @@ 0 0 - 8 - 51 + 7 + 55 1 0 0 @@ -856,8 +896,8 @@ 0 - 8 - 52 + 7 + 56 1 0 0 @@ -871,13 +911,13 @@ PeriphGeneral - 0 + 1 0 0 0 - 9 - 53 + 8 + 57 1 0 0 @@ -888,8 +928,8 @@ 0 - 9 - 54 + 8 + 58 1 0 0 @@ -900,8 +940,8 @@ 0 - 9 - 55 + 8 + 59 1 0 0 @@ -912,8 +952,8 @@ 0 - 9 - 56 + 8 + 60 1 0 0 @@ -924,8 +964,8 @@ 0 - 9 - 57 + 8 + 61 1 0 0 @@ -944,8 +984,8 @@ 0 0 - 10 - 58 + 9 + 62 1 0 0 @@ -956,8 +996,8 @@ 0 - 10 - 59 + 9 + 63 1 0 0 @@ -968,8 +1008,8 @@ 0 - 10 - 60 + 9 + 64 1 0 0 @@ -980,8 +1020,8 @@ 0 - 10 - 61 + 9 + 65 1 0 0 @@ -992,8 +1032,8 @@ 0 - 10 - 62 + 9 + 66 1 0 0 @@ -1004,8 +1044,8 @@ 0 - 10 - 63 + 9 + 67 1 0 0 @@ -1016,8 +1056,8 @@ 0 - 10 - 64 + 9 + 68 1 0 0 @@ -1028,8 +1068,8 @@ 0 - 10 - 65 + 9 + 69 1 0 0 @@ -1040,8 +1080,8 @@ 0 - 10 - 66 + 9 + 70 1 0 0 @@ -1052,8 +1092,8 @@ 0 - 10 - 67 + 9 + 71 1 0 0 @@ -1064,8 +1104,8 @@ 0 - 10 - 68 + 9 + 72 1 0 0 @@ -1076,8 +1116,8 @@ 0 - 10 - 69 + 9 + 73 1 0 0 @@ -1088,8 +1128,8 @@ 0 - 10 - 70 + 9 + 74 1 0 0 @@ -1100,8 +1140,8 @@ 0 - 10 - 71 + 9 + 75 1 0 0 @@ -1112,8 +1152,8 @@ 0 - 10 - 72 + 9 + 76 1 0 0 @@ -1124,8 +1164,8 @@ 0 - 10 - 73 + 9 + 77 1 0 0 @@ -1136,8 +1176,8 @@ 0 - 10 - 74 + 9 + 78 1 0 0 @@ -1148,8 +1188,8 @@ 0 - 10 - 75 + 9 + 79 1 0 0 @@ -1160,8 +1200,8 @@ 0 - 10 - 76 + 9 + 80 1 0 0 @@ -1172,8 +1212,8 @@ 0 - 10 - 77 + 9 + 81 1 0 0 @@ -1184,8 +1224,8 @@ 0 - 10 - 78 + 9 + 82 1 0 0 @@ -1196,8 +1236,8 @@ 0 - 10 - 79 + 9 + 83 1 0 0 @@ -1208,8 +1248,8 @@ 0 - 10 - 80 + 9 + 84 1 0 0 @@ -1220,8 +1260,8 @@ 0 - 10 - 81 + 9 + 85 1 0 0 @@ -1240,8 +1280,8 @@ 0 0 - 11 - 82 + 10 + 86 1 0 0 @@ -1260,8 +1300,8 @@ 0 0 - 12 - 83 + 11 + 87 2 0 0 diff --git a/UPP/MDK-ARM/UPP.uvprojx b/UPP/MDK-ARM/UPP.uvprojx index 6284731..585e041 100644 --- a/UPP/MDK-ARM/UPP.uvprojx +++ b/UPP/MDK-ARM/UPP.uvprojx @@ -445,6 +445,26 @@ 5 ..\Core\UPP\upp_main.h + + pwm_thyristors.c + 1 + ..\Core\UPP\pwm_thyristors.c + + + pwm_thyristors.h + 5 + ..\Core\UPP\pwm_thyristors.h + + + angle_control.c + 1 + ..\Core\UPP\angle_control.c + + + angle_control.h + 5 + ..\Core\UPP\angle_control.h + @@ -482,9 +502,6 @@ - - Thyristors - Application/User/Core diff --git a/UPP/UPP.ioc b/UPP/UPP.ioc index af2d530..5ed5897 100644 --- a/UPP/UPP.ioc +++ b/UPP/UPP.ioc @@ -54,13 +54,14 @@ Mcu.CPN=STM32F427ZGT6 Mcu.Family=STM32F4 Mcu.IP0=ADC3 Mcu.IP1=CAN1 -Mcu.IP10=TIM3 -Mcu.IP11=TIM5 -Mcu.IP12=TIM8 -Mcu.IP13=TIM11 -Mcu.IP14=TIM12 -Mcu.IP15=USART3 -Mcu.IP16=USART6 +Mcu.IP10=TIM2 +Mcu.IP11=TIM3 +Mcu.IP12=TIM5 +Mcu.IP13=TIM8 +Mcu.IP14=TIM11 +Mcu.IP15=TIM12 +Mcu.IP16=USART3 +Mcu.IP17=USART6 Mcu.IP2=DMA Mcu.IP3=IWDG Mcu.IP4=NVIC @@ -69,7 +70,7 @@ Mcu.IP6=RTC Mcu.IP7=SPI3 Mcu.IP8=SYS Mcu.IP9=TIM1 -Mcu.IPNb=17 +Mcu.IPNb=18 Mcu.Name=STM32F427Z(G-I)Tx Mcu.Package=LQFP144 Mcu.Pin0=PE2 @@ -127,17 +128,25 @@ Mcu.Pin55=VP_RTC_VS_RTC_Activate Mcu.Pin56=VP_RTC_VS_RTC_Calendar Mcu.Pin57=VP_SYS_VS_tim14 Mcu.Pin58=VP_TIM1_VS_ClockSourceINT -Mcu.Pin59=VP_TIM3_VS_ClockSourceINT +Mcu.Pin59=VP_TIM1_VS_OPM Mcu.Pin6=PC14/OSC32_IN -Mcu.Pin60=VP_TIM8_VS_ClockSourceINT -Mcu.Pin61=VP_TIM11_VS_ClockSourceINT -Mcu.Pin62=VP_TIM12_VS_ClockSourceINT +Mcu.Pin60=VP_TIM2_VS_ClockSourceINT +Mcu.Pin61=VP_TIM2_VS_no_output1 +Mcu.Pin62=VP_TIM2_VS_no_output2 +Mcu.Pin63=VP_TIM2_VS_no_output3 +Mcu.Pin64=VP_TIM3_VS_ControllerModeTrigger +Mcu.Pin65=VP_TIM3_VS_ClockSourceINT +Mcu.Pin66=VP_TIM3_VS_ClockSourceITR +Mcu.Pin67=VP_TIM3_VS_OPM +Mcu.Pin68=VP_TIM8_VS_ClockSourceINT +Mcu.Pin69=VP_TIM11_VS_ClockSourceINT Mcu.Pin7=PC15/OSC32_OUT +Mcu.Pin70=VP_TIM12_VS_ClockSourceINT Mcu.Pin8=PF6 Mcu.Pin9=PF7 -Mcu.PinsNb=63 +Mcu.PinsNb=71 Mcu.ThirdPartyNb=0 -Mcu.UserConstants=mb_huart,huart3;mbdbg_htim,htim11;PWM_CHANNEL_1,TIM_CHANNEL_1;PWM_CHANNEL_2,TIM_CHANNEL_2;PWM_CHANNEL_3,TIM_CHANNEL_3;PWM_CHANNEL_4,TIM_CHANNEL_4;mem_hspi,hspi3;PWM_CHANNEL_5,TIM_CHANNEL_3;PWM_CHANNEL_6,TIM_CHANNEL_4;mb_htim,htim12;adc_tim,htim8;hpwm2,htim2;mb_dbg_huart,huart6;ustim,htim5;hpwm1,htim1;usTick,ustim.Instance->CNT +Mcu.UserConstants=mb_huart,huart3;mbdbg_htim,htim11;PWM_CHANNEL_1,TIM_CHANNEL_1;PWM_CHANNEL_2,TIM_CHANNEL_2;PWM_CHANNEL_3,TIM_CHANNEL_3;PWM_CHANNEL_4,TIM_CHANNEL_4;mem_hspi,hspi3;PWM_CHANNEL_5,TIM_CHANNEL_3;PWM_CHANNEL_6,TIM_CHANNEL_4;mb_htim,htim12;adc_tim,htim8;usTick,ustim.Instance->CNT;hpwm2,htim3;mb_dbg_huart,huart6;ustim,htim5;hpwm1,htim1;ANGLE_CHANNEL_1,TIM_CHANNEL_1;ANGLE_CHANNEL_2,TIM_CHANNEL_2;ANGLE_CHANNEL_3,TIM_CHANNEL_3;angletim,htim2 Mcu.UserName=STM32F427ZGTx MxCube.Version=6.12.1 MxDb.Version=DB.6.0.121 @@ -152,6 +161,8 @@ NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false +NVIC.TIM1_UP_TIM10_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true +NVIC.TIM2_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true NVIC.TIM8_TRG_COM_TIM14_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:true NVIC.TimeBase=TIM8_TRG_COM_TIM14_IRQn NVIC.TimeBaseIP=TIM14 @@ -395,7 +406,7 @@ ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=false -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-true-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_ADC3_Init-ADC3-false-HAL-true,5-MX_USART3_UART_Init-USART3-false-HAL-true,6-MX_CAN1_Init-CAN1-false-HAL-true,7-MX_IWDG_Init-IWDG-false-HAL-true,8-MX_TIM13_Init-TIM13-false-HAL-true,8-MX_RTC_Init-RTC-false-HAL-true,9-MX_TIM1_Init-TIM1-false-HAL-true,10-MX_TIM3_Init-TIM3-false-HAL-true,11-MX_USART6_UART_Init-USART6-false-HAL-true,12-MX_SPI3_Init-SPI3-false-HAL-true,13-MX_TIM11_Init-TIM11-false-HAL-true,14-MX_TIM12_Init-TIM12-false-HAL-true,15-MX_TIM8_Init-TIM8-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-true-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_ADC3_Init-ADC3-false-HAL-true,5-MX_USART3_UART_Init-USART3-false-HAL-true,6-MX_CAN1_Init-CAN1-false-HAL-true,7-MX_IWDG_Init-IWDG-false-HAL-true,8-MX_RTC_Init-RTC-false-HAL-true,9-MX_TIM1_Init-TIM1-false-HAL-true,10-MX_TIM3_Init-TIM3-false-HAL-true,11-MX_USART6_UART_Init-USART6-false-HAL-true,12-MX_SPI3_Init-SPI3-false-HAL-true,13-MX_TIM11_Init-TIM11-false-HAL-true,14-MX_TIM12_Init-TIM12-false-HAL-true,15-MX_TIM8_Init-TIM8-false-HAL-true,16-MX_TIM5_Init-TIM5-false-HAL-true,17-MX_TIM2_Init-TIM2-false-HAL-true RCC.48MHZClocksFreq_Value=90000000 RCC.AHBFreq_Value=180000000 RCC.APB1CLKDivider=RCC_HCLK_DIV4 @@ -461,19 +472,30 @@ SPI3.Direction=SPI_DIRECTION_2LINES SPI3.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate SPI3.Mode=SPI_MODE_MASTER SPI3.VirtualType=VM_MASTER +TIM1.Channel-Output\ Compare2\ CH2=TIM_CHANNEL_2 TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1 TIM1.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2 TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 TIM1.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 -TIM1.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4,Prescaler -TIM1.Prescaler=180-1 +TIM1.IPParameters=Prescaler,Channel-Output Compare2 CH2,Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation4 CH4,Channel-PWM Generation3 CH3,TIM_MasterOutputTrigger +TIM1.Prescaler=0 +TIM1.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE TIM11.IPParameters=Prescaler TIM11.Prescaler=180-1 TIM12.IPParameters=Prescaler TIM12.Prescaler=90-1 +TIM2.Channel-Output\ Compare1\ No\ Output=TIM_CHANNEL_1 +TIM2.Channel-Output\ Compare2\ No\ Output=TIM_CHANNEL_2 +TIM2.Channel-Output\ Compare3\ No\ Output=TIM_CHANNEL_3 +TIM2.IPParameters=Channel-Output Compare2 No Output,Channel-Output Compare1 No Output,Channel-Output Compare3 No Output,OCMode_1,OCMode_2,OCMode_3 +TIM2.OCMode_1=TIM_OCMODE_TIMING +TIM2.OCMode_2=TIM_OCMODE_TIMING +TIM2.OCMode_3=TIM_OCMODE_TIMING TIM3.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 TIM3.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 -TIM3.IPParameters=Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4 +TIM3.IPParameters=Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4,TIM_MasterSlaveMode,TIM_MasterOutputTrigger +TIM3.TIM_MasterOutputTrigger=TIM_TRGO_RESET +TIM3.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_ENABLE TIM5.Channel-Input_Capture1_from_TI1=TIM_CHANNEL_1 TIM5.IPParameters=Channel-Input_Capture1_from_TI1,Prescaler TIM5.Prescaler=90-1 @@ -500,8 +522,24 @@ VP_TIM12_VS_ClockSourceINT.Mode=Internal VP_TIM12_VS_ClockSourceINT.Signal=TIM12_VS_ClockSourceINT VP_TIM1_VS_ClockSourceINT.Mode=Internal VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT +VP_TIM1_VS_OPM.Mode=OPM_bit +VP_TIM1_VS_OPM.Signal=TIM1_VS_OPM +VP_TIM2_VS_ClockSourceINT.Mode=Internal +VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT +VP_TIM2_VS_no_output1.Mode=Output Compare1 No Output +VP_TIM2_VS_no_output1.Signal=TIM2_VS_no_output1 +VP_TIM2_VS_no_output2.Mode=Output Compare2 No Output +VP_TIM2_VS_no_output2.Signal=TIM2_VS_no_output2 +VP_TIM2_VS_no_output3.Mode=Output Compare3 No Output +VP_TIM2_VS_no_output3.Signal=TIM2_VS_no_output3 VP_TIM3_VS_ClockSourceINT.Mode=Internal VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT +VP_TIM3_VS_ClockSourceITR.Mode=TriggerSource_ITR0 +VP_TIM3_VS_ClockSourceITR.Signal=TIM3_VS_ClockSourceITR +VP_TIM3_VS_ControllerModeTrigger.Mode=Trigger Mode +VP_TIM3_VS_ControllerModeTrigger.Signal=TIM3_VS_ControllerModeTrigger +VP_TIM3_VS_OPM.Mode=OPM_bit +VP_TIM3_VS_OPM.Signal=TIM3_VS_OPM VP_TIM8_VS_ClockSourceINT.Mode=Internal VP_TIM8_VS_ClockSourceINT.Signal=TIM8_VS_ClockSourceINT board=custom