[英]STM32 Timer auto-reload preload
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:这是我想解决的现实生活示例:我正在 stm32f411RET 上开发一个应用程序,该应用程序需要动态更改两个 PWM 的周期。两个 PWM 需要同步并且具有完全相同的频率,但是由于某些引脚限制我正在使用两个不同的计时器。在我的主循环中,我计算了我想要的时间段并调用:
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); //Important Line!!
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);
这对于计时器 2 来说是相当标准的,几乎相同的代码适用于计时器 3,唯一的例外是
LL_TIM_EnableARRPreload(TIM2);
changes to LL_TIM_DisableARRPreload(TIM3);
更改为
LL_TIM_DisableARRPreload(TIM3);
. .
When I change any of those two initialization functions the timer starts working but changing the frequency make the timer completely die.I have a grasp about what this function does from page 316 of the reference manual and also pages 320 and 321 that contain schematics but still I can't comprehend why this setting can cause the timers to freeze.当我更改这两个初始化函数中的任何一个时,计时器开始工作,但更改频率会使计时器完全失效。我从参考手册的第 316页以及第 320 页和第 321 页中了解了 function 的功能,但仍然我无法理解为什么此设置会导致计时器冻结。
PS 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. PS它可能有用,也可能没有,所以我将它留在这里定时器2的ARR寄存器是32位长,定时器3的ARR是16,这从我发布的配置中并不明显,但我怀疑这会影响结果。
For a start the same initialisation routine should work for both the timers used to generate the PWM signals you want, unless you using one timer in a different configuration to the other.首先,相同的初始化例程应该适用于用于生成所需 PWM 信号的两个定时器,除非您使用一个配置不同的定时器。
On thing that stands out is that the TIM_InitStruct.Autoreload
is set to 0
during initialisation, the behaviour of the timer in counter mode/pwm mode with ARR
set to 0
is undocumented in the reference manual.突出的是
TIM_InitStruct.Autoreload
在初始化期间设置为0
,在参考手册中未记录计时器在ARR
设置为0
的计数器模式/pwm 模式下的行为。 It would be wise to set the TIM_InitStruct.Autoreload
to the UINT32_MAX
or UINT16_MAX
depending on the timer.明智的做法是根据计时器将
TIM_InitStruct.Autoreload
设置为UINT32_MAX
或UINT16_MAX
。
Further, looking at the initialisation routine shown in your question (For timer 2 channel 3), the call LL_TIM_EnableARRPreload
enables a change to the ARR
value to be buffered.此外,查看您的问题中显示的初始化例程(对于计时器 2 通道 3),调用
LL_TIM_EnableARRPreload
可以缓冲对ARR
值的更改。 When the ARR
changes are buffered the ARR
value is only updated on an update event ( UEV
).当
ARR
更改被缓冲时, ARR
值仅在更新事件 ( UEV
) 时更新。 When buffered updates are disabled, LL_TIM_DisableARRPreload
, the ARR
value is updated with a new value immediately.当缓冲更新被禁用
LL_TIM_DisableARRPreload
时, ARR
值会立即用新值更新。 The behaviour with and without buffering are shown by the following figures in the reference manual.参考手册中的下图显示了带和不带缓冲的行为。
LL_TIM_EnableARRPreload
): LL_TIM_EnableARRPreload
): Where you are dynamically updating the ARR
value (PWM period) and the compare counter value (PWM duty-cycle, CCRn
) in a loop, it is generally a good idea to have both updates buffered/preloaded .在循环中动态更新
ARR
值(PWM 周期)和比较计数器值(PWM 占空比, CCRn
)的情况下,最好将两个更新都缓冲/预加载。 The CCRn
buffering is enabled with LL_TIM_OC_EnablePreload
, as shown in your initialisation routine. CCRn
缓冲通过LL_TIM_OC_EnablePreload
启用,如您的初始化例程中所示。 Buffering the ARR
changes, will maintain the integrity of PWM period between ARR
updates avoiding any inadvertently long pulses;缓冲
ARR
变化,将保持ARR
更新之间 PWM 周期的完整性,避免任何无意的长脉冲; particularly, should the system find itself in the condition where ARR
new < TIMx CNT
< ARR
old.特别是,如果系统发现自己处于
ARR
new < TIMx CNT
< ARR
old 的情况。 Note, if you wish to keep the PWM signals in sync, it is important the same ARR
preloading configuration is used for both timers.请注意,如果您希望保持 PWM 信号同步,重要的是要为两个定时器使用相同的
ARR
预加载配置。
Note, the following calls are superfluous if the timer hadn't been previously initialised for a different purpose.请注意,如果之前没有为其他目的初始化计时器,则以下调用是多余的。
LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH3);
LL_TIM_DisableMasterSlaveMode(TIM2);
LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
Beyond your question and more to the use-case;除了您的问题之外,还有更多的用例; depending on how closely you want the PWM signals to be synchronised, you may want to consider the basic configuration of one timer operating as the master (
TIMxCR2.MMS=001
)and the other as the slave ( TIMxSMCR.SMS=100
) where the slave timer is enabled when the master is enabled.根据您希望 PWM 信号同步的紧密程度,您可能需要考虑一个定时器作为主机(
TIMxCR2.MMS=001
)和另一个作为从机( TIMxSMCR.SMS=100
)的基本配置,其中从定时器在主控启用时启用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.