cancel
Showing results for 
Search instead for 
Did you mean: 

Trouble with using TIM8 for PWM

jbsnyder
Associate II
Posted on July 10, 2009 at 05:30

Trouble with using TIM8 for PWM

16 REPLIES 16
jbsnyder
Associate II
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
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
Associate II
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 ]

jbsnyder
Associate II
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 🙂

swhite
Associate III
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 😉

swhite
Associate III
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?

ozenozkaya
Associate II
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);

jbsnyder
Associate II
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
Posted on May 17, 2011 at 13:16

i forgot writing it:

i had already included it:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM3 , ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);