#include "hal/hal.h" #include "hal/pwm.h" #include "stm32f3xx_ll_tim.h" #include "stm32f3xx_ll_gpio.h" #include "stm32f3xx_ll_system.h" #define TIMxCCER_MASK_CH123 ((uint16_t) (LL_TIM_CHANNEL_CH1|LL_TIM_CHANNEL_CH1N|\ LL_TIM_CHANNEL_CH2|LL_TIM_CHANNEL_CH2N|\ LL_TIM_CHANNEL_CH3|LL_TIM_CHANNEL_CH3N)) static TIM_HandleTypeDef htim1; static void HAL_TIM1_Pin_Init(void); void HAL_PWM_Init(int fs) { TIM_SlaveConfigTypeDef sSlaveConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; htim1.Instance = TIM1; htim1.Init.Prescaler = 0; htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1; htim1.Init.Period = (TIM_CLOCK / fs /2); htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter = 0; htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim1) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_Init(&htim1) != HAL_OK) { Error_Handler(); } sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER; sSlaveConfig.InputTrigger = TIM_TS_ITR1; if (HAL_TIM_SlaveConfigSynchronization(&htim1, &sSlaveConfig) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF; sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = (TIM_CLOCK / fs) / 4; //运行后,根据svpwm重新设置 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); } /* 触发ADC采样的配置 */ sConfigOC.OCMode = TIM_OCMODE_PWM2; sConfigOC.Pulse = (TIM_CLOCK / fs) / 2 - 5; //运行后,根据pwm,sector信息,重新设置采样点 if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } /* 刹车配置 */ sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE; sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE; sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1; sBreakDeadTimeConfig.DeadTime = 0; sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; sBreakDeadTimeConfig.BreakFilter = 0; sBreakDeadTimeConfig.Break2State = TIM_BREAK2_ENABLE; sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_LOW; sBreakDeadTimeConfig.Break2Filter = 0xF; sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) { Error_Handler(); } /* TIM1 Counter Clock stopped when the core is halted */ LL_DBGMCU_APB2_GRP1_FreezePeriph( LL_DBGMCU_APB2_GRP1_TIM1_STOP ); HAL_TIM1_Pin_Init(); } void PWM_TimerEnable(void){ TIM_TypeDef * TIMx = htim1.Instance; uint32_t Brk2Timeout = 1000; LL_TIM_SetTriggerOutput(TIMx, LL_TIM_TRGO_RESET); /* Enables the TIMx Preload on CC1 Register */ LL_TIM_OC_EnablePreload( TIMx, LL_TIM_CHANNEL_CH1 ); /* Enables the TIMx Preload on CC2 Register */ LL_TIM_OC_EnablePreload( TIMx, LL_TIM_CHANNEL_CH2 ); /* Enables the TIMx Preload on CC3 Register */ LL_TIM_OC_EnablePreload( TIMx, LL_TIM_CHANNEL_CH3 ); /* Enables the TIMx Preload on CC4 Register */ LL_TIM_OC_EnablePreload( TIMx, LL_TIM_CHANNEL_CH4 ); /* Prepare timer for synchronization */ LL_TIM_GenerateEvent_UPDATE( TIMx ); LL_TIM_SetCounter( TIMx, 0); LL_TIM_ClearFlag_BRK( TIMx ); while ((LL_TIM_IsActiveFlag_BRK2 (TIMx) == 1u) && (Brk2Timeout != 0u) ) { LL_TIM_ClearFlag_BRK2( TIMx ); Brk2Timeout--; } LL_TIM_EnableIT_BRK( TIMx ); /* Enable PWM channel */ LL_TIM_CC_EnableChannel( TIMx, TIMxCCER_MASK_CH123 ); /* TIM1_BRK_IRQn interrupt configuration */ HAL_NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn); HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn); LL_TIM_EnableCounter(TIMx); } void PWM_UpdateDuty(u32 duty1, u32 duty2, u32 duty3, u32 sample_point ) { TIM_TypeDef * TIMx = htim1.Instance; //LL_TIM_DisableUpdateEvent(TIMx); LL_TIM_OC_SetCompareCH1(TIMx, duty1); LL_TIM_OC_SetCompareCH2(TIMx, duty2); LL_TIM_OC_SetCompareCH3(TIMx, duty3); LL_TIM_OC_SetCompareCH4(TIMx, sample_point); #if 0 /* wait for a new PWM period */ LL_TIM_ClearFlag_UPDATE( TIMx ); LL_TIM_EnableUpdateEvent(TIMx); #if 0 while ( LL_TIM_IsActiveFlag_UPDATE( TIMx ) == 0u ) {} /* Clear Update Flag */ LL_TIM_ClearFlag_UPDATE( TIMx ); #endif #endif } void PWM_Disable_Channels(void) { TIM_TypeDef * TIMx = htim1.Instance; LL_TIM_CC_DisableChannel(TIMx, TIMxCCER_MASK_CH123); } void PWM_Enable_Channels(void) { TIM_TypeDef * TIMx = htim1.Instance; LL_TIM_CC_EnableChannel(TIMx, TIMxCCER_MASK_CH123); } void PWM_Start(void) { TIM_TypeDef * TIMx = htim1.Instance; /* Set all duty to 50% */ LL_TIM_OC_SetCompareCH1(TIMx, ((uint32_t) FOC_PWM_Half_Period / (uint32_t) 2)); LL_TIM_OC_SetCompareCH2(TIMx, ((uint32_t) FOC_PWM_Half_Period / (uint32_t) 2)); LL_TIM_OC_SetCompareCH3(TIMx, ((uint32_t) FOC_PWM_Half_Period / (uint32_t) 2)); LL_TIM_OC_SetCompareCH4(TIMx, ((uint32_t) FOC_PWM_Half_Period - (uint32_t) 5)); /* wait for a new PWM period */ LL_TIM_ClearFlag_UPDATE( TIMx ); while ( LL_TIM_IsActiveFlag_UPDATE( TIMx ) == 0u ) {} /* Clear Update Flag */ LL_TIM_ClearFlag_UPDATE( TIMx ); /* Main PWM Output Enable */ TIMx->BDTR |= LL_TIM_OSSI_ENABLE; LL_TIM_EnableAllOutputs ( TIMx ); if ( ( TIMx->CCER & TIMxCCER_MASK_CH123 ) != 0u ) { LL_GPIO_SetOutputPin( PWM_EN_U_GPIO_Port, PWM_EN_U_Pin ); LL_GPIO_SetOutputPin( PWM_EN_V_GPIO_Port, PWM_EN_V_Pin ); LL_GPIO_SetOutputPin( PWM_EN_W_GPIO_Port, PWM_EN_W_Pin ); } else { /* It is executed during calibration phase the EN signal shall stay off */ LL_GPIO_ResetOutputPin( PWM_EN_U_GPIO_Port, PWM_EN_U_Pin ); LL_GPIO_ResetOutputPin( PWM_EN_V_GPIO_Port, PWM_EN_V_Pin ); LL_GPIO_ResetOutputPin( PWM_EN_W_GPIO_Port, PWM_EN_W_Pin ); } /* Clear Update Flag */ LL_TIM_ClearFlag_UPDATE( TIMx ); /* Enable Update IRQ */ LL_TIM_EnableIT_UPDATE( TIMx ); } void PWM_Stop(void) { TIM_TypeDef * TIMx = htim1.Instance; /* Disable UPDATE ISR */ LL_TIM_DisableIT_UPDATE( TIMx ); /* Main PWM Output Disable */ LL_TIM_DisableAllOutputs( TIMx ); LL_GPIO_ResetOutputPin( PWM_EN_U_GPIO_Port, PWM_EN_U_Pin ); LL_GPIO_ResetOutputPin( PWM_EN_V_GPIO_Port, PWM_EN_V_Pin ); LL_GPIO_ResetOutputPin( PWM_EN_W_GPIO_Port, PWM_EN_W_Pin ); /* wait for a new PWM period to flush last HF task */ LL_TIM_ClearFlag_UPDATE( TIMx ); while ( LL_TIM_IsActiveFlag_UPDATE( TIMx ) == 0u ) {} /* Clear Update Flag */ LL_TIM_ClearFlag_UPDATE( TIMx ); } void PWM_TurnOnLowSides(void) { TIM_TypeDef * TIMx = htim1.Instance; /* Clear Update Flag */ LL_TIM_ClearFlag_UPDATE( TIMx ); /*Turn on the three low side switches */ LL_TIM_OC_SetCompareCH1( TIMx, 0u ); LL_TIM_OC_SetCompareCH2( TIMx, 0u ); LL_TIM_OC_SetCompareCH3( TIMx, 0u ); /* Wait until next update */ while ( LL_TIM_IsActiveFlag_UPDATE( TIMx ) == 0u ) {} /* Main PWM Output Enable */ LL_TIM_EnableAllOutputs( TIMx ); LL_GPIO_SetOutputPin( PWM_EN_U_GPIO_Port, PWM_EN_U_Pin ); LL_GPIO_SetOutputPin( PWM_EN_V_GPIO_Port, PWM_EN_V_Pin ); LL_GPIO_SetOutputPin( PWM_EN_W_GPIO_Port, PWM_EN_W_Pin ); return; } static void HAL_TIM1_Pin_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = PWM_UH_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF6_TIM1; HAL_GPIO_Init(PWM_UH_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = PWM_VH_Pin; HAL_GPIO_Init(PWM_VH_GPIO_Port, &GPIO_InitStruct); GPIO_InitStruct.Pin = PWM_WH_Pin; HAL_GPIO_Init(PWM_WH_GPIO_Port, &GPIO_InitStruct); }