STM32 TIM1高级定时器RCR重复计数器的理解
TIMx_RCR
重复计数器寄存器,重复计数器只支持高级定时器TIM1
和TIM8
,下面看标准外设库的TIM
结构体的封装;
typedef struct{uint16_t TIM_Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock.This parameter can be a number between 0x0000 and 0xFFFF */uint16_t TIM_CounterMode; /*!< Specifies the counter mode.This parameter can be a value of @ref TIM_Counter_Mode */uint16_t TIM_Period; /*!< Specifies the period value to be loaded into the activeAuto-Reload Register at the next update event.This parameter must be a number between 0x0000 and 0xFFFF. */ uint16_t TIM_ClockDivision;/*!< Specifies the clock division.This parameter can be a value of @ref TIM_Clock_Division_CKD */uint8_t TIM_RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounterreaches zero, an update event is generated and counting restartsfrom the RCR value (N).This means in PWM mode that (N+1) corresponds to:- the number of PWM periods in edge-aligned mode- the number of half PWM period in center-aligned modeThis parameter must be a number between 0x00 and 0xFF. @note This parameter is valid only for TIM1 and TIM8. */} TIM_TimeBaseInitTypeDef;
可以看到uint8_t TIM_RepetitionCounter
将暂存RCR寄存器的值,从后面注释可以得知;
RCR寄存器中的值会递减到0,在允许更新事件UEV
发生的情况下,则TIM
的更新事件UEV
就会产生;
如果设置RCR
的值为N
,那么PWM
模式下,更新事件将会在弟N+1
个周期发生;
下面根据PWM
模式加以区分;
边沿模式edge-aligned mode
,延迟PWM
周期数量和N相同;中央对齐模式center-aligned mode
,延迟PWM
周期数量等于N2\cfrac{N}{2}2N;
更新事件
UEV
会在当计数器达到溢出条件(向下计数时的下溢条件)并当TIMx_CR1寄存器中的UDIS位等于0时产生
下面看STM32参考手册中的一张图;
从图中不难发现;
中央对齐模式下:
RCR = 0,更新事件没有延迟;RCR = 1,更新事件延后了半个PWM周期;RCR = 2, 更新事件延后了一个PWM周期;RCR = 3,更新事件延后了32\cfrac{3}{2}23个PWM周期;
因此,中央对齐模式center-aligned mode
,更新事件延迟的PWM
周期数量等于 RCR2\cfrac{RCR}{2}2RCR;
RCR 寄存器的范围是 0~0xFF;
边沿对齐模式下:
RCR = 0,更新事件没有延迟;RCR = 1,更新事件延后了一个PWM周期;RCR = 2, 更新事件延后了两个PWM周期;RCR = 3,更新事件延后了三个PWM周期;
因此,边沿对齐模式延迟的PWM
周期数量等于RCRRCRRCR;
这么一来,TIM中的UEV的使用就变得非常灵活。
实际的应用中,对于STM32芯片的ADC的转换启动,一般分为软件启动或外部触发事件启动。其中外部触发事件启动,可以是定时器触发事件或EXTI引脚信号。在很多应用场合,比如电机、电源、变频器等应用中,ADC的采样点可能会有很严格的时间要求,如果采样点选择错误,可能会给整个控制系统造成严重不良后果。这里针对STM32的定时器周期性地触发ADC采样的实现方式做个简要介绍。
这里以STM32F1的TIMER1 触发ADC注入通道的转换为例【当然,规则通道也可以使用定时器触发】。我们可以利用定时器更新事件或比较输出信号作为ADC的触发使能信号。根据STM32F1参考手册查表得知,可以使用TIM1的TRGO事件或通道CH4的捕捉事件来触发注入通道的ADC转换。
1、使用TIM1 TRGO来触发ADC
// 选择Tim1更新事件作为TRGOTIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);//设定T1_TRGO作为ADC触发源ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_T1_TRGO;
特别提醒:经常有人忘记配置上面红色语句,那就相当于使用了默认的TRGO信号。但对于一个定时器来讲,可以作为TRGO的信号很多,有时默认的并非你要的信号。
2、利用TIM1 CH4的比较事件来触发ADC
这里就是选择OC4REF信号作为TRGO输出来触发ADC.
// 选择OC4REF作为TRGO;TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC4Ref);//设定T1_TRGO作为ADC触发源ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_T1_TRGO;
相比上面第一种方法,ADC采样时间点更为灵活可调,不仅仅局限于定时器的更新事件。
图一:间隔触发ADC采样点
有时候,我们可能需要多个周期才需进行一次AD触发采样及相关计算。如果时间是基于更新时刻又是定时周期的倍数,较为方便的办法就是使用定时器里的重复计数器,使用更新事件作为TRGO。软件设置就是在上面第一种方法的基础上增加一句对重复计数器TIMx_RCR的设置。图一的蓝色箭头即为此种情况的触发点设定。基本配置如下:
//配置重复计数器为2次TIM_TimeBaseStructure.TIM_RepetitionCounter = 1;// 选择Tim1更新事件作为TRGOTIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);//设定T1_TRGO作为ADC触发源ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_T1_TRGO;
如果要实现跨周期非更新时间点采样和计算,即上图中绿色箭头所指的情形。我们可以考虑使用多次采样配合中断进行计数的方式或者引入其它定时器进行分频后来灵活处理。