STM32定时器自动重载预载

STM32 Timer auto-reload preload

重现条件:

这是我想要的真实生活示例 solve:I 我正在 stm32f411RET 上开发一个应用程序,它需要动态更改两个 PWM 的周期s.The 两个 PWM 需要同步并且具有完全相同的频率,但是由于某些引脚限制,我使用了两个不同的 timers.In 我的主循环我计算了我想要的周期,然后调用:

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

一切正常,但我不清楚的是两个定时器的初始化设置的组合:

  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);

这对于计时器 2 来说是非常标准的,几乎相同的代码适用于计时器 3,唯一的例外是 LL_TIM_EnableARRPreload(TIM2); 更改为 LL_TIM_DisableARRPreload(TIM3);

TLDR 实际问题

当我更改这两个初始化函数中的任何一个时,定时器开始工作,但改变频率会使定时器完全die.I从第 316 of the reference manual 页和第 320 页了解此函数的作用和 321 包含原理图,但我仍然无法理解为什么此设置会导致计时器冻结。

P.S。 它可能有用也可能没用所以我将它留在这里定时器 2 的 ARR 寄存器长 32 位而定时器 3 的 ARR 是 16,这从我发布的配置中并不明显但我怀疑这会影响结果.

首先,相同的初始化例程应该适用于用于生成所需 PWM 信号的两个定时器,除非您使用一个定时器的配置与另一个不同。

值得注意的是 TIM_InitStruct.Autoreload 在初始化期间设置为 0,定时器在计数器 mode/pwm 模式下的行为 ARR 设置为0 未在参考手册中记录。明智的做法是根据计时器将 TIM_InitStruct.Autoreload 设置为 UINT32_MAXUINT16_MAX

此外,查看问题中显示的初始化例程(对于计时器 2 通道 3),调用 LL_TIM_EnableARRPreload 可以对 ARR 值进行缓冲更改。当缓冲 ARR 更改时,ARR 值仅在更新事件 (UEV) 上更新。当禁用缓冲更新时,LL_TIM_DisableARRPreloadARR 值立即更新为新值。参考手册中的下图显示了有无缓冲的行为。

  • ARR 缓冲(LL_TIM_EnableARRPreload):

  • ARR 无缓冲 (LL_TIM_DisableARRPreload):

在循环中动态更新ARR值(PWM周期)和比较计数器值(PWM占空比,CCRn),通常是同时更新 buffered/preloaded 是个好主意。 CCRn 缓冲是通过 LL_TIM_OC_EnablePreload 启用的,如您的初始化例程所示。缓冲 ARR 变化,将保持 ARR 更新之间 PWM 周期的完整性,避免任何无意中的长脉冲;特别是,如果系统发现自己处于 ARR new < TIMx CNT < ARR old 的情况。请注意,如果您希望保持 PWM 信号同步,重要的是对两个定时器使用相同的 ARR 预加载配置。

请注意,如果之前未出于其他目的初始化计时器,则以下调用是多余的。

  • LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH3);
  • LL_TIM_DisableMasterSlaveMode(TIM2);
  • LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);

超出您的问题,更多关于用例;根据您希望 PWM 信号同步的程度,您可能需要考虑一个定时器作为主机(TIMxCR2.MMS=001)和另一个作为从机(TIMxSMCR.SMS=100)的基本配置,其中当启用主机时启用从定时器。