简体   繁体   English

STM32定时器自动重载预加载

[英]STM32 Timer auto-reload preload

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:这是我想解决的现实生活示例:我正在 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); . .

TLDR The actual question TLDR 实际问题

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_MAXUINT16_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.参考手册中的下图显示了带和不带缓冲的行为。

  • ARR buffered ( LL_TIM_EnableARRPreload ): ARR 缓冲( LL_TIM_EnableARRPreload ):

ARR 缓冲 (LL_TIM_EnableARRPreload)

  • ARR un-buffered ( LL_TIM_DisableARRPreload ): ARR 未缓冲 ( LL_TIM_DisableARRPreload ): * ARR 无缓冲(LL_TIM_DisableARRPreload):

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM