天天看點

STM32學習筆記(五)——通用定時器計數延時

STM32定時器概述

STM32F40x系列總共最多有14個定時器,定時器分為三類:基本定時器、通用定時器和進階定時器。它們的都是通過計數來達到定時的目的,和51的定時器差不多,基本原理都是一樣的,就是功能多了一些,這些計數器都是自動重新裝載初值的,使用起來非常友善,而且計數時鐘頻率可以通過分頻系數來設定。本文章将介紹使用定時器中斷來控制LED間隔1s閃爍。

STM32學習筆記(五)——通用定時器計數延時

計數的時鐘來源主要有四個:

  • 内部時鐘CK_INT
  • 外部時鐘模式1:外部輸入腳TIx
  • 外部時鐘模式2:外部觸發輸入ETR,僅适用于 TIM2、 TIM3、 TIM4
  • 内部觸發輸入ITRx:使用 A 定時器作為 B 定時器的預分頻器(A為B提供時鐘)

我們使用定時器内部時鐘,即CK_INT作為計數器的時鐘源 = 168MHz / 2 = 84MHz

時鐘框圖如下:

STM32學習筆記(五)——通用定時器計數延時

定時器的配置

1.使能定時器時鐘

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);    //定時器3時鐘使能      

2.初始化定時器參數,設定分頻系數和計數初值,計數模式設定等。如果要定時1s定時器溢出,那麼可以設定分頻系數為8400 ,則分頻後的時鐘頻率為 : 84MHz / 8400 = 10KHz  = 0。1ms  ,計數初值設定為1s / 0。1 ms = 10000即可。

/*初始化定時器參數,設定自動重裝值,分頻系數,計數方式*/
    TIM_Init。TIM_ClockDivision=    TIM_CKD_DIV1;            //時鐘分頻因子
    TIM_Init。TIM_CounterMode=TIM_CounterMode_Up;                //定時器模式
    TIM_Init。TIM_Period=Period;                            //自動重裝值,0-65535
    TIM_Init。TIM_Prescaler=  Prescaler;
//    TIM_Init。TIM_Prescaler=    8400;                    //分頻系數-0。1ms
//    TIM_Init。TIM_Prescaler=    42000;                    //分頻系數-0。5ms
//    TIM_Init。TIM_RepetitionCounter=    
    TIM_TimeBaseInit(TIM3,&TIM_Init);
          

TIM_RepetitionCounter是使用進階定時器要進行設定的。我們使用的是定時器3,屬于通用定時器,計數模式設定為向上計數,則計數器從0 開始計數,當計數到設定的初值時,然後計數器重新從0開始計數,并将溢出标志位置1,如果設定了溢出中斷,則會産生計數器溢出中斷。

3.定時器3中斷設定,注意優先級的設定,如果程式中開啟了多個中斷。就要考慮中斷優先級的設定,本程式隻使用了一個定時器中斷,則配置為任何優先級都是可以的。

/*定時器3中斷優先級設定*/
    NC_Init。NVIC_IRQChannel=TIM3_IRQn;                    //中斷通道指定定時器3
    NC_Init。NVIC_IRQChannelCmd= ENABLE;    
    NC_Init。NVIC_IRQChannelPreemptionPriority=0;        //設定搶占優先級
    NC_Init。NVIC_IRQChannelSubPriority=0;                //設定響應優先級
    NVIC_Init(&NC_Init);      

4.使能定時器,當執行完這一句後,定時器就開始從 0 開始計數了。我們可以通過使能定時器來暫停計數器,或者使能定時器來啟動定時器,在開發時鐘時可以使用這個。

相當于51中的TR1 = 1 / TR1 = 0

TIM_Cmd(TIM3,ENABLE);      

5.中斷服務函數,本程式是讓LED1間隔1s閃爍,那麼中斷服務函數的功能就是讓LED1的狀态反轉。

void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update))    //如果産生溢出中斷
    {
        LED1=!LED1;                    //那麼狀态反轉
//        LED0=!LED0;
    }
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);        //清楚更新中斷标志位
}      

這裡檢測的是定時器溢出中斷,即計時1s時間到,則将LED1的狀态反轉,然後将溢出标志位清零。

主函數

int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    delay_init(168);
    LED_Init();                        //LED初始化熄滅
    Timer3_Config(2000,42000);        //0.5ms*2000 = 1s
    while(1)
    {
        LED0=!LED0;
        delay_ms(1000);            
    }
}      

這裡使用延時函數來延時1s控制LED0閃爍,實際運作效果可以看出兩個LED的閃爍在一定的時間内是同步的,但是時間一長還是有點誤差。

總結

當學完這一節定時器的時候,我就有一個想法了,那就是寫一個LCD電子時鐘的程式,通過定時器來達到準确延時的目的,當然還要學習一下LCD1602的驅動方法,哈哈,想想就很有成就感。

參考資料:

STM32F4_TIM基本延時(計數原理) STM32-通用定時器基本定時功能

STM32F4xx中文參考手冊

以上是我學習過程的一些個人了解,有不對或不準确的地方,歡迎各位大神指正。

2017年4月21日21:33:44

繼續閱讀