当前位置:   article > 正文

stm32关于影子寄存器、预装载寄存器,TIM_OC1PreloadConfig和TIM_ARRPreloadConfig的作用

tim_oc1preloadconfig

 一直没搞清楚stm32定时器的TIM_OC1PreloadConfig、TIM_ARRPreloadConfig函数的作用,影子寄存器、预装载寄存器、重载寄存器的概念。今天来研究一下:

关于影子寄存器、预装载寄存器   

首先看高级定时器的框图:

图1.高级定时器框图

图1中有阴影的小方框(已用红色框标出),代表该功能对应的寄存器有影子寄存器,也就是:PSC预分频器、自动重装载寄存器、REP寄存器和4个通道的捕获/比较寄存器。

       可以看到这几个寄存器都是经常用到的,而且存在定时器工作过程中修改他们的可能性。在定时器工作过程中修改他们的值,就会出现一个问题了:如果上次ARR的值是200,通道1的比较寄存器CCR1值是100,产生占空比为50%的PWM。这个时候我要改变PWM的频率,我把ARR的值改为100,CCR1的值还没来得及更改,那么占空比肯定就会出问题,所以我就需要让他们同步修改。以前ARR=200,CCR1=100,提高频率后ARR=100,CCR1=50,我需要这两个寄存器的值同步修改,最好还是让他们计数完一个周期后再修改,那么进入下一个周期ARR、CCR1同步修改过去,对PWM的占空比就没有一点影响了。

       为了达到这个目的,就得先用一个寄存器A把修改的值保存好(ARR_A=100,CCR1_A=50),一旦上一个周期结束,给一个信号,立即就把寄存器A的值赋值过去,立即生效,这样就完成了最理想的在定时器运行中修改寄存器的过程。下面对应到stm32中:

       有影子寄存器的寄存器实际上对应了两个寄存器:一个是用户可以写入或读出数据的寄存器,称为preload register(预装载寄存器),另一个是用户看不见的、但在操作中真正起作用的寄存器称为shadow register(影子寄存器)。我们修改的定时器周期、预分频系数、通道的比较值等都是修改的表面那个预装载寄存器,要让这个修改起作用,就还要把预装载寄存器的值赋给影子寄存器才行。

       从ARR预装载寄存器传送到影子寄存器,有两种方式,一种是立刻更新,一种是等触发事件之后更新;这两种方式主要取决于寄存器TIMx->CR1中的“APRE”位:

  • APRE=0,当ARR值被修改时,同时马上更新影子寄存器的值;
  • APRE=1,当ARR值被修改时,必须在下一次事件UEV发生后才能更新影子寄存器的值;

TIM_OC1PreloadConfig和TIM_ARRPreloadConfig的作用

这就是TIM_ARRPreloadConfig(TIM1, ENABLE);函数的作用:

  1. #define  TIM_CR1_ARPE     ((uint16_t)0x0080)
  2.  
  3. void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState)
  4. {
  5.   if (NewState != DISABLE)
  6.   {
  7.     TIMx->CR1 |= TIM_CR1_ARPE;
  8.   }
  9.   else
  10.   {
  11.     TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_ARPE);
  12.   }
  13. }

       4个通道的捕获/比较寄存器也是同样的道理,从CCRx的预装载寄存器传送到影子寄存器由下面的位控制:

TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);函数的作用就是修改这个位:

  1. #define  TIM_CCMR1_OC1PE        ((uint16_t)0x0008)
  2. #define TIM_OCPreload_Enable    ((uint16_t)0x0008)
  3.  
  4. void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
  5. {
  6.   uint16_t tmpccmr1 = 0;
  7.  
  8.   tmpccmr1 = TIMx->CCMR1;
  9.   tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1PE);
  10.   tmpccmr1 |= TIM_OCPreload;
  11.   TIMx->CCMR1 = tmpccmr1;
  12. }

再给几个时序图:

图2.计数器时序图(当ARPE=0)

1、APRE=0,直接给ARR影子寄存器赋值的情况:

可以看到之前ARR=FF,给ARR赋值为36后,马上就生效了,并在等于36时发生了溢出。

图3.计数器时序图(当ARPE=1)

2、APRE=1,在下一个周期再更新值的情况:

可以看到之前ARR=F5,这个时候修改ARR的值为36,只有表面的重加载寄存器值更改了,真正起作用的影子寄存器并没有更改。等到上一个周期结束,发生更新事件,影子寄存器才更改。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/285301?site
推荐阅读
相关标签
  

闽ICP备14008679号