2
\$\begingroup\$

I have configured timer 4 for PWM with following code and connected LED to the configured pin. It is working.

TIM_TimeBaseInitTypeDef TIM_BaseStruct;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);    // Enable bus clock

TIM_BaseStruct.TIM_Prescaler = 0;   // Set prescaler (frequency divider)
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_CenterAligned1;    // Set counting mode (up, down, center-aligned) to center aligned for better motor control
TIM_BaseStruct.TIM_Period = 4000; // Set timer period (timer reset/change direction value)
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_BaseStruct);    // Initialize timer with chosen settings
TIM_Cmd(TIM4, ENABLE);  // Start timer

GPIO_InitTypeDef GPIO_InitStruct;

/* Clock for GPIOD */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

/* Alternating functions for pins */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);

/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &GPIO_InitStruct);

TIM_OCInitTypeDef TIM_OCStruct;

TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;

TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCStruct.TIM_Pulse = 1999;
TIM_OC1Init(TIM4, &TIM_OCStruct);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);

but when I configured TIM 1 and connected LED to its pin, nothing happened (I tested pin separately by toggling it as output to make sure I connected LED to the right pin and it lit up)

TIM_TimeBaseInitTypeDef TIM_BaseStruct;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);    // Enable bus clock

TIM_BaseStruct.TIM_Prescaler = 1;   // Set prescaler (frequency divider)
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_CenterAligned1;    // Set counting mode (up, down, center-aligned) to center aligned for better motor control
TIM_BaseStruct.TIM_Period = 4000; // Set timer period (timer reset/change direction value)
TIM_BaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_BaseStruct);    // Initialize timer with chosen settings
TIM_Cmd(TIM1, ENABLE);  // Start timer

GPIO_InitTypeDef GPIO_InitStruct;

/* Clock for GPIOE */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

/* Alternating functions for pins */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_TIM1);

/* Set pins */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOE, &GPIO_InitStruct);

TIM_OCInitTypeDef TIM_OCStruct;

TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_OCIdleState = TIM_OCIdleState_Reset;

TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCStruct.TIM_Pulse = 1999;
TIM_OC1Init(TIM1, &TIM_OCStruct);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

Is there something different I have to do about advanced timers to make them work with pwm? I also achieved success with TIM3 and TIM12 (which are general purpose timers), but not with TIM8 (which is also an advanced timer).

\$\endgroup\$
0

2 Answers 2

4
\$\begingroup\$

With help from people on STM32 forum, I found out I was missing the following additional code to make advanced timer work the same way as general-purpose timer:

TIM_BDTRInitTypeDef TIM_BDTRInitStruct;
TIM_BDTRStructInit(&TIM_BDTRInitStruct);
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStruct);
TIM_CCPreloadControl(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);

Note: Channels must be initialized before calling the code for advanced features. If you try to initialize channels after that there might be problems (my LED connected to channel 3, which was initialized after advanced features, was always ON and did not respond to pwm changes, oddly channel 4 was working but was also initialized after advanced features).

\$\endgroup\$
0
0
\$\begingroup\$

This is an old question but I have a general comment about your code as it might cause bugs (I came across this bug just today, preventing me to use the PWM at all). I am posting it as an answer because I can't use comments yet with my new account.

When using init structs, it is best practise to call their corresponding struct init functions before doing anything else, e.g. here TIM_TimeBaseStructInit() for TIM_TimeBaseInitTypeDef, GPIO_StructInit() for GPIO_InitTypeDef and TIM_OCStructInit() for TIM_OCInitTypeDef.

An uninitialised structure member can trigger unexpected behaviour. In your code, you didn't initialise all members of TIM_OCStruct, which means TIM_OC1Init() will use dirty values to init the timer registers. You should either call TIM_OCStructInit() or set all members individually.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.