AnsweredAssumed Answered

STM32F407 PWM output high on startup

Question asked by Phil Pemberton on Mar 10, 2014
Latest reply on Mar 10, 2014 by Phil Pemberton
I'm using the PWM (driven by the DMA controller) to run a line of LEDs. These devices interpret a long high pulse as a start of packet. A pull-down resistor keeps the output in a 'safe' state until the I/Os are initialised.

Unfortunately when I initialise the timer for PWM (mode 1), the STM32F407VG (on a Discovery board) drives the PWM output high, confusing the LEDs. I can force the line low if I enable the timer, then immediately disable it:

#define PWM_TIMER    TIM3
#define TIM_COMPARE_LOW        9

But this still results in a momentary high glitch between the GPIO initialisation and the PWM bodge above. Is there a better way to do this?

I'm also interested if there's a better way to get the clock frequency of TIM3 -- at the moment I'm doing this, which is reliant on the code being updated if/when the stm32f4xx_system.c file is updated:

/* Compute the prescaler value */
RCC_ClocksTypeDef clocks;
PrescalerValue = (uint16_t) ((clocks.SYSCLK_Frequency / 4) / 24000000) - 1;

Here is my init code, for reference:

#define PWM_TIMER   TIM3
#define DMA_STREAM  DMA1_Stream2
#define DMA_CHANNEL DMA_Channel_5
#define DMA_SOURCE  TIM_DMA_Update
#define TIM_PERIOD          29
#define TIM_COMPARE_HIGH    18
#define TIM_COMPARE_LOW     9
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
    uint16_t PrescalerValue;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    /* GPIOB Configuration: PWM_TIMER Channel 1 as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_TIM3);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    /* Compute the prescaler value */
    RCC_ClocksTypeDef clocks;
    PrescalerValue = (uint16_t) ((clocks.SYSCLK_Frequency / 4) / 24000000) - 1;
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = TIM_PERIOD; // 800kHz
    TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(PWM_TIMER, &TIM_TimeBaseStructure);
    /* PWM1 Mode configuration: Channel1 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 0;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(PWM_TIMER, &TIM_OCInitStructure);
    // PAP: Start up TIM1 so that the PWM output is forced low (it starts out high)