Skip to main content
jbsnyder
Associate
July 10, 2009
Question

Trouble with using TIM8 for PWM

  • July 10, 2009
  • 16 replies
  • 3000 views
Posted on July 10, 2009 at 05:30

Trouble with using TIM8 for PWM

    This topic has been closed for replies.

    16 replies

    jbsnyder
    jbsnyderAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    I've gone up and down my code a number of times attempting to configure PWM output for the default TIM8_CHx pins, but I never seem to get any actual output on the pins themselves. I can tell that the timer is cycling over the expected range, and that the port is configured in push-pull (I can even manually drive it up and down), but the OC events don't seem to be causing the pins to go high and low, regardless of what I try.

    The setup code is included in this file:

    http://github.com/jsnyder/elua/blob/5213ff7bdf4c12e708dafea507e3179376bba13e/src/platform/stm32/platform.c

    platform_init is run on startup and all of the associated peripherals get their clocks turned on and whatnot. A few things might be commented out in there now that would prevent things like CAN from coming up correctly, but what I'm curious about is why PWM will not work for me. A version that should follow the general order of things from the source file follows.

    (ptimer is TIM8)

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM8, ENABLE );

    TIM_Cmd(ptimer, DISABLE);

    TIM_SetCounter( ptimer, 0 );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOC, &GPIO_InitStructure);

    TIM_TimeBaseStructure.TIM_Period = 999; //(TIM_GET_BASE_CLK( PWM_TIMER_ID ) / clock) - 1;

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;

    TIM_TimeBaseInit( ptimer, &TIM_TimeBaseStructure );

    TIM_ARRPreloadConfig( ptimer, ENABLE );

    /* PWM Mode configuration */

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;

    TIM_OCInitStructure.TIM_Pulse = 125;

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

    TIM_OC1Init( ptimer, &TIM_OCInitStructure );

    TIM_OC1PreloadConfig( ptimer, TIM_OCPreload_Enable );

    TIM_CtrlPWMOutputs(ptimer, ENABLE);

    TIM_Cmd( ptimer, ENABLE );

    I'm wondering if some other peripheral I'm bringing up is causing the output pins to no longer respond to OC, or if there's some other suggestion for why the clock might be running but the pin doesn't pull up and down as it goes through the different OC stages. I think I've essentially verified that things are getting set up as the documentation.

    FYI: the reason so many devices are being activated is that this is a peripheral interface for Lua. It could all be done a bit more efficiently, but I'm more interested in why this is failing for me.

    I'm using an STM32F103RET6, which should be revz.

    I should also mention that I've had no success getting things working with the general purpose timers on this device either (with configuration adjusted per the examples that come with the driver library).

    [ This message was edited by: jbsnyder on 08-07-2009 20:31 ]

    swhite
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    Quote:

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    Try changing this line to

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    I see you already have the

    TIM_CtrlPWMOutputs(TIMx, ENABLE);

    line which stumped me for a while ;) For newbies Timers 1 & 8 have a ''brake'' function so if you forget this line the PWM's don't work.

    jbsnyder
    jbsnyderAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    *bangs head against desk*

    Yep, AF_PP was the right mode instead of Out_PP. I'm not sure I understand why it needs to be set as an alternate function given it's one of the default pin mappings, but whatever :)

    swhite
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    Quote:

    *bangs head against desk*

    But it feels so good when you stop :) Believe me I have lots of ''desk marks'' on my forehead.

    So I assume PWM is working now?

    swhite
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    Quote:

    Or, is it always necessary for when a periph is driving the pin?

    That one.

    Remapping peripheral I/O is a whole other issue ;)

    jbsnyder
    jbsnyderAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    Indeed, it seems to be working perfectly as far as I can tell (haven't tested everything yet) with that single change. Thanks very much for that one. I spent a great deal of yesterday digging through the reference manual and trying to track down every register that needed to be set correctly. Unfortunately, I missed one...

    Some things have been dead simple to get going with these drivers (CAN, for example), but the configuration model is towards the complicated end of the spectrum of devices I've worked with, and so I've definitely run into more gotchas like this with the STM32 driver lib than with others. I wish they would mention in the PWM section of the manual that in addition to being dependent on all those other timer register parameters, it's also critical that the associated pin be set in the right push-pull output mode.

    Is the AF mode necessary for any situation where a peripheral is driving a pin if said peripheral is not listed as the first function for that pin? Or, is it always necessary for when a periph is driving the pin?

    Ah well, I learned more about the wide range of configuration of PWM on this platform :)

    jbsnyder
    jbsnyderAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    One thing that initially struck me that you might be missing is turning on the peripheral clock for GPIOC:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    I'm pretty sure that one needs both the AFIO & GPIOC clocks enabled.

    ozenozkaya
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    i am trying to use TIM3 Channel 1 as PWM from PC6 as AF; but the brigthness doesnt change. what am i doing wrong?? pls help...

    here is the code:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM3 , ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    TIM_OCInitTypeDef TIM_OCInitStructure;

    //this pin functions as AF; when remapping

    GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);

    /*GPIOC Configuration: TIM3 channel 1 */

    /* make sure that C port is opened in RCC*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOC, &GPIO_InitStructure);

    TIM_Cmd(TIM3, DISABLE);

    TIM_ARRPreloadConfig(TIM3, ENABLE);

    /* Time base configuration */

    TIM_TimeBaseStructure.TIM_Period = 999;

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    /* PWM1 Mode configuration: Channel1 */

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

    TIM_OCInitStructure.TIM_Channel = TIM_Channel_1;

    TIM_OCInitStructure.TIM_Pulse = 500;

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OCInit(TIM3, &TIM_OCInitStructure);

    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);

    TIM_ARRPreloadConfig(TIM3, ENABLE);

    /* TIM3 enable counter */

    TIM_Cmd(TIM3, ENABLE);

    TIM_SetCompare1(TIM3,0x10);

    ozenozkaya
    Associate II
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    you are right! tim3 is not running;

    when i watch a=TIM_GetCounter(TIM3); a is always 0. what can be the reason for TIM3 problem?

    jbsnyder
    jbsnyderAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 13:16

    Hmm.. otherwise I'm not sure.

    You probably shouldn't need the TIM_SetCompare1 since that should already be set with the TIM_Pulse.

    Have you checked that the timer is actually running? I.e.: maybe run in a loop and get the counter value and set a pin based on that that you can check with a scope.

    You could also use things like: TIM_ForcedOC1Config to see if forcing the OC state causes your PWM pin to change.

    You could also try initiating an immediate update of some of the registers using: TIM_PrescalerConfig

    Not sure if all of those are present in your version of the drivers.