From d14354e47c046f261bc73fee0931bb2de3b9d931 Mon Sep 17 00:00:00 2001 From: tkl Date: Tue, 9 Aug 2016 11:57:54 +0200 Subject: [PATCH] wip --- .../stm32f4xx/driver/include/stm32f4_pwm.h | 34 +++++++ .../arch/stm32f4xx/driver/stm32f4_pwm.c | 99 +++++++++++++++++++ source/test/pwm/main.c | 82 ++------------- 3 files changed, 141 insertions(+), 74 deletions(-) create mode 100644 source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h create mode 100644 source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c diff --git a/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h b/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h new file mode 100644 index 0000000..2e1dff4 --- /dev/null +++ b/source/firmware/arch/stm32f4xx/driver/include/stm32f4_pwm.h @@ -0,0 +1,34 @@ +/* + * stm32f4_pwm.h + * + * Created on: Aug 9, 2016 + * Author: tkl + */ + +#ifndef SOURCE_FIRMWARE_ARCH_STM32F4XX_DRIVER_INCLUDE_STM32F4_PWM_H_ +#define SOURCE_FIRMWARE_ARCH_STM32F4XX_DRIVER_INCLUDE_STM32F4_PWM_H_ + +enum stm32f4_pwm_channel { + channel_1 = 1, + channel_2, + channel_3, + channel_4 +}; + +struct stm32f4_pwm { + TIM_TypeDef *timer; + const TIM_TimeBaseInitTypeDef *timer_cfg; + const TIM_OCInitTypeDef *output_compare_cfg; + const TIM_BDTRInitTypeDef *bdtr_cfg; + GPIO_TypeDef *port; + uint8_t pin_src; + const GPIO_InitTypeDef *port_cfg; + enum stm32f4_pwm_channel channel; +}; + + +int stm32f4_pwm_open(struct stm32f4_pwm *pwm); +int stm32f4_pwm_close(struct stm32f4_pwm *pwm); +int stm32f4_pwm_set_duty_cycle(struct stm32f4_pwm *pwm, unsigned int duty_cycle_percent); + +#endif /* SOURCE_FIRMWARE_ARCH_STM32F4XX_DRIVER_INCLUDE_STM32F4_PWM_H_ */ diff --git a/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c b/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c new file mode 100644 index 0000000..8b8505d --- /dev/null +++ b/source/firmware/arch/stm32f4xx/driver/stm32f4_pwm.c @@ -0,0 +1,99 @@ +/* + * stm32f4_pwm.c + * + * Created on: Aug 9, 2016 + * Author: tkl + */ +#include + +#include "stm32f4xx.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(struct stm32f4_pwm *pwm) +{ + uint32_t clk_ahb_timer = 0, clk_ahb_gpio = 0; + uint8_t gpio_af_timer = 0; + if(pwm->timer == TIM4) { + clk_ahb_timer = RCC_APB1Periph_TIM4; + gpio_af_timer = GPIO_AF_TIM4; + } + RCC_APB1PeriphClockCmd(clk_ahb_timer, ENABLE); + if(pwm->port == GPIOD) { + clk_ahb_gpio = RCC_AHB1Periph_GPIOD; + } + RCC_AHB1PeriphClockCmd(clk_ahb_gpio, ENABLE); + GPIO_Init(pwm->port, (GPIO_InitTypeDef *)pwm->port_cfg); + GPIO_PinAFConfig(pwm->port, pwm->pin_src, gpio_af_timer); + + TIM_TimeBaseInit(pwm->timer, (TIM_TimeBaseInitTypeDef *)pwm->timer_cfg); + + switch(pwm->channel) { + case channel_1: + TIM_OC1Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg); + TIM_OC1PreloadConfig(pwm->timer, TIM_OCPreload_Enable); + stm32f4_pwm_object.channel_1_max_period = pwm->timer_cfg->TIM_Period + 1; + break; + case channel_2: + TIM_OC2Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg); + TIM_OC2PreloadConfig(pwm->timer, TIM_OCPreload_Enable); + stm32f4_pwm_object.channel_2_max_period = pwm->timer_cfg->TIM_Period + 1; + break; + case channel_3: + TIM_OC3Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg); + TIM_OC3PreloadConfig(pwm->timer, TIM_OCPreload_Enable); + stm32f4_pwm_object.channel_3_max_period = pwm->timer_cfg->TIM_Period + 1; + break; + case channel_4: + TIM_OC4Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg); + TIM_OC4PreloadConfig(pwm->timer, TIM_OCPreload_Enable); + stm32f4_pwm_object.channel_4_max_period = pwm->timer_cfg->TIM_Period + 1; + break; + } + TIM_ARRPreloadConfig(pwm->timer, ENABLE); + TIM_Cmd(pwm->timer, ENABLE); + stm32f4_pwm_object.used_channels++; + return 0; +} + +int stm32f4_pwm_close(struct stm32f4_pwm *pwm) +{ + stm32f4_pwm_object.used_channels--; + if(stm32f4_pwm_object.used_channels == 0) { + TIM_Cmd(pwm->timer, DISABLE); + } + return 0; +} + +int stm32f4_pwm_set_duty_cycle(struct stm32f4_pwm *pwm, unsigned int duty_cycle_percent) +{ + switch(pwm->channel) { + case channel_1: + TIM_SetCompare1(pwm->timer, stm32f4_pwm_object.channel_1_max_period * duty_cycle_percent / 100); + break; + case channel_2: + TIM_SetCompare2(pwm->timer, stm32f4_pwm_object.channel_2_max_period * duty_cycle_percent / 100); + break; + case channel_3: + TIM_SetCompare3(pwm->timer, stm32f4_pwm_object.channel_3_max_period * duty_cycle_percent / 100); + break; + case channel_4: + TIM_SetCompare4(pwm->timer, stm32f4_pwm_object.channel_4_max_period * duty_cycle_percent / 100); + break; + } +} diff --git a/source/test/pwm/main.c b/source/test/pwm/main.c index fde0061..edcbf59 100644 --- a/source/test/pwm/main.c +++ b/source/test/pwm/main.c @@ -17,24 +17,7 @@ #include "shell.h" #include "stm32f4xx.h" - -enum stm32f4_pwm_channel { - channel_1 = 1, - channel_2, - channel_3, - channel_4 -}; - -struct stm32f4_pwm { - TIM_TypeDef *timer; - const TIM_TimeBaseInitTypeDef *timer_cfg; - const TIM_OCInitTypeDef *output_compare_cfg; - const TIM_BDTRInitTypeDef *bdtr_cfg; - GPIO_TypeDef *port; - uint8_t pin_src; - const GPIO_InitTypeDef *port_cfg; - enum stm32f4_pwm_channel channel; -}; +#include "stm32f4_pwm.h" /* apb1 clock = 84MHz */ /* period_reg = src_clk / presc / cnt_clk */ @@ -76,74 +59,25 @@ static struct stm32f4_pwm str32f4_pwm = { .channel = channel_4, }; -extern uint32_t SystemCoreClock; -void pwm_open(struct stm32f4_pwm *pwm) -{ - - uint32_t clk_ahb_timer = 0, clk_ahb_gpio = 0; - uint8_t gpio_af_timer = 0; - if(pwm->timer == TIM4) { - clk_ahb_timer = RCC_APB1Periph_TIM4; - gpio_af_timer = GPIO_AF_TIM4; - } - RCC_APB1PeriphClockCmd(clk_ahb_timer, ENABLE); - if(pwm->port == GPIOD) { - clk_ahb_gpio = RCC_AHB1Periph_GPIOD; - } - /* LEDs are on GPIOD */ - RCC_AHB1PeriphClockCmd(clk_ahb_gpio, ENABLE); - GPIO_Init(pwm->port, (GPIO_InitTypeDef *)pwm->port_cfg); - GPIO_PinAFConfig(pwm->port, pwm->pin_src, gpio_af_timer); - - /* Time base configuration */ - TIM_TimeBaseInit(pwm->timer, (TIM_TimeBaseInitTypeDef *)pwm->timer_cfg); - - switch(pwm->channel) { - case channel_1: - TIM_OC1Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg); - TIM_OC1PreloadConfig(pwm->timer, TIM_OCPreload_Enable); - break; - case channel_2: - TIM_OC2Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg); - TIM_OC2PreloadConfig(pwm->timer, TIM_OCPreload_Enable); - break; - case channel_3: - TIM_OC3Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg); - TIM_OC3PreloadConfig(pwm->timer, TIM_OCPreload_Enable); - break; - case channel_4: - TIM_OC4Init(pwm->timer, (TIM_OCInitTypeDef *)pwm->output_compare_cfg); - TIM_OC4PreloadConfig(pwm->timer, TIM_OCPreload_Enable); - break; - } - TIM_ARRPreloadConfig(pwm->timer, ENABLE); - TIM_Cmd(pwm->timer, ENABLE); -} #define TH_STACK_SIZE 256 stack_t th_stack[TH_STACK_SIZE]; struct thread_context th_ctx; static void th_func(void *arg) { - uint32_t brightness = 4200 / 2; - TIM4->CCR4 = brightness; + unsigned int duty = 0; while(1) { - brightness++; - if(brightness == UINT32_MAX) - brightness = 0; -#if 0 - TIM4->CCR3 = 333 - (brightness + 0) % 333; // set brightness - TIM4->CCR4 = 333 - (brightness + 166/2) % 333; // set brightness - TIM4->CCR1 = 333 - (brightness + 333/2) % 333; // set brightness - TIM4->CCR2 = 333 - (brightness + 499/2) % 333; // set brightness -#endif - sleep_ms(1); + stm32f4_pwm_set_duty_cycle(&str32f4_pwm, duty); + sleep_ms(100); + duty++; + if(duty > 100) + duty = 0; } } int main(void) { - pwm_open(&str32f4_pwm); + stm32f4_pwm_open(&str32f4_pwm); thread_create(&th_ctx, th_stack, TH_STACK_SIZE, th_func, NULL, THREAD_PRIO_LOW); schedule_start();