cancel
Showing results for 
Search instead for 
Did you mean: 

[stm32f3]can't make PWM output work

bifrost
Associate II
Posted on September 01, 2013 at 19:04

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;

}

#stm32f3-pwm #pwm-ppm-tim4
2 REPLIES 2
Posted on September 01, 2013 at 20:27

 RCC_APB2PeriphClockCmd(RCC_APB1Periph_TIM4 , ENABLE ); // What APB?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bifrost
Associate II
Posted on September 06, 2013 at 11:40

you are right, also some error here and there 8like using pin 10 and 11 instad of 14 and

Finally this is the working code:

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_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
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_PinSource12, GPIO_AF_2 );
GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_2 );
GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_2 );
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_2 );
NVIC_InitTypeDef NVIC_InitStructure;
/* Here you can 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);
uint16_t prescaler = (uint16_t) ((RCC_Clocks.HCLK_Frequency / 1000000) - 1); 
// Shooting for 1 MHz, (1us)
uint32_t pwm_period = 20000;
// Enable the TIM4 peripherie
RCC_APB1PeriphClockCmd(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(TIM4, &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 = 800; 
// 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);