STM32 定时器自动重载预加载

如何解决STM32 定时器自动重载预加载

重现条件:

这是我想解决的现实生活示例:我正在 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));
  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 of the reference manual 以及包含原理图,但我仍然无法理解为什么此设置会导致计时器冻结。

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

解决方法

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

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

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

  • 缓冲的 ARR (ARR):

ARR buffered (LL_TIM_EnableARRPreload)

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

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

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

  • ARR
  • LL_TIM_OC_DisableFast(TIM2,LL_TIM_CHANNEL_CH3);
  • LL_TIM_DisableMasterSlaveMode(TIM2);

除了您的问题之外,还有更多的用例;根据您希望 PWM 信号同步的紧密程度,您可能需要考虑一个定时器作为主设备 (LL_TIM_SetTriggerOutput(TIM2,LL_TIM_TRGO_RESET);) 和另一个作为从设备 (TIMxCR2.MMS=001) 的基本配置,其中启用主定时器时启用从定时器。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?