diplom/научка/code/pwm_motor_control/PWM/pwm.c
2025-05-09 21:26:59 +03:00

1085 lines
38 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "pwm.h"
#include "rng.h"
PWM_HandleTypeDef hpwm1;
PWM_SlaveHandleTypeDef hpwm2;
PWM_SlaveHandleTypeDef hpwm3;
uint32_t sin_table[SIN_TABLE_SIZE_MAX];
unsigned ActiveChannelSHDW_Master;
float DeadTimeCnt_Master;
unsigned ActiveChannelSHDW_Slave2;
float DeadTimeCnt_Slave2;
float shiftPHASE1= 0.6666666666;
float shiftPHASE2= 0.3333333333;
unsigned ActiveChannelSHDW_Slave3;
float DeadTimeCnt_Slave3;
/**
* @brief First set up of PWM.
* @note Первый инит ШИМ. Заполняет структуры и инициализирует таймер для генерации синуоидального ШИМ.
* Скважность ШИМ меняется по закону синусоиды, каждый канал генерирует свой полупериод синуса (от -1 до 0 И от 0 до 1)
* ШИМ генерируется на одном канале.
* @note This called from main
*/
void PWM_Sine_FirstInit(void)
{
hpwm1.sPWM_Config.PWM_Mode = (PWM_ModeCoilsTypeDef *)&coils_regs[0];
hpwm1.sPWM_Config.PWM_Settings = (PWM_ModeRegsTypeDef *)&pwm_ctrl[0];
// PWM RAMP INIT
hpwm1.pDuty_Table_Origin = SIN_TABLE_ORIGIN;
hpwm1.hramp.Kp = 0;
hpwm1.hramp.Ki = PWM_RAMP_SPEED;
hpwm1.hramp.Kd = 0;
hpwm1.hramp.limMax = 656;
hpwm1.hramp.limMin = 0;
hpwm1.hramp.limMaxInt = 20;
hpwm1.hramp.limMinInt = -20;
hpwm1.hramp.SampleT = (1.0f/HZ_TIMER_CTRL);
// PWM CONTROL PINS INIT
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_Clock_Enable(GPIOC);
GPIO_InitStruct.Pin = GPIO_PIN_0 ;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIOC->ODR|=1<<0;//подача 0 разрешает . Аппаратное разрешение и запрет не подачу шим . Cигнал идет на логический элемент & 74AC08d
GPIO_InitStruct.Pin = GPIO_PIN_1 ;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT ;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); //кнопка для вкл аппаратно шим 74AC08d
//---------PWM TIMER1 INIT------------
// channels settings
hpwm1.sConfigOC.OCMode = TIM_OCMODE_PWM1;
hpwm1.sConfigOC.Pulse = 0;
hpwm1.sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
//hpwm1.sConfigOC.OCNPolarity=TIM_OCNPOLARITY_LOW;
hpwm1.sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
// tim1 settings
hpwm1.stim.htim.Instance = TIMER_PWM1_INSTANCE;
hpwm1.stim.sTimMode = TIM_IT_MODE;
hpwm1.stim.sTimFreqHz = HZ_TIMER_PWM;
hpwm1.stim.sTickBaseMHz = PROJSET.TIM_PWM_TICKBASE;
hpwm1.stim.sTimAHBFreqMHz = PROJSET.TIM_PWM_AHB_FREQ;
hpwm1.GPIOx = TIMER_PWM1_GPIOx;
hpwm1.GPIO_PIN_X1 = PROJSET.TIM_PWM1_GPIO_PIN_X1;
hpwm1.GPIO_PIN_X2 = PROJSET.TIM_PWM1_GPIO_PIN_X2;
hpwm1.PWM_Channel1 = PROJSET.TIM_PWM1_TIM_CHANNEL1;
hpwm1.PWM_Channel2 = PROJSET.TIM_PWM1_TIM_CHANNEL2;
hpwm1.hpwm2 = (void *)&hpwm2;
hpwm1.hpwm3 = (void *)&hpwm3;
TIM_Base_Init(&hpwm1.stim);
TIM_Output_PWM_Init(&hpwm1.stim.htim, &hpwm1.sConfigOC, hpwm1.PWM_Channel1, hpwm1.GPIOx, hpwm1.GPIO_PIN_X1);
TIM_Output_PWM_Init(&hpwm1.stim.htim, &hpwm1.sConfigOC, hpwm1.PWM_Channel2, hpwm1.GPIOx, hpwm1.GPIO_PIN_X2);
// PWM SLAVES INIT
hpwm2.hMasterPWM = &hpwm1;
hpwm2.stim = hpwm1.stim;
hpwm2.stim.htim.Instance = (TIM_TypeDef *)PROJSET.TIM_PWM2_INSTANCE;
hpwm2.GPIOx = (GPIO_TypeDef *)PROJSET.TIM_PWM2_GPIOx;
hpwm2.GPIO_PIN_X1 = PROJSET.TIM_PWM2_GPIO_PIN_X1;
hpwm2.GPIO_PIN_X2 = PROJSET.TIM_PWM2_GPIO_PIN_X2;
hpwm2.PWM_Channel1 = PROJSET.TIM_PWM2_TIM_CHANNEL1;
hpwm2.PWM_Channel2 = PROJSET.TIM_PWM2_TIM_CHANNEL2;
//hpwm2.Duty_Shift_Ratio = shiftPHASE1;
hpwm2.Duty_Shift_Ratio = shiftPHASE1;
hpwm3.hMasterPWM = &hpwm1;
hpwm3.stim = hpwm1.stim;
hpwm3.stim.htim.Instance = (TIM_TypeDef *)PROJSET.TIM_PWM3_INSTANCE;
hpwm3.GPIOx = (GPIO_TypeDef *)PROJSET.TIM_PWM3_GPIOx;
hpwm3.GPIO_PIN_X1 = PROJSET.TIM_PWM3_GPIO_PIN_X1;
hpwm3.GPIO_PIN_X2 = PROJSET.TIM_PWM3_GPIO_PIN_X2;
hpwm3.PWM_Channel1 = PROJSET.TIM_PWM3_TIM_CHANNEL1;
hpwm3.PWM_Channel2 = PROJSET.TIM_PWM3_TIM_CHANNEL2;
//hpwm3.Duty_Shift_Ratio = shiftPHASE2;
hpwm3.Duty_Shift_Ratio = shiftPHASE2;
PWM_SlavePhase_Init(&hpwm2);
PWM_SlavePhase_Init(&hpwm3);
//----------TIMERS START-------------
HAL_TIM_Base_Start_IT(&hpwm1.stim.htim); // timer for PWM
HAL_TIM_PWM_Start(&hpwm1.stim.htim, hpwm1.PWM_Channel1); // PWM channel 1
HAL_TIM_PWM_Start(&hpwm1.stim.htim, hpwm1.PWM_Channel2); // PWM channel 2
}
/**
* @brief PWM Handler.
* @param hpwm - указатель на хендл ШИМ.
* @note Управляет скважностью ШИМ.
* @note This called from TIM_PWM_Handler
*/
void PWM_Handler(PWM_HandleTypeDef *hpwm)
{
uint16_t rotate_ind_A;
uint16_t rotate_ind_B;
uint16_t rotate_ind_C;
// rotate pwm
rotate_ind_A = PWM_Get_Duty_Table_Ind(hpwm, hpwm->stim.sTimFreqHz);
if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE))
{
rotate_ind_B = PWM_SlavePhase_Calc_TableInd(PWM_Set_pSlaveHandle(hpwm,hpwm2), rotate_ind_A);
rotate_ind_C = PWM_SlavePhase_Calc_TableInd(PWM_Set_pSlaveHandle(hpwm,hpwm3), rotate_ind_A);
}
if(hpwm->PWM_Value == 0) // if value = 0 reset all channels
{
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
return;
}
//--------BRIDGE MODE DISABLE--------
if(PWM_Get_Mode(&hpwm1,PWM_BRIDGE_MODE) == 0)
{
//-----------PWM DC MODE-------------
if(PWM_Get_Mode(&hpwm1,PWM_DC_MODE))
PWM_SingleChannel_Mode(hpwm, rotate_ind_A, 0);
//------------SINUS MODE-------------
else
PWM_SingleChannel_Mode(hpwm, rotate_ind_A, 1);
}
//---------BRIDGE MODE ENABLE--------
else
{
if(PWM_Get_Mode(&hpwm1,PWM_DC_MODE))
//-----------PWM DC MODE-------------
PWM_DC_Bridge_Mode(hpwm, rotate_ind_A, rotate_ind_B, rotate_ind_C);
//------------SINUS MODE-------------
else
PWM_Sine_Bridge_Mode(hpwm, rotate_ind_A, rotate_ind_B, rotate_ind_C);
}
//-----CHECK CHANNELS FOR ERRORS-----
uint16_t min_duty = PWM_Calc_Min_Duty(hpwm);
uint16_t max_duty = PWM_Calc_Max_Duty(hpwm);
// IF FIRST CHANNEL IS ACRIVE
if(PWM_Get_Compare1(hpwm) != 0)
{
// Duty shoud be bigger or equeal than min duration
if (PWM_Get_Compare1(hpwm)<min_duty)
PWM_Set_Compare1(hpwm, min_duty);
// Duty shoud be less or equeal than ARR-min duration
if (PWM_Get_Compare1(hpwm)>max_duty)
PWM_Set_Compare1(hpwm, max_duty);
}
// IF SECOND CHANNEL IS ACRIVE
else if(PWM_Get_Compare2(hpwm) != 0)
{
// Duty shoud be bigger or equeal than min duration
if (PWM_Get_Compare2(hpwm)<min_duty)
PWM_Set_Compare2(hpwm, min_duty);
// Duty shoud be less or equeal than ARR
if (PWM_Get_Compare2(hpwm)>max_duty)
PWM_Set_Compare2(hpwm, max_duty);
}
// IF BOTH CHANNEL IS ACRIVE
if((PWM_Get_Compare1(hpwm) != 0) && (PWM_Get_Compare2(hpwm) != 0))
{
// Only one channel shoud be active so disable all
PWM_Set_Compare1(hpwm, 0);
PWM_Set_Compare2(hpwm, 0);
}
PWM_SlavePhase_Check_Channels(PWM_Set_pSlaveHandle(hpwm,hpwm2));
PWM_SlavePhase_Check_Channels(PWM_Set_pSlaveHandle(hpwm,hpwm3));
if(hpwm->PWM_DeadTime)
{
PWM_CreateDeadTime(hpwm, &DeadTimeCnt_Master, &ActiveChannelSHDW_Master);
PWM_SlavePhase_CreateDeadTime(PWM_Set_pSlaveHandle(hpwm,hpwm2), &DeadTimeCnt_Slave2, &ActiveChannelSHDW_Slave2);
PWM_SlavePhase_CreateDeadTime(PWM_Set_pSlaveHandle(hpwm,hpwm3), &DeadTimeCnt_Slave3, &ActiveChannelSHDW_Slave3);
}
}
///**
// * @brief .
// * @param hspwm - указатель на хендл слейв ШИМ.
// * @param sin_ind - индекс таблицы для Мастер ШИМ.
// * @note Индекс для свейл ШИМ расчитывается в самой функции.
// */
//void PWM_Sine_SingleChannel_Mode(PWM_HandleTypeDef *hpwm, uint16_t rotate_ind_A, uint16_t rotate_ind_B, uint16_t rotate_ind_C)
//{
// //----------MASTER PWM-----------
// PWM_Set_Duty_From_Table(hpwm, rotate_ind_A); // set phase 1 (A)
//
// //----------SLAVE PWMs-----------
// if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE))
// {
// PWM_SlaveHandleTypeDef *hspwm = PWM_Set_pSlaveHandle(hpwm,hpwm2);
// PWM_Set_SlaveDuty_From_Table(hspwm, rotate_ind_B); // set phase 2 (B)
//
// hspwm = PWM_Set_pSlaveHandle(hpwm,hpwm3);
// PWM_Set_SlaveDuty_From_Table(hspwm, rotate_ind_C); // set phase 3 (C)
// }
//}
/**
* @brief .
* @param hspwm - указатель на хендл слейв ШИМ.
* @param sin_ind - индекс таблицы для Мастер ШИМ.
* @note Индекс для свейл ШИМ расчитывается в самой функции.
*/
void PWM_Sine_Bridge_Mode(PWM_HandleTypeDef *hpwm, uint16_t rotate_ind_A, uint16_t rotate_ind_B, uint16_t rotate_ind_C)
{
//----------MASTER PWM-----------
// SET PHASE 1 (A)
int Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_A);
// если это первая полуволна
if(Duty >= 0) {
PWM_Set_Compare1(hpwm, Duty+PWM_Calc_Min_Duty(hpwm)); // set first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
}
// если это вторая полуволна
else {
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Compare2(hpwm, (-Duty)+PWM_Calc_Min_Duty(hpwm)); // set second channel
}
//----------SLAVE PWMs-----------
if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE))
{
// SET PHASE 2 (B)
PWM_SlaveHandleTypeDef *hspwm = PWM_Set_pSlaveHandle(hpwm,hpwm2);
Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_B);
// если это первая полуволна
if(Duty > 0) {
PWM_Set_Compare1(hspwm, Duty+PWM_Calc_Min_Duty(hspwm->hMasterPWM)); // set first channel
PWM_Set_Compare2(hspwm, 0); // reset second channel
}
// если это вторая полуволна
else {
PWM_Set_Compare1(hspwm, 0); // reset first channel
PWM_Set_Compare2(hspwm, (-Duty)+PWM_Calc_Min_Duty(hspwm->hMasterPWM)); // set second channel
}
// SET PHASE 3 (C)
hspwm = PWM_Set_pSlaveHandle(hpwm,hpwm3);
Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_C);
// если это первая полуволна
if(Duty > 0) {
PWM_Set_Compare1(hspwm, Duty+PWM_Calc_Min_Duty(hspwm->hMasterPWM)); // set first channel
PWM_Set_Compare2(hspwm, 0); // reset second channel
}
// если это вторая полуволна
else {
PWM_Set_Compare1(hspwm, 0); // reset first channel
PWM_Set_Compare2(hspwm, (-Duty)+PWM_Calc_Min_Duty(hspwm->hMasterPWM)); // set second channel
}
}
else
{
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
}
}
/**
* @brief .
* @param hspwm - указатель на хендл слейв ШИМ.
* @param sin_ind - индекс таблицы для Мастер ШИМ.
* @note Индекс для свейл ШИМ расчитывается в самой функции.
*/
void PWM_SingleChannel_Mode(PWM_HandleTypeDef *hpwm, uint16_t rotate_ind_A, uint8_t SineOrDC)
{
PWM_SlaveHandleTypeDef *hspwm2 = PWM_Set_pSlaveHandle(hpwm,hpwm2);
PWM_SlaveHandleTypeDef *hspwm3 = PWM_Set_pSlaveHandle(hpwm,hpwm3);
// PWM_Set_Compare1(hpwm, 0); // reset first channel
// PWM_Set_Compare2(hpwm, 0); // reset second channel
// PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
// PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
// PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
// PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
switch(PWM_Get_Mode(hpwm, PWM_ACTIVECHANNEL_MODE))
{
case PWM_ACTIVECHANNEL_A0:
if(SineOrDC)
PWM_Set_Duty_From_Table(hpwm, hpwm->PWM_Channel1, rotate_ind_A);
else
PWM_Set_Duty_From_Value(hpwm, hpwm->PWM_Channel1); // set first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
break;
case PWM_ACTIVECHANNEL_A1:
if(SineOrDC)
PWM_Set_Duty_From_Table(hpwm, hpwm->PWM_Channel2, rotate_ind_A);
else
PWM_Set_Duty_From_Value(hpwm, hpwm->PWM_Channel2); // set second channel
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
break;
case PWM_ACTIVECHANNEL_B0:
if(SineOrDC)
PWM_Set_SlaveDuty_From_Table(hspwm2, hspwm2->PWM_Channel1, rotate_ind_A);
else
PWM_Set_SlaveDuty_From_Value(hspwm2, hspwm2->PWM_Channel1); // set first channel
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
break;
case PWM_ACTIVECHANNEL_B1:
if(SineOrDC)
PWM_Set_SlaveDuty_From_Table(hspwm2, hspwm2->PWM_Channel2, rotate_ind_A);
else
PWM_Set_SlaveDuty_From_Value(hspwm2, hspwm2->PWM_Channel2); // set second channel
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
break;
case PWM_ACTIVECHANNEL_C0:
if(SineOrDC)
PWM_Set_SlaveDuty_From_Table(hspwm3, hspwm3->PWM_Channel1, rotate_ind_A);
else
PWM_Set_SlaveDuty_From_Value(hspwm3, hspwm3->PWM_Channel1); // set first channel
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
break;
case PWM_ACTIVECHANNEL_C1:
if(SineOrDC)
PWM_Set_SlaveDuty_From_Table(hspwm3, hspwm3->PWM_Channel2, rotate_ind_A);
else
PWM_Set_SlaveDuty_From_Value(hspwm3, hspwm3->PWM_Channel2); // set second channel
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
break;
default:
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
break;
}
}
/**
* @brief .
* @param hspwm - указатель на хендл слейв ШИМ.
* @param sin_ind - индекс таблицы для Мастер ШИМ.
* @note Индекс для свейл ШИМ расчитывается в самой функции.
*/
void PWM_DC_Bridge_Mode(PWM_HandleTypeDef *hpwm, uint16_t rotate_ind_A, uint16_t rotate_ind_B, uint16_t rotate_ind_C)
{
//----------MASTER PWM-----------
// SET PHASE 1 (A)
int Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_A);
// если это первая полуволна
if(Duty >= 0) {
PWM_Set_Duty_From_DutyBridge(hpwm, hpwm->PWM_Channel1); // set first channel
PWM_Set_Compare2(hpwm, 0); // reset second channel
}
// если это вторая полуволна
else {
PWM_Set_Compare1(hpwm, 0); // reset first channel
PWM_Set_Duty_From_DutyBridge(hpwm, hpwm->PWM_Channel2); // set second channel
}
//----------SLAVE PWMs-----------
if (PWM_Get_Mode(hpwm, PWM_PHASE_MODE))
{
// SET PHASE 2 (B)
PWM_SlaveHandleTypeDef *hspwm = PWM_Set_pSlaveHandle(hpwm,hpwm2);
Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_B);
// если это первая полуволна
if(Duty > 0) {
PWM_Set_SlaveDuty_From_DutyBridge(hspwm, hspwm->PWM_Channel1); // set first channel
PWM_Set_Compare2(hspwm, 0); // reset second channel
}
// если это вторая полуволна
else {
PWM_Set_Compare1(hspwm, 0); // reset first channel
PWM_Set_SlaveDuty_From_DutyBridge(hspwm, hspwm->PWM_Channel2); // set second channel
}
// SET PHASE 3 (C)
hspwm = PWM_Set_pSlaveHandle(hpwm,hpwm3);
Duty = PWM_Get_Table_Element_Signed(hpwm, rotate_ind_C);
// если это первая полуволна
if(Duty > 0) {
PWM_Set_SlaveDuty_From_DutyBridge(hspwm, hspwm->PWM_Channel1); // set first channel
PWM_Set_Compare2(hspwm, 0); // reset second channel
}
// если это вторая полуволна
else {
PWM_Set_Compare1(hspwm, 0); // reset first channel
PWM_Set_SlaveDuty_From_DutyBridge(hspwm, hspwm->PWM_Channel2); // set second channel
}
}
else
{
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm2), 0); // reset second channel
PWM_Set_Compare1(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset first channel
PWM_Set_Compare2(PWM_Set_pSlaveHandle(hpwm,hpwm3), 0); // reset second channel
}
}
/**
* @brief Update PWM parameters.
* @note Проверка надо ли обновлять параметры ШИМ, и если надо - обновляет их.
* @note This called from TIM_CTRL_Handler
*/
void Update_Params_For_PWM(PWM_HandleTypeDef *hpwm)
{
unsigned UpdateModeParams = 0;
unsigned UpdateLog = 0;
// READ PWM_VALUE
if(hpwm->hramp.setpoint != int_to_percent(pwm_ctrl[R_PWM_CTRL_PWM_VALUE]))
{
hpwm->hramp.setpoint = int_to_percent(pwm_ctrl[R_PWM_CTRL_PWM_VALUE]);
if((hpwm->hramp.setpoint == 0) || // if zero - force reset pwm value
(hpwm->PWM_Value != hpwm->PWM_Value ) ) // or if PWM_Value isnt in range
{
PWM_Ramp_Reset(hpwm);
}
// update logs params
UpdateLog = 1;
}
// UPDATE RAMP
if(hpwm->hramp.setpoint > 0) // if setpiont inst zero
PWM_Ramp_ControlPWMValue(hpwm);
// READ PWM_ACTIVECHANNEL_MODE
uint16_t activechannesls = (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_ACTIVECHANNEL))|
(MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_ACTIVECHANNEL+1) << 1)|
(MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_ACTIVECHANNEL+2) << 2);
if(PWM_Get_Mode(hpwm, PWM_ACTIVECHANNEL_MODE) != (activechannesls << PWM_ACTIVECHANNEL_MODE_Pos))
{
uint16_t tmpmode = hpwm->sPWM_Mode&(~PWM_ACTIVECHANNEL_MODE);
tmpmode |= activechannesls << PWM_ACTIVECHANNEL_MODE_Pos;
hpwm->sPWM_Mode = tmpmode;
// update mode params
UpdateModeParams = 1;
// update logs params
UpdateLog = 1;
}
// READ PWM_DC_MODE
if(PWM_Get_Mode(hpwm, PWM_DC_MODE) != (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_DC_MODE) << PWM_DC_MODE_Pos))
{
if(MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_DC_MODE))
{
hpwm->sPWM_Mode |= PWM_DC_MODE;
}
else
{
hpwm->sPWM_Mode &= ~PWM_DC_MODE;
}
// update mode params
UpdateModeParams = 1;
// update logs params
UpdateLog = 1;
}
// READ PWM_BRIDGE_MODE
if(PWM_Get_Mode(hpwm, PWM_BRIDGE_MODE) != (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_BRIDGE_MODE) << PWM_BRIDGE_MODE_Pos))
{
if(MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_BRIDGE_MODE))
{
hpwm->sPWM_Mode |= PWM_BRIDGE_MODE;
}
else
{
hpwm->sPWM_Mode &= ~PWM_BRIDGE_MODE;
}
// update mode params
UpdateModeParams = 1;
// update logs params
UpdateLog = 1;
}
// READ PWM_PHASE_MODE
if(PWM_Get_Mode(hpwm, PWM_PHASE_MODE) != (MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_PHASE_MODE) << PWM_PHASE_MODE_Pos))
{
if(MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_PHASE_MODE))
{
hpwm->sPWM_Mode |= PWM_PHASE_MODE;
}
else
{
hpwm->sPWM_Mode &= ~PWM_PHASE_MODE;
}
// update mode params
UpdateModeParams = 1;
// update logs params
UpdateLog = 1;
}
// READ PWM_POLARITY
uint16_t polarity_temp = MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_POLARITY);
if(((hpwm->stim.htim.Instance->CCER&TIM_CCER_CC1P) || (hpwm->stim.htim.Instance->CCER&TIM_CCER_CC3P)) != (polarity_temp))
{
__HAL_TIM_SET_CAPTUREPOLARITY(&hpwm->stim.htim, hpwm->PWM_Channel1, polarity_temp<<1);
__HAL_TIM_SET_CAPTUREPOLARITY(&hpwm->stim.htim, hpwm->PWM_Channel2, polarity_temp<<1);
PWM_SlaveHandleTypeDef *shpwm = PWM_Set_pSlaveHandle(hpwm,hpwm2);
__HAL_TIM_SET_CAPTUREPOLARITY(&shpwm->stim.htim, shpwm->PWM_Channel1, polarity_temp<<1);
__HAL_TIM_SET_CAPTUREPOLARITY(&shpwm->stim.htim, shpwm->PWM_Channel2, polarity_temp<<1);
shpwm = PWM_Set_pSlaveHandle(hpwm,hpwm3);
__HAL_TIM_SET_CAPTUREPOLARITY(&shpwm->stim.htim, shpwm->PWM_Channel1, polarity_temp<<1);
__HAL_TIM_SET_CAPTUREPOLARITY(&shpwm->stim.htim, shpwm->PWM_Channel2, polarity_temp<<1);
}
// READ TABLE_SIZE
if(hpwm->Duty_Table_Size != pwm_ctrl[R_PWM_CTRL_SIN_TABLE_SIZE])
{
hpwm->Duty_Table_Size = PWM_Fill_Sine_Table(&hpwm1, pwm_ctrl[R_PWM_CTRL_SIN_TABLE_SIZE]);
pwm_ctrl[R_PWM_CTRL_SIN_TABLE_SIZE] = hpwm->Duty_Table_Size;
}
// READ DUTY_BRIDGE
if(hpwm->PWM_DutyBridge != pwm_ctrl[R_PWM_CTRL_DUTY_BRIDGE])
{
hpwm->PWM_DutyBridge = int_to_percent(pwm_ctrl[R_PWM_CTRL_DUTY_BRIDGE]);
// update mode params
UpdateModeParams = 1;
// update logs params
UpdateLog = 1;
}
// READ MIN PULSE DURATION
if(hpwm->PWM_MinPulseDur != pwm_ctrl[R_PWM_CTRL_MIN_PULSE_DUR])
{
hpwm->PWM_MinPulseDur = pwm_ctrl[R_PWM_CTRL_MIN_PULSE_DUR];
// update mode params
UpdateModeParams = 1;
// update logs params
UpdateLog = 1;
}
// READ MAX PULSE DURATION
if((hpwm->PWM_MaxPulseDur != pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR]) &&
(pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR] <= PWM_Get_Autoreload(hpwm)) &&
(pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR] != 0))
{
hpwm->PWM_MaxPulseDur = pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR];
// update mode params
UpdateModeParams = 1;
// update logs params
UpdateLog = 1;
}
else if (((hpwm->PWM_MaxPulseDur != PWM_Get_Autoreload(hpwm)) && (pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR] == 0)) ||
((hpwm->PWM_MaxPulseDur != PWM_Get_Autoreload(hpwm)) && (pwm_ctrl[R_PWM_CTRL_MAX_PULSE_DUR] > PWM_Get_Autoreload(hpwm))))
{
hpwm->PWM_MaxPulseDur = PWM_Get_Autoreload(hpwm);
// update mode params
UpdateModeParams = 1;
}
// READ DEAD TIME
if(hpwm->PWM_DeadTime != pwm_ctrl[R_PWM_CTRL_DEAD_TIME])
{
hpwm->PWM_DeadTime = pwm_ctrl[R_PWM_CTRL_DEAD_TIME];
}
// UPDATE PWM PARAMS
if(UpdateModeParams)
{
// UPDATE DUTY TABLE SCALE
PWM_Update_DutyTableScale(hpwm);
// update logs params
UpdateLog = 1;
}
// UPDATE LOG PARAMS
if(UpdateLog)
{
// set logs params
Set_Log_Params();
}
}
/**
* @brief PID for ramp.
* @param hpwm - указатель на хендл ШИМ.
* @note ПИД-регулятор, который управляет скважностью ШИМ и не дает её изменяться резко.
*/
void PWM_Ramp_ControlPWMValue(PWM_HandleTypeDef *hpwm) {
/*
* Error signal
*/
float error = hpwm->hramp.setpoint - hpwm->PWM_Value;
/*
* Proportional
*/
float proportional = hpwm->hramp.Kp * error;
/* Limiting the accelerate */
if (error > hpwm->hramp.limMaxInt) {
error = hpwm->hramp.limMaxInt;
} else if (error < hpwm->hramp.limMinInt) {
error = hpwm->hramp.limMinInt;
}
/* * Integral
*/
hpwm->hramp.integrator = hpwm->hramp.integrator + 0.5f * hpwm->hramp.Ki * hpwm->hramp.SampleT * (error + hpwm->hramp.prevError);
/* Anti-wind-up via integrator clamping */
if (hpwm->hramp.integrator > hpwm->hramp.limMax) {
hpwm->hramp.integrator = hpwm->hramp.limMax;
} else if (hpwm->hramp.integrator < hpwm->hramp.limMin) {
hpwm->hramp.integrator = hpwm->hramp.limMin;
}
/*
* Derivative (band-limited differentiator)
*/
hpwm->hramp.differentiator = -(2.0f * hpwm->hramp.Kd * (hpwm->PWM_Value - hpwm->hramp.prevMeasurement) /* Note: derivative on measurement, therefore minus sign in front of equation! */
+ (2.0f * hpwm->hramp.tau - hpwm->hramp.SampleT) * hpwm->hramp.differentiator)
/ (2.0f * hpwm->hramp.tau + hpwm->hramp.SampleT);
/*
* Compute output and apply limits
*/
hpwm->PWM_Value = proportional + hpwm->hramp.integrator + hpwm->hramp.differentiator;
if (hpwm->PWM_Value > hpwm->hramp.limMax) {
hpwm->PWM_Value = hpwm->hramp.limMax;
} else if (hpwm->PWM_Value < hpwm->hramp.limMin) {
hpwm->PWM_Value = hpwm->hramp.limMin;
}
/* Store error and measurement for later use */
hpwm->hramp.prevError = error;
hpwm->hramp.prevMeasurement = hpwm->PWM_Value;
// /* set PWM Value output */
// *hpwm->hramp.out;
}
/**
* @brief Reset PID for ramp.
* @param hpwm - указатель на хендл ШИМ.
* @note Сбрасывает переменные ПИД-регулятора, чтобы потом его запустить "с чистого листа".
*/
void PWM_Ramp_Reset(PWM_HandleTypeDef *hpwm)
{
hpwm->PWM_Value = 0;
/* Clear controller variables */
hpwm->hramp.integrator = 0.0f;
hpwm->hramp.prevError = 0.0f;
hpwm->hramp.differentiator = 0.0f;
hpwm->hramp.prevMeasurement = 0.0f;
}
/**
* @brief reInitialization of PWM TIM.
* @param hpwm - указатель на хендл ШИМ.
* @note Перенастраивает таймер согласно принятным настройкам в pwm_ctrl
* ШИМ генерируется на одном канале.
*/
void PWM_Sine_ReInit(PWM_HandleTypeDef *hpwm)
{
Trace_PWM_reInit_Enter();
TIM_Base_MspDeInit(&hpwm->stim.htim);
hpwm1.stim.sTickBaseMHz = TIMER_PWM_TICKBASE;
hpwm1.sConfigOC.OCPolarity = MB_Read_Coil_Local(&coils_regs[0], COIL_PWM_POLARITY) << TIM_CCER_CC1P_Pos;
TIM_Base_Init(&hpwm->stim);
TIM_Output_PWM_Init(&hpwm->stim.htim, &hpwm->sConfigOC, hpwm->PWM_Channel1, hpwm->GPIOx, hpwm->GPIO_PIN_X1);
TIM_Output_PWM_Init(&hpwm->stim.htim, &hpwm->sConfigOC, hpwm->PWM_Channel2, hpwm->GPIOx, hpwm->GPIO_PIN_X2);
PWM_Update_DutyTableScale(hpwm);
//----------TIMERS START-------------
HAL_TIM_Base_Start_IT(&hpwm1.stim.htim); // timer for PWM
HAL_TIM_PWM_Start(&hpwm1.stim.htim, hpwm->PWM_Channel1); // PWM channel 1
HAL_TIM_PWM_Start(&hpwm1.stim.htim, hpwm->PWM_Channel2); // PWM channel 2
Trace_PWM_reInit_Exit();
}
/**
* @brief Getting ind for Duty Table.
* @param hpwm - указатель на хендл ШИМ.
* @param FreqTIM - частота таймера ШИМ.
* @note Рассчитывает индекс для таблицы скважностей.
* PWM_Value в hpwm - частота с которой эта таблица должна выводиться на ШИМ
* @note This called from TIM_PWM_Handler
*/
uint32_t PWM_Get_Duty_Table_Ind(PWM_HandleTypeDef *hpwm, float FreqTIM)
{
float sine_ind_step;
// calc ind for sin table
if(hpwm->PWM_Value != 0) // if there some frequency
{
sine_ind_step = hpwm->Duty_Table_Size/(FreqTIM/hpwm->PWM_Value);
hpwm->Duty_Table_Ind += sine_ind_step;
}
else
return hpwm->Duty_Table_Size;
// overflow check
if(hpwm->Duty_Table_Ind >= hpwm->Duty_Table_Size)
hpwm->Duty_Table_Ind -= hpwm->Duty_Table_Size;
if(hpwm->Duty_Table_Ind >= hpwm->Duty_Table_Size)
hpwm->Duty_Table_Ind = 0;
// if its too big (e.g. inf)
if((hpwm->Duty_Table_Ind >= 0xFFFF) ||
(hpwm->Duty_Table_Ind != hpwm->Duty_Table_Ind)) // in nan case
hpwm->Duty_Table_Ind = 0;
return hpwm->Duty_Table_Ind;
}
/**
* @brief Create Dead Time when switches channels.
* @param hpwm - указатель на хендл ШИМ.
*/
void PWM_CreateDeadTime(PWM_HandleTypeDef *hpwm, float *LocalDeadTimeCnt, unsigned *LocalActiveChannel)
{
// get current active channel
hpwm->fActiveChannel = (PWM_Get_Compare2(hpwm) != 0); // if channel two is active - write 1, otherwise - 0
// when channels are swithed and no dead time currently active
if(*LocalActiveChannel != hpwm->fActiveChannel)
{ // update active channel
*LocalActiveChannel = hpwm->fActiveChannel;
// set deadtime
*LocalDeadTimeCnt = hpwm->PWM_DeadTime;
Trace_PWM_DeadTime_Enter();
}
// decrement dead time
*LocalDeadTimeCnt -= (PWM_Get_Autoreload(hpwm)+1)*hpwm->stim.sTickBaseMHz;
if(*LocalDeadTimeCnt > 0) // if dead time is still active
{ // reset all channels
// reset channels
PWM_Set_Compare1(hpwm, 0);
PWM_Set_Compare2(hpwm, 0);
}
else // if dead time is done
{ // set it to zero
*LocalDeadTimeCnt = 0;
Trace_PWM_DeadTime_Exit();
}
}
/**
* @brief Filling table with one period of sinus values.
* @param hpwm - указатель на хендл ШИМ.
* @param table_size - размер таблицы.
* @note Формирует таблицу синусов размером table_size.
*/
uint32_t PWM_Fill_Sine_Table(PWM_HandleTypeDef *hpwm, uint32_t table_size)
{
if((hpwm == NULL) || (hpwm->pDuty_Table_Origin == NULL) || (table_size == 0))
{
return 0;
}
if (table_size > SIN_TABLE_SIZE_MAX)
table_size = SIN_TABLE_SIZE_MAX;
hpwm->Duty_Table_Size = table_size;
float pi_step = 2*M_PI/(hpwm->Duty_Table_Size);
float pi_val = 0;
float sin_koef = 0;
uint32_t sin_val = 0;
// fill table with sinus
for(int i = 0; i < hpwm->Duty_Table_Size; i++)
{
// rotate pi
pi_val += pi_step;
// calc sin value
sin_koef = (float)0xFFFF;
sin_val = (sin(pi_val)+1)*sin_koef/2;
sin_table[i] = sin_val;
}
// fill rest of table with zeros
for(int i = hpwm->Duty_Table_Size; i < SIN_TABLE_SIZE_MAX; i++)
sin_table[i] = 0;
// if second channel is enabled
PWM_Update_DutyTableScale(hpwm);
return hpwm->Duty_Table_Size;
}
/**
* @brief Calc and update new Duty Table Scale.
* @param hpwm - указатель на хендл ШИМ.
* @note Используется, когда изменяется значение регистра ARR.
*/
void PWM_Update_DutyTableScale(PWM_HandleTypeDef *hpwm)
{
// UPDATE DUTY TABLE SCALE
if(PWM_Get_Mode(hpwm, PWM_BRIDGE_MODE)) // if second channel is enabled
{
hpwm->Duty_Table_Scale = PWM_Calc_Duty_Scale(&hpwm1, 0x8000);
}
else
{
hpwm->Duty_Table_Scale = PWM_Calc_Duty_Scale(&hpwm1, 0xFFFF);
}
// for case if min pulse dur is too big and scale is negative
if (hpwm->Duty_Table_Scale < 0)
hpwm->Duty_Table_Scale = 1;
}
//-------------------------------------------------------------------
//-----------------------THREEPHASE FUNCTIONS------------------------
/**
* @brief Initialization of Slave PWM TIM.
* @param hspwm - указатель на хендл слейв ШИМ.
* @note Вызывает функции инициализации и включения слейв ШИМ.
*/
void PWM_SlavePhase_Init(PWM_SlaveHandleTypeDef *hspwm)
{
TIM_Base_Init(&hspwm->stim);
TIM_Output_PWM_Init(&hspwm->stim.htim, &hspwm->hMasterPWM->sConfigOC, hspwm->PWM_Channel1, hspwm->GPIOx, hspwm->GPIO_PIN_X1);
TIM_Output_PWM_Init(&hspwm->stim.htim, &hspwm->hMasterPWM->sConfigOC, hspwm->PWM_Channel2, hspwm->GPIOx, hspwm->GPIO_PIN_X2);
// if three phase enables
//----------TIMERS START-------------
HAL_TIM_Base_Start(&hspwm->stim.htim);
HAL_TIM_PWM_Start(&hspwm->stim.htim, hspwm->PWM_Channel1); // PWM channel 1
HAL_TIM_PWM_Start(&hspwm->stim.htim, hspwm->PWM_Channel2); // PWM channel 2
if(PWM_Get_Mode(hspwm->hMasterPWM, PWM_PHASE_MODE) == 0) // if three phase disabled
{
PWM_Set_Compare1(hspwm, 0); // reset first channel
PWM_Set_Compare2(hspwm, 0); // reset second channel
}
}
/**
* @brief reInitialization of Slave PWM TIM.
* @param hspwm - указатель на хендл слейв ШИМ.
* @note Перенастраивает таймер согласно принятным настройкам в pwm_ctrl.
*/
void PWM_SlavePhase_reInit(PWM_SlaveHandleTypeDef *hspwm)
{
PWM_Slave_CopyTimSetting(hspwm, sTimFreqHz);
TIM_Base_MspDeInit(&hspwm->stim.htim);
PWM_SlavePhase_Init(hspwm);
}
/**
* @brief Set Duty from table on Slave PWM at one channel by sin_ind of the Master PWM.
* @param hspwm - указатель на хендл слейв ШИМ.
* @param sin_ind - индекс таблицы для Мастер ШИМ.
* @note Индекс для свейл ШИМ расчитывается в самой функции.
*/
uint16_t PWM_SlavePhase_Calc_TableInd(PWM_SlaveHandleTypeDef *hspwm, uint16_t rotate_ind_Phase)
{
// if three phase enables
if(hspwm->Duty_Shift_Ratio > 0)
rotate_ind_Phase += hspwm->hMasterPWM->Duty_Table_Size*hspwm->Duty_Shift_Ratio;
else
rotate_ind_Phase += hspwm->hMasterPWM->Duty_Table_Size*(1+hspwm->Duty_Shift_Ratio);
// overflow check
if(rotate_ind_Phase > hspwm->hMasterPWM->Duty_Table_Size)
rotate_ind_Phase -= hspwm->hMasterPWM->Duty_Table_Size;
if(rotate_ind_Phase > hspwm->hMasterPWM->Duty_Table_Size)
rotate_ind_Phase = 0;;
return rotate_ind_Phase;
//
// PWM_Set_SlaveDuty_From_Table(hspwm, sin_ind); // set first channel
}
/**
* @brief Check is all Slave channels works properly.
* @param hspwm - указатель на хендл слейв ШИМ.
* @note Проверка работает ли только один из каналов, и проверка чтобы CCRx <= ARR
* @note В мастере проверка происходит напрямую в PWM_Handler.
*/
void PWM_SlavePhase_Check_Channels(PWM_SlaveHandleTypeDef *hspwm)
{
uint16_t min_duty = PWM_Calc_Min_Duty(hspwm->hMasterPWM);
uint16_t max_duty = PWM_Calc_Max_Duty(hspwm->hMasterPWM);
// IF FIRST CHANNEL IS ACRIVE
if(PWM_Get_Compare1(hspwm) != 0)
{
// Duty shoud be bigger or equeal than min duration
if (PWM_Get_Compare1(hspwm)<min_duty)
PWM_Set_Compare1(hspwm, min_duty);
// Duty shoud be less or equeal than ARR-min duration
if (PWM_Get_Compare1(hspwm)>max_duty)
PWM_Set_Compare1(hspwm, max_duty);
}
// IF SECOND CHANNEL IS ACRIVE
else if(PWM_Get_Compare2(hspwm) != 0)
// Duty shoud be bigger or equeal than min duration
if (PWM_Get_Compare2(hspwm)<min_duty)
PWM_Set_Compare2(hspwm, min_duty);
// Duty shoud be less or equeal than ARR
if (PWM_Get_Compare2(hspwm)>max_duty)
PWM_Set_Compare2(hspwm, max_duty);
// IF BOTH CHANNEL IS ACRIVE
if((PWM_Get_Compare1(hspwm) != 0) && (PWM_Get_Compare2(hspwm) != 0))
{
// Only one channel shoud be active so disable all
PWM_Set_Compare1(hspwm, 0);
PWM_Set_Compare2(hspwm, 0);
}
}
/**
* @brief Create Dead Time for Slave PWM when switches channels.
* @param hspwm - указатель на хендл слейв ШИМ.
* @param LocalDeadTimeCnt - указатель на переменную для отсчитывания дедтайма.
* @param LocalActiveChannel - указатель на переменную для отслеживания смены канала.
* @note Аналог функции PWM_CreateDeadTime но для слейв ШИМов.
*/
void PWM_SlavePhase_CreateDeadTime(PWM_SlaveHandleTypeDef *hspwm, float *LocalDeadTimeCnt, unsigned *LocalActiveChannel)
{
// get current active channel
hspwm->fActiveChannel = (PWM_Get_Compare2(hspwm) != 0); // if channel two is active - write 1, otherwise - 0
// when channels are swithed and no dead time currently active
if(*LocalActiveChannel != hspwm->fActiveChannel)
{ // update active channel
*LocalActiveChannel = hspwm->fActiveChannel;
// set deadtime
*LocalDeadTimeCnt = hspwm->hMasterPWM->PWM_DeadTime;
Trace_PWM_DeadTime_Enter();
}
// decrement dead time
*LocalDeadTimeCnt -= (PWM_Get_Autoreload(hspwm)+1)*hspwm->hMasterPWM->stim.sTickBaseMHz;
if(*LocalDeadTimeCnt > 0) // if dead time is still active
{ // reset all channels
// reset channels
PWM_Set_Compare1(hspwm, 0);
PWM_Set_Compare2(hspwm, 0);
}
else // if dead time is done
{ // set it to zero
*LocalDeadTimeCnt = 0;
Trace_PWM_DeadTime_Exit();
}
}
//-------------------------------------------------------------------
//------------------------HANDLERS FUNCTIONS-------------------------
//---------------PWM TIMER-----------------
#if (PWM_MASTER_TIM_NUMB == 1) || (PWM_MASTER_TIM_NUMB == 10) // choose handler for TIM
void TIM1_UP_TIM10_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 2)
void TIM2_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 3)
void TIM3_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 4)
void TIM4_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 5)
void TIM5_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 6)
void TIM6_DAC_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 7)
void TIM7_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 8) || (PWM_MASTER_TIM_NUMB == 13)
void TIM8_UP_TIM13_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 1) || (PWM_MASTER_TIM_NUMB == 9)
void TIM1_BRK_TIM9_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 1) || (PWM_MASTER_TIM_NUMB == 11)
void TIM1_TRG_COM_TIM11_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 8) || (PWM_MASTER_TIM_NUMB == 12)
void TIM8_BRK_TIM12_IRQHandler(void)
#elif (PWM_MASTER_TIM_NUMB == 8) || (PWM_MASTER_TIM_NUMB == 14)
void TIM8_TRG_COM_TIM14_IRQHandler(void)
#endif
{
/* TIM_PWM_Handler */
Trace_PWM_TIM_Enter();
HAL_TIM_IRQHandler(&hpwm1.stim.htim);
PWM_Handler(&hpwm1);
Trace_PWM_TIM_Exit();
}