繁体   English   中英

STM32定时器自动重载预加载

[英]STM32 Timer auto-reload preload

繁殖条件:

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

一切都很好,但对我来说模糊的是两个计时器的初始化设置的组合:

  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 实际问题

当我更改这两个初始化函数中的任何一个时,计时器开始工作,但更改频率会使计时器完全失效。我从参考手册的第 316页以及第 320 页和第 321 页中了解了 function 的功能,但仍然我无法理解为什么此设置会导致计时器冻结。

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

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

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

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

  • ARR 缓冲( LL_TIM_EnableARRPreload ):

ARR 缓冲 (LL_TIM_EnableARRPreload)

  • ARR 未缓冲 ( LL_TIM_DisableARRPreload ): * ARR 无缓冲(LL_TIM_DisableARRPreload):

在循环中动态更新ARR值(PWM 周期)和比较计数器值(PWM 占空比, CCRn )的情况下,最好将两个更新都缓冲/预加载 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 )的基本配置,其中从定时器在主控启用时启用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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