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_MAX
或 UINT16_MAX
。
此外,查看问题中显示的初始化例程(对于计时器 2 通道 3),调用 LL_TIM_EnableARRPreload
可以对 ARR
值进行缓冲更改。当缓冲 ARR
更改时,ARR
值仅在更新事件 (UEV
) 上更新。当禁用缓冲更新时,LL_TIM_DisableARRPreload
,ARR
值立即更新为新值。参考手册中的下图显示了有无缓冲的行为。
- 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
)的基本配置,其中当启用主机时启用从定时器。
重现条件:
这是我想要的真实生活示例 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_MAX
或 UINT16_MAX
。
此外,查看问题中显示的初始化例程(对于计时器 2 通道 3),调用 LL_TIM_EnableARRPreload
可以对 ARR
值进行缓冲更改。当缓冲 ARR
更改时,ARR
值仅在更新事件 (UEV
) 上更新。当禁用缓冲更新时,LL_TIM_DisableARRPreload
,ARR
值立即更新为新值。参考手册中的下图显示了有无缓冲的行为。
- 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
)的基本配置,其中当启用主机时启用从定时器。