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 active Auto-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 downcounter reaches zero, an update event is generated and counting restarts from 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 mode This 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周期數量等於 ;
更新事件
UEV會在當計數器達到溢出條件(向下計數時的下溢條件)並當TIMx_CR1寄存器中的UDIS位等於0時產生
下面看STM32參考手冊中的一張圖;

從圖中不難發現;
中央對齊模式下:
- RCR = 0,更新事件沒有延遲;
- RCR = 1,更新事件延后了半個PWM周期;
- RCR = 2, 更新事件延后了一個PWM周期;
- RCR = 3,更新事件延后了
個PWM周期;
因此,中央對齊模式center-aligned mode,更新事件延遲的PWM周期數量等於 ;
RCR 寄存器的范圍是 0~0xFF;
邊沿對齊模式下:
- RCR = 0,更新事件沒有延遲;
- RCR = 1,更新事件延后了一個PWM周期;
- RCR = 2, 更新事件延后了兩個PWM周期;
- RCR = 3,更新事件延后了三個PWM周期;
因此,邊沿對齊模式延遲的PWM周期數量等於 ;
這么一來,TIM中的UEV的使用就變得非常靈活。
實際的應用中,對於STM32芯片的ADC的轉換啟動,一般分為軟件啟動或外部觸發事件啟動。其中外部觸發事件啟動,可以是定時器觸發事件或EXTI引腳信號。在很多應用場合,比如電機、電源、變頻器等應用中,ADC的采樣點可能會有很嚴格的時間要求,如果采樣點選擇錯誤,可能會給整個控制系統造成嚴重不良后果。這里針對STM32的定時器周期性地觸發ADC采樣的實現方式做個簡要介紹。
這里以STM32F1的TIMER1 觸發ADC注入通道的轉換為例【當然,規則通道也可以使用定時器觸發】。我們可以利用定時器更新事件或比較輸出信號作為ADC的觸發使能信號。根據STM32F1參考手冊查表得知,可以使用TIM1的TRGO事件或通道CH4的捕捉事件來觸發注入通道的ADC轉換。
1、使用TIM1 TRGO來觸發ADC
// 選擇Tim1更新事件作為TRGO
TIM_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更新事件作為TRGO
TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);
//設定T1_TRGO作為ADC觸發源
ADC_InitStructure.ADC_ExternalTrigConv =ADC_ExternalTrigConv_T1_TRGO;

如果要實現跨周期非更新時間點采樣和計算,即上圖中綠色箭頭所指的情形。我們可以考慮使用多次采樣配合中斷進行計數的方式或者引入其它定時器進行分頻后來靈活處理。
