在STM32的定时器中,TIMx_PSC、 TIM_ARR两个寄存器加上捕捉比较模块中TIMX_CCR寄存器,它们都可以动态修改。不过他们的修改和生效可能不在同一个时刻,或者说,修改过后立即生效的话可能会带来潜在问题,这里便引入了预装寄存器及影子寄存器的概念。要记住一点,真正在TIMER模块中起作用的是影子寄存器。(中文手册P393)
实际上,STM32定时器中,CNT与ARR或CCR的比较,都是比较是否相等,而不是大小!!比如此时CNT已经到了5,ARR 本来是9,现在突然变成4了,就没有相等了,CNT会数到最大值,2^32 或 2^16次方,再从零开始。
默认情况下,影子寄存器用户没有办法直接读取或修改,用户只能操作预装寄存器。以ARR为例,用户需要操作ARR寄存器时,其实操作的都是ARR的预装载寄存器,然后由预装载寄存器把值更新给影子寄存器。
更新的时机是可以操作的。默认情况下,当操作ARR的预装载寄存器时,立即把操作更新给影子寄存器。这种情况下,可以认为没有预装载寄存器没有缓冲功能。
另一种情况是,在发生特定事件(UEV)的时候,把操作更新给影子寄存器。实际发挥作用的影子寄存器的值没有立即更新,即ARR的预装载寄存器有缓冲功能。什么时候会发生事件呢?通常在CNT等于ARR或CCR的时候,即中断溢出或输出状态翻转时。
ARR的预装载寄存器可以由TIMX_CR1寄存器的ARPE位使能。
我在HAL库里没有找到操作CR1,或者ARPE的函数。只好操作寄存器,修改代码如下:
//main.c
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 2 */
htim2.Instance->CR1 |= TIM_CR1_ARPE;//使能ARR寄存器的缓冲
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
/* USER CODE END TIM2_Init 2 */
}
理论上来讲,CCR是不是也要使能缓冲功能?不需要。HAL库中CCR的初始化里,已经使能了预装载寄存器。HAL_TIM_PWM_ConfigChannel>>htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE;