cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 Timer auto-reload preload

SMour.1
Associate III

The conditions to reproduce:

Here is my real life example that I would like to solve:I am developing an application on an stm32f411RET which needs to dynamically change the period of two PWM's.The two PWM's need to be synced and have exactly the same frequency but because of some pin restrictions I am using two different timers.In my main loop I calculate the period I want and I call:

TIM3->ARR = (uint16_t)period;
LL_TIM_OC_SetCompareCH4(TIM3, period/2);
TIM2->ARR=(uint16_t)period;
LL_TIM_OC_SetCompareCH3(TIM2, period/2);

Everything works great but what is obscure to me is the combination of initialization settings of the two timers :

 LL_TIM_InitTypeDef TIM_InitStruct = {0};
 LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
 LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
 NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
 NVIC_EnableIRQ(TIM2_IRQn);
 TIM_InitStruct.Prescaler = 0;
 TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
 TIM_InitStruct.Autoreload = 0;
 TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
 LL_TIM_EnableARRPreload(TIM2);
 LL_TIM_Init(TIM2, &TIM_InitStruct);
 LL_TIM_OC_EnablePreload(TIM2, LL_TIM_CHANNEL_CH3);
 TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
 TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
 TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE;
 TIM_OC_InitStruct.CompareValue = 0;
 TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
 LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct);
 LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH3);
 LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
 LL_TIM_DisableMasterSlaveMode(TIM2);
 LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOB);
 GPIO_InitStruct.Pin = BBD_R_Pin;
 GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
 GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
 GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
 GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
 LL_GPIO_Init(BBD_R_GPIO_Port, &GPIO_InitStruct);

This is quite standard for the timer 2 and nearly the same code works for timer 3 with the only exception that LL_TIM_EnableARRPreload(TIM2); changes to LL_TIM_DisableARRPreload(TIM3);.

TLDR The actual question

When I change any of those two initialization functions the timer starts working but changing the frequency real-time make the timer completely die.I have a grasp about what this function does from page 316 of the reference manual https://www.st.com/resource/en/reference_manual/dm00119316-stm32f411xc-e-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf and also pages 320 and 321 that contain schematics but still I can't comprehend why this setting can cause the timers to freeze.

P.S.

It might be useful or it might not so I'll leave it here the ARR register of timer 2 is 32 bit long and the ARR of timer 3 is 16 ,that is not obvious from the configurations I posted but I doubt this affects the outcome.

 [1]: https://www.st.com/resource/en/reference_manual/dm00119316-stm32f411xc-e-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

7 REPLIES 7

Hello

>> TIM_InitStruct.Autoreload = 0;

this will not produce a valid PWM pulse if TIM_OC_InitStruct.CompareValue >0

PWM Frequency is Ftim /( (Presc+1)* (ARR+1) ) Ftim is the input freq of the timer

PWM duty cycle is (CompValue+1)/(ARR+1)

>>but changing the frequency real-time make the timer completely die.

If increase the freq and keep the CompareValue to 0 then the duty cycle will be 0

This App Note will help yto clear everything about standard timers

I don't understand what the question is, but whenever you don't know what happened, read out and check/post the timer registers content.

JW

SMour.1
Associate III

@Vangelis Fortounas​  Thank you for the answer though I am quite aware about the first part (initialy the timer is "disabled") and then at these four lines that I posted I am changing the Autoreload register and the compare value of PWM to half of the Autoreload (with 0 prescaler this keeps the duty cycle at 50% ) and it works .

@Community member​  My question relates with the second part about two apparently same timers ,functioning differently with the same setting LL_TIM_DisableARRPreload(TIM3); and also about the importance of that setting as it seems(at least for my application) quite insignificant.

I still don't understand what do you want to achieve, what do you do to achieve that and how are the symptoms different from it, but in any case, reading out and checking the timers registers helps revealing what is going on.

JW

SMour.1
Associate III

I don't want to achieve anything the code currently works. I just want to learn why it works , I find it very odd for the code to works as in it's current state I am initializing two same timers with different settings in order to work.

I repeat : Changing this :

 LL_TIM_EnableARRPreload(TIM2);

To this :

 LL_TIM_DisableARRPreload(TIM2);

make the timer 2 completely freeze and also changing :

 LL_TIM_DisableARRPreload(TIM3);

to :

 LL_TIM_EnableARRPreload(TIM3);

makes timer 3 completely freeze.I just ask why?

Hard to tell without knowing the rest of the settings.

I don't use Cube/LL so don't understand what those command do, and they also can be faulty or be used in an unanticipated way. The timer works out of its registers.

JW

Piranha
Chief II

Drivers can also be broken - check the actual register values. But most likely there is something wrong with the timer management code. Maybe some broken math related to the fact that TIM2 is 32-bit and TIM3 is 16-bit.