/* * stm32f4_pwm.c * * Created on: Aug 9, 2016 * Author: tkl */ #include #include #include "stm32f4xx.h" #include "isr.h" #include "gpio.h" #include "stm32f4_gpio.h" #include "pwm.h" #include "stm32f4_pwm.h" struct stm32f4_pwm_channel_object { struct stm32f4_pwm *pwm; uint32_t period; uint32_t period_start; uint32_t pulse; uint32_t pulse_start; }; struct stm32f4_pwm_timer_object { struct stm32f4_pwm_channel_object channel_1; struct stm32f4_pwm_channel_object channel_2; struct stm32f4_pwm_channel_object channel_3; struct stm32f4_pwm_channel_object channel_4; }; struct stm32f4_pwm_object { struct stm32f4_pwm_timer_object timer_2; struct stm32f4_pwm_timer_object timer_4; struct stm32f4_pwm_timer_object timer_5; }; static volatile struct stm32f4_pwm_object pwm_object = { .timer_2.channel_1.pwm = NULL, .timer_2.channel_1.period = 0, .timer_2.channel_1.period_start = 0, .timer_2.channel_1.pulse = 0, .timer_2.channel_1.pulse_start = 0, .timer_2.channel_2.pwm = NULL, .timer_2.channel_2.period = 0, .timer_2.channel_2.period_start = 0, .timer_2.channel_2.pulse = 0, .timer_2.channel_2.pulse_start = 0, .timer_2.channel_3.pwm = NULL, .timer_2.channel_3.period = 0, .timer_2.channel_3.period_start = 0, .timer_2.channel_3.pulse = 0, .timer_2.channel_3.pulse_start = 0, .timer_2.channel_4.pwm = NULL, .timer_2.channel_4.period = 0, .timer_2.channel_4.period_start = 0, .timer_2.channel_4.pulse = 0, .timer_2.channel_4.pulse_start = 0, .timer_4.channel_1.pwm = NULL, .timer_4.channel_1.period = 0, .timer_4.channel_1.period_start = 0, .timer_4.channel_1.pulse = 0, .timer_4.channel_1.pulse_start = 0, .timer_4.channel_2.pwm = NULL, .timer_4.channel_2.period = 0, .timer_4.channel_2.period_start = 0, .timer_4.channel_2.pulse = 0, .timer_4.channel_2.pulse_start = 0, .timer_4.channel_3.pwm = NULL, .timer_4.channel_3.period = 0, .timer_4.channel_3.period_start = 0, .timer_4.channel_3.pulse = 0, .timer_4.channel_3.pulse_start = 0, .timer_4.channel_4.pwm = NULL, .timer_4.channel_4.period = 0, .timer_4.channel_4.period_start = 0, .timer_4.channel_4.pulse = 0, .timer_4.channel_4.pulse_start = 0, .timer_5.channel_1.pwm = NULL, .timer_5.channel_1.period = 0, .timer_5.channel_1.period_start = 0, .timer_5.channel_1.pulse = 0, .timer_5.channel_1.pulse_start = 0, .timer_5.channel_2.pwm = NULL, .timer_5.channel_2.period = 0, .timer_5.channel_2.period_start = 0, .timer_5.channel_2.pulse = 0, .timer_5.channel_2.pulse_start = 0, .timer_5.channel_3.pwm = NULL, .timer_5.channel_3.period = 0, .timer_5.channel_3.period_start = 0, .timer_5.channel_3.pulse = 0, .timer_5.channel_3.pulse_start = 0, .timer_5.channel_4.pwm = NULL, .timer_5.channel_4.period = 0, .timer_5.channel_4.period_start = 0, .timer_5.channel_4.pulse = 0, .timer_5.channel_4.pulse_start = 0, }; int stm32f4_pwm_open(const void *pwm) { if(NULL == pwm) return -1; struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; IRQn_Type irq_type = TIM2_IRQn; stm32f4_gpio_open(this->pwm_gpio); if(this->timer_handle->Instance == TIM2) { __HAL_RCC_TIM2_CLK_ENABLE(); irq_type = TIM2_IRQn; if(this->channel == TIM_CHANNEL_1) pwm_object.timer_2.channel_1.pwm = this; else if(this->channel == TIM_CHANNEL_2) pwm_object.timer_2.channel_2.pwm = this; else if(this->channel == TIM_CHANNEL_3) pwm_object.timer_2.channel_3.pwm = this; else if(this->channel == TIM_CHANNEL_4) pwm_object.timer_2.channel_4.pwm = this; } if(this->timer_handle->Instance == TIM4) { __HAL_RCC_TIM4_CLK_ENABLE(); irq_type = TIM4_IRQn; if(this->channel == TIM_CHANNEL_1) pwm_object.timer_4.channel_1.pwm = this; else if(this->channel == TIM_CHANNEL_2) pwm_object.timer_4.channel_2.pwm = this; else if(this->channel == TIM_CHANNEL_3) pwm_object.timer_4.channel_3.pwm = this; else if(this->channel == TIM_CHANNEL_4) pwm_object.timer_4.channel_4.pwm = this; } if(this->timer_handle->Instance == TIM5) { __HAL_RCC_TIM5_CLK_ENABLE(); irq_type = TIM5_IRQn; if(this->channel == TIM_CHANNEL_1) pwm_object.timer_5.channel_1.pwm = this; else if(this->channel == TIM_CHANNEL_2) pwm_object.timer_5.channel_2.pwm = this; else if(this->channel == TIM_CHANNEL_3) pwm_object.timer_5.channel_3.pwm = this; else if(this->channel == TIM_CHANNEL_4) pwm_object.timer_5.channel_4.pwm = this; } HAL_TIM_Base_Start(this->timer_handle); if((NULL != this->output_compare_cfg) && (NULL != this->master_cfg)) { /* pwm output */ HAL_TIM_PWM_Init(this->timer_handle); HAL_TIM_PWM_ConfigChannel(this->timer_handle, this->output_compare_cfg, this->channel); HAL_TIMEx_MasterConfigSynchronization(this->timer_handle, this->master_cfg); HAL_TIM_PWM_Start(this->timer_handle, this->channel); } else if((NULL != this->input_capture_init) && (NULL != this->slave_config)) { /* pwm input */ HAL_NVIC_SetPriority(irq_type, 5, 1); HAL_TIM_IC_Init(this->timer_handle); HAL_TIM_IC_ConfigChannel(this->timer_handle, this->input_capture_init, this->channel); HAL_TIM_SlaveConfigSynchronization(this->timer_handle, this->slave_config); HAL_TIM_IC_Start_IT(this->timer_handle, this->channel); HAL_NVIC_EnableIRQ(irq_type); } return 0; } int stm32f4_pwm_close(const void *pwm) { if(NULL == pwm) return -1; stm32f4_pwm_set_duty_cycle(pwm, 0); struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; HAL_TIM_Base_Stop(this->timer_handle); if((NULL != this->output_compare_cfg) && (NULL != this->master_cfg)) { HAL_TIM_PWM_Stop(this->timer_handle, this->channel); } else if((NULL != this->input_capture_init) && (NULL != this->slave_config)) { HAL_TIM_IC_Stop_IT(this->timer_handle, this->channel); } return 0; } int stm32f4_pwm_set_duty_cycle(const void *pwm, unsigned int duty_cycle_percent) { if(NULL == pwm) return -1; struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; __HAL_TIM_SET_COMPARE(this->timer_handle, this->channel, this->timer_handle->Init.Period * duty_cycle_percent / 100); return 0; } int stm32f4_pwm_get_period_ns(const void *pwm) { if(NULL == pwm) return -1; struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; int ret = 0; if(this->timer_handle->Instance == TIM2) { if(this->channel == TIM_CHANNEL_1) { ret = (int)pwm_object.timer_2.channel_1.period; return ret * pwm_object.timer_2.channel_1.pwm->timer_handle->Init.Prescaler / pwm_object.timer_2.channel_1.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_2) { ret = (int)pwm_object.timer_2.channel_2.period; return ret * pwm_object.timer_2.channel_2.pwm->timer_handle->Init.Prescaler / pwm_object.timer_2.channel_2.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_3) { ret = (int)pwm_object.timer_2.channel_3.period; return ret * pwm_object.timer_2.channel_3.pwm->timer_handle->Init.Prescaler / pwm_object.timer_2.channel_3.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_4) { ret = (int)pwm_object.timer_2.channel_4.period; return ret * pwm_object.timer_2.channel_4.pwm->timer_handle->Init.Prescaler / pwm_object.timer_2.channel_4.pwm->timer_src_frequency_MHz; } } else if(this->timer_handle->Instance == TIM4) { if(this->channel == TIM_CHANNEL_1) { ret = (int)pwm_object.timer_4.channel_1.period; return ret * pwm_object.timer_4.channel_1.pwm->timer_handle->Init.Prescaler / pwm_object.timer_4.channel_1.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_2) { ret = (int)pwm_object.timer_4.channel_2.period; return ret * pwm_object.timer_4.channel_2.pwm->timer_handle->Init.Prescaler / pwm_object.timer_4.channel_2.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_3) { ret = (int)pwm_object.timer_4.channel_3.period; return ret * pwm_object.timer_4.channel_3.pwm->timer_handle->Init.Prescaler / pwm_object.timer_4.channel_3.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_4) { ret = (int)pwm_object.timer_4.channel_4.period; return ret * pwm_object.timer_4.channel_4.pwm->timer_handle->Init.Prescaler / pwm_object.timer_4.channel_4.pwm->timer_src_frequency_MHz; } } else if(this->timer_handle->Instance == TIM5) { if(this->channel == TIM_CHANNEL_1) { ret = (int)pwm_object.timer_5.channel_1.period; return ret * pwm_object.timer_5.channel_1.pwm->timer_handle->Init.Prescaler / pwm_object.timer_5.channel_1.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_2) { ret = (int)pwm_object.timer_5.channel_2.period; return ret * pwm_object.timer_5.channel_2.pwm->timer_handle->Init.Prescaler / pwm_object.timer_5.channel_2.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_3) { ret = (int)pwm_object.timer_5.channel_3.period; return ret * pwm_object.timer_5.channel_3.pwm->timer_handle->Init.Prescaler / pwm_object.timer_5.channel_3.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_4) { ret = (int)pwm_object.timer_5.channel_4.period; return ret * pwm_object.timer_5.channel_4.pwm->timer_handle->Init.Prescaler / pwm_object.timer_5.channel_4.pwm->timer_src_frequency_MHz; } } return 0; } int stm32f4_pwm_get_pulse_width_ns(const void *pwm) { if(NULL == pwm) return -1; struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; int ret = 0; if(this->timer_handle->Instance == TIM2) { if(this->channel == TIM_CHANNEL_1) { ret = (int)pwm_object.timer_2.channel_1.pulse; return ret * pwm_object.timer_2.channel_1.pwm->timer_handle->Init.Prescaler / pwm_object.timer_2.channel_1.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_2) { ret = (int)pwm_object.timer_2.channel_2.pulse; return ret * pwm_object.timer_2.channel_2.pwm->timer_handle->Init.Prescaler / pwm_object.timer_2.channel_2.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_3) { ret = (int)pwm_object.timer_2.channel_3.pulse; return ret * pwm_object.timer_2.channel_3.pwm->timer_handle->Init.Prescaler / pwm_object.timer_2.channel_3.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_4) { ret = (int)pwm_object.timer_2.channel_4.pulse; return ret * pwm_object.timer_2.channel_4.pwm->timer_handle->Init.Prescaler / pwm_object.timer_2.channel_4.pwm->timer_src_frequency_MHz; } } else if(this->timer_handle->Instance == TIM4) { if(this->channel == TIM_CHANNEL_1) { ret = (int)pwm_object.timer_4.channel_1.pulse; return ret * pwm_object.timer_4.channel_1.pwm->timer_handle->Init.Prescaler / pwm_object.timer_4.channel_1.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_2) { ret = (int)pwm_object.timer_4.channel_2.pulse; return ret * pwm_object.timer_4.channel_2.pwm->timer_handle->Init.Prescaler / pwm_object.timer_4.channel_2.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_3) { ret = (int)pwm_object.timer_4.channel_3.pulse; return ret * pwm_object.timer_4.channel_3.pwm->timer_handle->Init.Prescaler / pwm_object.timer_4.channel_3.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_4) { ret = (int)pwm_object.timer_4.channel_4.pulse; return ret * pwm_object.timer_4.channel_4.pwm->timer_handle->Init.Prescaler / pwm_object.timer_4.channel_4.pwm->timer_src_frequency_MHz; } } else if(this->timer_handle->Instance == TIM5) { if(this->channel == TIM_CHANNEL_1) { ret = (int)pwm_object.timer_5.channel_1.pulse; return ret * pwm_object.timer_5.channel_1.pwm->timer_handle->Init.Prescaler / pwm_object.timer_5.channel_1.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_2) { ret = (int)pwm_object.timer_5.channel_2.pulse; return ret * pwm_object.timer_5.channel_2.pwm->timer_handle->Init.Prescaler / pwm_object.timer_5.channel_2.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_3) { ret = (int)pwm_object.timer_5.channel_3.pulse; return ret * pwm_object.timer_5.channel_3.pwm->timer_handle->Init.Prescaler / pwm_object.timer_5.channel_3.pwm->timer_src_frequency_MHz; } else if(this->channel == TIM_CHANNEL_4) { ret = (int)pwm_object.timer_5.channel_4.pulse; return ret * pwm_object.timer_5.channel_4.pwm->timer_handle->Init.Prescaler / pwm_object.timer_5.channel_4.pwm->timer_src_frequency_MHz; } } return 0; } static void handle_irq_tim2_cc1(TIM_HandleTypeDef *timer_handle) { /* Capture compare 1 event */ if(__HAL_TIM_GET_FLAG(timer_handle, TIM_FLAG_CC1) != RESET) { if(__HAL_TIM_GET_IT_SOURCE(timer_handle, TIM_IT_CC1) != RESET) { __HAL_TIM_CLEAR_IT(timer_handle, TIM_IT_CC1); /* Input capture event */ if((timer_handle->Instance->CCMR2 & TIM_CCMR1_CC1S) != 0x00U) { uint32_t read = timer_handle->Instance->CCR1; if(pwm_object.timer_2.channel_1.pwm->input_capture_init->ICPolarity == TIM_ICPOLARITY_BOTHEDGE) { GPIO_TypeDef* port = pwm_object.timer_2.channel_1.pwm->pwm_gpio->port; uint16_t pin = pwm_object.timer_2.channel_1.pwm->pwm_gpio->pin->Pin; if(GPIO_PIN_SET == HAL_GPIO_ReadPin(port, pin)) { if(read > pwm_object.timer_2.channel_1.period_start) pwm_object.timer_2.channel_1.period = read - pwm_object.timer_2.channel_1.period_start; pwm_object.timer_2.channel_1.period_start = read; pwm_object.timer_2.channel_1.pulse_start = read; } else { if(read > pwm_object.timer_2.channel_1.pulse_start) pwm_object.timer_2.channel_1.pulse = read - pwm_object.timer_2.channel_1.pulse_start; } } } } } } static void handle_irq_tim2_cc2(TIM_HandleTypeDef *timer_handle) { /* Capture compare 2 event */ if(__HAL_TIM_GET_FLAG(timer_handle, TIM_FLAG_CC2) != RESET) { if(__HAL_TIM_GET_IT_SOURCE(timer_handle, TIM_IT_CC2) != RESET) { __HAL_TIM_CLEAR_IT(timer_handle, TIM_IT_CC2); /* Input capture event */ if((timer_handle->Instance->CCMR2 & TIM_CCMR1_CC2S) != 0x00U) { uint32_t read = timer_handle->Instance->CCR2; if(pwm_object.timer_2.channel_2.pwm->input_capture_init->ICPolarity == TIM_ICPOLARITY_BOTHEDGE) { GPIO_TypeDef* port = pwm_object.timer_2.channel_2.pwm->pwm_gpio->port; uint16_t pin = pwm_object.timer_2.channel_2.pwm->pwm_gpio->pin->Pin; if(GPIO_PIN_SET == HAL_GPIO_ReadPin(port, pin)) { if(read > pwm_object.timer_2.channel_2.period_start) pwm_object.timer_2.channel_2.period = read - pwm_object.timer_2.channel_2.period_start; pwm_object.timer_2.channel_2.period_start = read; pwm_object.timer_2.channel_2.pulse_start = read; } else { if(read > pwm_object.timer_2.channel_2.pulse_start) pwm_object.timer_2.channel_2.pulse = read - pwm_object.timer_2.channel_2.pulse_start; } } } } } } static void handle_irq_tim2_cc3(TIM_HandleTypeDef *timer_handle) { /* Capture compare 3 event */ if(__HAL_TIM_GET_FLAG(timer_handle, TIM_FLAG_CC3) != RESET) { if(__HAL_TIM_GET_IT_SOURCE(timer_handle, TIM_IT_CC3) != RESET) { __HAL_TIM_CLEAR_IT(timer_handle, TIM_IT_CC3); /* Input capture event */ if((timer_handle->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U) { uint32_t read = timer_handle->Instance->CCR3; if(pwm_object.timer_2.channel_3.pwm->input_capture_init->ICPolarity == TIM_ICPOLARITY_BOTHEDGE) { GPIO_TypeDef* port = pwm_object.timer_2.channel_3.pwm->pwm_gpio->port; uint16_t pin = pwm_object.timer_2.channel_3.pwm->pwm_gpio->pin->Pin; if(GPIO_PIN_SET == HAL_GPIO_ReadPin(port, pin)) { if(read > pwm_object.timer_2.channel_3.period_start) pwm_object.timer_2.channel_3.period = read - pwm_object.timer_2.channel_3.period_start; pwm_object.timer_2.channel_3.period_start = read; pwm_object.timer_2.channel_3.pulse_start = read; } else { if(read > pwm_object.timer_2.channel_3.pulse_start) pwm_object.timer_2.channel_3.pulse = read - pwm_object.timer_2.channel_3.pulse_start; } } } } } } static void handle_irq_tim2_cc4(TIM_HandleTypeDef *timer_handle) { /* Capture compare 4 event */ if(__HAL_TIM_GET_FLAG(timer_handle, TIM_FLAG_CC4) != RESET) { if(__HAL_TIM_GET_IT_SOURCE(timer_handle, TIM_IT_CC4) != RESET) { __HAL_TIM_CLEAR_IT(timer_handle, TIM_IT_CC4); /* Input capture event */ if((timer_handle->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U) { uint32_t read = timer_handle->Instance->CCR4; if(pwm_object.timer_2.channel_4.pwm->input_capture_init->ICPolarity == TIM_ICPOLARITY_BOTHEDGE) { GPIO_TypeDef* port = pwm_object.timer_2.channel_4.pwm->pwm_gpio->port; uint16_t pin = pwm_object.timer_2.channel_4.pwm->pwm_gpio->pin->Pin; if(GPIO_PIN_SET == HAL_GPIO_ReadPin(port, pin)) { if(read > pwm_object.timer_2.channel_4.period_start) pwm_object.timer_2.channel_4.period = read - pwm_object.timer_2.channel_4.period_start; pwm_object.timer_2.channel_4.period_start = read; pwm_object.timer_2.channel_4.pulse_start = read; } else { if(read > pwm_object.timer_2.channel_4.pulse_start) pwm_object.timer_2.channel_4.pulse = read - pwm_object.timer_2.channel_4.pulse_start; } } } } } } void TIM2_IRQHandler(void) { enter_isr(); handle_irq_tim2_cc1(pwm_object.timer_2.channel_1.pwm->timer_handle); handle_irq_tim2_cc2(pwm_object.timer_2.channel_2.pwm->timer_handle); handle_irq_tim2_cc3(pwm_object.timer_2.channel_3.pwm->timer_handle); handle_irq_tim2_cc4(pwm_object.timer_2.channel_4.pwm->timer_handle); exit_isr(); }