1. 程式人生 > >STM32 通用定時器的定時功能 學習筆記

STM32 通用定時器的定時功能 學習筆記

這節主要講下STM32 通用定時器的定時功能。

一、TIMx的時鐘源問題:

STM32有8路暫存器,包括TIM1和TIM8兩個高階定時器,TIM6和TIM7兩個基本定時器,TIM2-TIM5四個通用定時器,定時器是完全獨立的,而且沒有互相共享任何資源,它們可以一起同步操作,所有TIMx定時器在內部相連,用於定時器同步或連結。當一個定時器處於主模式時,它可以對另一個處於從模式的定時器的計數器進行復位、啟動、停止或提供時鐘等操作。其中TIM1和TIM8掛在APB2總線上,而TIM2-TIM7則掛在APB1總線上。他們所在的APB2匯流排也比APB1匯流排要好。APB2可以工作在72MHz下,而APB1最大是36MHz。

1)定時器的時鐘:
計數器時鐘可由下列時鐘源提供: 
 1:內部時鐘(CK_INT) 
 2:外部時鐘模式1:外部輸入腳(TIx) 
 3:外部時鐘模式2:外部觸發輸入(ETR) 

 4:內部觸發輸入(ITRx):使用一個定時器作為另一個定時器的預分頻器,如可以配置一個定時器Timer1而作為另一個定時器Timer2的預分頻器。

這些時鐘,具體選擇哪個可以通過TIMx_SMCR暫存器的相關位來設定。這裡的CK_INT時鐘是從APB1倍頻的來的,除非APB1的時鐘分頻數設定為1,否則通用定時器TIMx的時鐘是APB1時鐘的2倍,當APB1的時鐘不分頻的時候,通用定時器TIMx的時鐘就等於APB1的時鐘。這裡還要注意的就是高階定時器的時鐘不是來自APB1,而是來自APB2的。


2)定時器的核心:
說到定時器的核心,自然少不了兩個,一個是計數時鐘(每隔多長時間計一次),二是計多少次溢位,這兩個就共同決定了溢位時間。定時器的計數時鐘根據定時器的不同分別來自APB1或APB2,計數時鐘說白了就是要把一秒分成很多份,但由於匯流排時鐘一般在數十兆,經過分頻的APB也在數十兆,所以要把APB再分頻至更低的頻率,這就需要設定預分頻暫存器。例如當前APB1為36MHz,除非APB1的時鐘分頻數設定為1,否則通用定時器TIMx的時鐘是APB1時鐘的2倍,這時的TIMx時鐘為72MHz,因此分頻至10KHz需要設定預分頻器暫存器TIMx_PSC(如下圖)為7199,為什麼是7199而不是7200呢?
下面暫存器介紹說明了這點:計數器時鐘CK_CNT等於TIMx時鐘/(PSC+1),所以只需設定暫存器值7199就行了。
這裡10KHz的頻率相當於把一秒分為10000份,即0.0001秒,定時器每隔0.0001秒漲一次。
注:因為PSC是16位暫存器,所以值範圍為0-65535。
計數器自動重灌載暫存器TIMx_ARR,該暫存器存放的就是計數器要增加的次數(計多少次溢位)。
注:因為ARR也是16位暫存器,所以值範圍為0-65535。
這樣這兩個暫存器決定了溢位時間,接著上面的例子,如果設定ARR暫存器值為5000,那就是說定時器每隔0.0001秒漲一次,總共漲5000次,這樣就是0.5秒溢位一次。
總結下來,定時器的溢位公式為:溢位時間(秒)= ((ARR+1)*(PSC+1))/ TIMx時鐘CK_INT(MHz)


定時器的時鐘不是直接來自APB1或APB2,而是來自於輸入為APB1或APB2的一個倍頻器。
下面以定時器2~7的時鐘說明這個倍頻器的作用:當APB1的預分頻係數為1時,這個倍頻器不起作用,定時器的時鐘頻率等於APB1的頻率;
當APB1的預分頻係數為其它數值(即預分頻係數為2、4、8或16)時,這個倍頻器起作用,定時器的時鐘頻率等於APB1的頻率兩倍。


假定AHB=36MHz,因為APB1允許的最大頻率為36MHz,所以APB1的預分頻係數可以取任意數值;
當預分頻係數=1時,APB1=36MHz,TIM2~7的時鐘頻率=36MHz(倍頻器不起作用);

當預分頻係數=2時,APB1=18MHz,在倍頻器的作用下,TIM2~7的時鐘頻率=36MHz。

有人會問,既然需要TIM2~7的時鐘頻率=36MHz,為什麼不直接取APB1的預分頻係數=1?

答案是:APB1不但要為TIM2~7提供時鐘,而且還要為其它外設提供時鐘;

設定這個倍頻器可以在保證其它外設使用較低時鐘頻率時,TIM2~7仍能得到較高的時鐘頻率。
再舉個例子:當AHB=72MHz時,APB1的預分頻係數必須大於2,因為APB1的最大頻率只能為36MHz。

如果APB1的預分頻係數=2,則因為這個倍頻器,TIM2~7仍然能夠得到72MHz的時鐘頻率。能夠使用更高的時鐘頻率,無疑提高了定時器的解析度,這也正是設計這個倍頻器的初衷。

二、TIM通用定時器配置步驟:
1.配置TIM時鐘  
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);


2.定時器基本配置
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

TIM_DeInit(TIM2); //復位TIM2定時器


TIM_TimeBaseStructure.TIM_Period = 5-1;        // 2.5ms    
TIM_TimeBaseStructure.TIM_Prescaler = 36000-1;    // 分頻36000      
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  // 時鐘分頻 
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 計數方向向上計數
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);


TIM_ClearFlag(TIM2, TIM_FLAG_Update);


TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); 


TIM_Cmd(TIM2, ENABLE);      
}


TIM_Period設定了在下一個更新事件裝入活動的自動重灌載暫存器週期的值。它的取值必須在0x0000和0xFFFF之間。
TIM_Prescaler設定了用來作為TIMx時鐘頻率除數的預分頻值。它的取值必須在0x0000和0xFFFF之間。
TIM_ClockDivision的作用是做一段延時,一般在特殊場合的時候會用到,可不關心。
TIM_CounterMode選擇了計數器模式:
TIM_CounterMode_Up                       //TIM向上計數模式
TIM_CounterMode_Down                     //TIM向下計數模式
TIM_CounterMode_CenterAligned1   //TIM中央對齊模式1計數模式
TIM_CounterMode_CenterAligned2   //TIM中央對齊模式2計數模式
TIM_CounterMode_CenterAligned3   //TIM中央對齊模式3計數模式
微控制器時鐘頻率72MHz,APB1 二分頻36MHz,故TIM2自動2倍頻至72MHz,故定時器中斷頻率為72000000/36000/5=400Hz


3.使能定時器中斷TIM_Cmd(TIM2, ENABLE);


4.配置NVIC。
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4; 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

5.寫中斷函式
void TIM2_IRQHandler(void)
{
......//中斷處理
}