1085 lines
38 KiB
C
1085 lines
38 KiB
C
#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();
|
||
}
|
||
|