100 lines
2.9 KiB
C
100 lines
2.9 KiB
C
|
/*
|
||
|
* stm32f4_pwm.c
|
||
|
*
|
||
|
* Created on: Aug 9, 2016
|
||
|
* Author: tkl
|
||
|
*/
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#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;
|
||
|
}
|
||
|
}
|