AnsweredAssumed Answered

[stm32f3]can't make PWM output work

Question asked by fante.lesto on Sep 1, 2013
Latest reply on Sep 6, 2013 by fante.lesto
i'm tryng to simply get 50Hz PWM out of 4 pin, timer used is TIM4, pins are D10, D11, D12 and D13.
but i get a fixed HIGH..

code:

int init_pwm2(int pwm_freq)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    /*Enable or disable the AHB peripheral clock */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);

    /*Configure GPIO pin */
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* Connect TIM4 pins to AF2 */
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_2);
    GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_2);

    NVIC_InitTypeDef NVIC_InitStructure;

    /* Enable the TIM4 gloabal Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // Calculates the timing. This is common for all channels
    uint32_t clk = RCC_Clocks.HCLK_Frequency; // 72MHz -> system core clock. This is default on the stm32f3 discovery
    //RCC_Clocks.PCLK1_Frequency;
    uint32_t tim_freq = 2e6; // in Hz (2MHz) Base frequency of the pwm timer
    uint32_t prescaler = ((clk / tim_freq) - 1);

    // Calculate the period for a given pwm frequency
    //        int pwm_freq = 200; // in Hz
    uint32_t pwm_period = tim_freq/pwm_freq;        // 2MHz / 200Hz = 10000
                                                // For 50Hz we get: 2MHz / 50Hz = 40000

    // Calculate a number of pulses per millisecond.
    // Not used in this rutine but I put it here just as an example
    uint32_t ms_pulses = (float)pwm_period / (1000.0/pwm_freq); // for 200Hz we get: 10000 / (1/200 * 1000) = 2000


//  Enable the TIM1 peripherie
    RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM4 , ENABLE );

// Setup the timing and configure the TIM1 timer
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_TimeBaseStructInit(& TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Prescaler = prescaler;
    TIM_TimeBaseStructure.TIM_Period = pwm_period - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up ;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);


// Initialise the timer channels
    TIM_OCInitTypeDef  TIM_OCInitStructure;

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_Pulse = ms_pulses/2; // preset pulse width 0..pwm_period
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // Pulse polarity
    //      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

    // These settings must be applied on the timer 1.
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;

// Setup four channels
    // Channel 1, pin PD10?
    TIM_OC1Init(TIM4, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);

    // Channel 2, pin PD11?
    TIM_OC2Init(TIM4, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);

    // Channel 3, pin PD12?
    TIM_OC3Init(TIM4, &TIM_OCInitStructure);
    TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);

    // Channel 4, pin PD13?
    TIM_OC4Init(TIM4, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);

    // Starup the timer
    //TIM_ARRPreloadConfig(TIM1, DISABLE);
    TIM_ARRPreloadConfig(TIM4, DISABLE);
    TIM_CtrlPWMOutputs(TIM4, ENABLE);
    TIM_Cmd(TIM4 , ENABLE);

    // The PWM is running now. The pulse width can be set by
    // TIM1->CCR1 = [0..pwm_period] -> 0..100% duty cycle
    //
    // For example:
    // int pulse_width = 3000;
    // TIM4->CCR1 = pulse_width;
    //
    // The firmware offers a API to do this:
    //TIM_SetCompare1(TIM4 , pulse_width); // This is a wrapper for TIM4->CCR1, the same as TIM4->CCR1=pulse_width;


    return pwm_period;
}

Outcomes