/* * stm32f4_pwm.c * * Created on: Aug 9, 2016 * Author: tkl */ #include #include #include "stm32f4xx.h" #include "pwm.h" #include "stm32f4_pwm.h" struct stm32f4_pwm_object { uint8_t used_channels; uint32_t channel_1_max_period; uint32_t channel_2_max_period; uint32_t channel_3_max_period; uint32_t channel_4_max_period; }; static struct stm32f4_pwm_object stm32f4_pwm_object = { .used_channels = 0, .channel_1_max_period = 0, .channel_2_max_period = 0, .channel_3_max_period = 0, .channel_4_max_period = 0, }; int stm32f4_pwm_open(const void *pwm) { if(NULL == pwm) return -1; struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; uint32_t clk_ahb_timer = 0, clk_ahb_gpio = 0; uint8_t gpio_af_timer = 0; if(this->timer == TIM4) { clk_ahb_timer = RCC_APB1Periph_TIM4; gpio_af_timer = GPIO_AF_TIM4; } RCC_APB1PeriphClockCmd(clk_ahb_timer, ENABLE); if(this->port == GPIOD) { clk_ahb_gpio = RCC_AHB1Periph_GPIOD; } RCC_AHB1PeriphClockCmd(clk_ahb_gpio, ENABLE); GPIO_Init(this->port, (GPIO_InitTypeDef *)this->port_cfg); GPIO_PinAFConfig(this->port, this->pin_src, gpio_af_timer); TIM_TimeBaseInit(this->timer, (TIM_TimeBaseInitTypeDef *)this->timer_cfg); switch(this->channel) { case channel_1: TIM_OC1Init(this->timer, (TIM_OCInitTypeDef *)this->output_compare_cfg); TIM_OC1PreloadConfig(this->timer, TIM_OCPreload_Enable); stm32f4_pwm_object.channel_1_max_period = this->timer_cfg->TIM_Period + 1; break; case channel_2: TIM_OC2Init(this->timer, (TIM_OCInitTypeDef *)this->output_compare_cfg); TIM_OC2PreloadConfig(this->timer, TIM_OCPreload_Enable); stm32f4_pwm_object.channel_2_max_period = this->timer_cfg->TIM_Period + 1; break; case channel_3: TIM_OC3Init(this->timer, (TIM_OCInitTypeDef *)this->output_compare_cfg); TIM_OC3PreloadConfig(this->timer, TIM_OCPreload_Enable); stm32f4_pwm_object.channel_3_max_period = this->timer_cfg->TIM_Period + 1; break; case channel_4: TIM_OC4Init(this->timer, (TIM_OCInitTypeDef *)this->output_compare_cfg); TIM_OC4PreloadConfig(this->timer, TIM_OCPreload_Enable); stm32f4_pwm_object.channel_4_max_period = this->timer_cfg->TIM_Period + 1; break; } TIM_ARRPreloadConfig(this->timer, ENABLE); TIM_Cmd(this->timer, ENABLE); stm32f4_pwm_object.used_channels++; return 0; } int stm32f4_pwm_close(const void *pwm) { if(NULL == pwm) return -1; struct stm32f4_pwm *this = (struct stm32f4_pwm *)pwm; stm32f4_pwm_set_duty_cycle(pwm, 0); stm32f4_pwm_object.used_channels--; if(stm32f4_pwm_object.used_channels == 0) { TIM_Cmd(this->timer, DISABLE); } 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; switch(this->channel) { case channel_1: TIM_SetCompare1(this->timer, stm32f4_pwm_object.channel_1_max_period * duty_cycle_percent / 100); break; case channel_2: TIM_SetCompare2(this->timer, stm32f4_pwm_object.channel_2_max_period * duty_cycle_percent / 100); break; case channel_3: TIM_SetCompare3(this->timer, stm32f4_pwm_object.channel_3_max_period * duty_cycle_percent / 100); break; case channel_4: TIM_SetCompare4(this->timer, stm32f4_pwm_object.channel_4_max_period * duty_cycle_percent / 100); break; } return 0; }