STM32時鍾和定時器


時鍾源

STM32包含了5個時鍾源,分別為HSI、HSE、LSI、LSE、PLL。

  • HSI是高速內部時鍾、RC振盪器,頻率為8MHz;
  • HSE是高速外部時鍾,即晶振,可接石英/陶瓷諧振器或接外部時鍾源,頻率范圍為4MHz~16MHz;
  • LSI為低速內部時鍾、RC振盪器,頻率40kHz;
  • LSE為低速外部時鍾,接32.768kHz晶振,作為RTC時鍾源;
  • PLL為鎖相環倍頻輸出,其時鍾輸入源可選擇為HSI/2、HSE或者HSE/2。倍頻可選擇為2~16倍,但是其輸出頻率最大不得超過72MHz;

定時器TIM2~TIM7掛載在APB1分頻器上,TIM1和TIM8掛載在APB2分頻器上;APB1上面掛載的是低速外設,APB2上掛載高速外設。APB2可以工作在72MHz下,而APB1最大是36MHz

定時器的產生路線:系統時鍾 -> AHB預分頻 -> APB2預分頻 -> TIM1倍頻器 -> 產生TIM1的時鍾系統

在system_stm32f10x.c文件下,有默認定義SYSCLK_FREQ_72MHz,同時在SystemInit()函數下調用了SetSysClock(),根據宏定義將時鍾設為72MHz。讀取SystemCoreClock變量即可獲得系統時鍾頻率

在默認情況下,系統的各個時鍾頻率如下:

  • SYSCLK:72M
  • AHB:72M
  • APB1(PCLK1):36M
  • APB2(PCLK2):72M
  • PLL:72M

 計時器的類型

  • TIM1和TIM8是高級定時器
  • TIM2-TIM5是通用定時器
  • TIM6和TIM7是基本的定時器

這8個定時器都是16位的,它們的計數器的類型除了基本定時器TIM6和TIM7其他都支持向上、向下、向上/向下這3種計數模式。

計數器的三種計數模式

  • 向上計數模式:從0開始,計到arr預設值,產生溢出事件,返回重新計時
  • 向下計數模式:從arr預設值開始,計到0,產生溢出事件,返回重新計時
  • 中央對齊模式:從0開始向上計數,計到arr產生溢出事件,然后向下計數,計數到1以后,又產生溢出,然后再從0開始向上計數。(此種技術方法也可叫向上/向下計數)

各定時器的主要功能

基本定時器(TIM6、TIM7)的主要功能:

只有最基本的定時功能,基本定時器TIM6和TIM7各包含一個16位自動裝載計數器,由各自的可編程預分頻器驅動。主要用於產生DAC觸發信號。

通用定時器(TIM2~TIM5)的主要功能:

除了基本的定時器的功能外,還具有測量輸入信號的脈沖長度(輸入捕獲)或者產生輸出波形(輸出比較和PWM)

高級定時器(TIM1、TIM8)的主要功能:

高級定時器不但具有基本/通用定時器的所有的功能外,還具有控制交直流電動機所有的功能,比如它可以輸出6路互補帶死區的信號,剎車功能等等。

詳細的定時器設定如下:

  1. 首先要搞清楚定時器的計數時鍾頻率,在預分頻系數≠1的時候,TIM2~7的時鍾頻率為APB1的頻率的2倍,即72MHz,預分頻系數的默認值不是1。
  2. 定時器的設置主要包括定時器的初始化和中斷的初始化。

定時器的時鍾不是直接來自APB1或APB2,而是來自輸入為APB1或APB2的一個倍頻器,當APB1的預分頻系數為1時,這個倍頻器不起作用,定時器的時鍾頻率等於APB1的頻率;當APB1的預分頻系數為其它數值(即預分頻系數為2、4、8或16)時,這個倍頻器起作用,定時器的時鍾頻率等於APB1的頻率的兩倍

假定AHB=36MHz,因為APB1允許的最大頻率為36MHz,所以APB1的預分頻系數可以取任意數值;

當預分頻系數=1時,APB1=36MHz,TIM2~7的時鍾頻率=36MHz(倍頻器不起作用);

當預分頻系數=2時,APB1=36MHz/2=18MHz,在倍頻器的作用下,TIM2~7的時鍾頻率=36MHz;

當預分頻系數=4時,APB1=36MHz/4=9MHz,在倍頻器的作用下,TIM2~7的時鍾頻率=18MHz;

當預分頻系數=8時,APB1=36MHz/8=4.5MHz,在倍頻器的作用下,TIM2~7的時鍾頻率=9MHz;

當預分頻系數=16時,APB1=36MHz/16=2.25MHz,在倍頻器的作用下,TIM2~7的時鍾頻率=4.5MHz;

既然需要TIM2~7的時鍾頻率=36MHz,為什么不直接取APB1的預分頻系數=1呢?這是因為APB1不但要為TIM2~7提供時鍾,而且還要為其它外設提供時鍾,設置這個倍頻器可以在保證其它外設使用較低時鍾頻率時,TIM2~7仍能得到較高的時鍾頻率。例如當AHB=72MHz時,APB1的預分頻系數必須大於2,因為APB1的最大頻率只能為36MHz。如果APB1的預分頻系數=2,則因為這個倍頻器,TIM2~7仍然能夠得到72MHz的時鍾頻率。能夠使用更高的時鍾頻率,無疑提高了定時器的分辨率,這也正是設計這個倍頻器的初衷。

定時器初始化:

首先定義TIM_TimeBaseInitTypeDef類型的結構體,它包含了如下的內容:

typedef struct
{
  uint16_t TIM_Prescaler;
  uint16_t TIM_CounterMode;
  uint16_t TIM_Period;
  uint16_t TIM_ClockDivision;
  uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;

第一項 TIM_Prescaler 是定時器預分頻值,時鍾源經該預分頻器才是定時器時鍾,它設定TIMx_PSC 寄存器的值。可設置范圍為 0 至 65535,實現 1至 65536 分頻。

第二項 TIM_CounterMode 為定時器計數模式,它的內容如下:

#define TIM_CounterMode_Up                 ((uint16_t)0x0000)
#define TIM_CounterMode_Down               ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1     ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2     ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3     ((uint16_t)0x0060)

它可以是向上計數、向下計數以及三種中心對齊模式。基本定時器只能是向上計數,即 TIMx_CNT只能從0開始遞增,並且無需初始化。

第三項 TIM_Period 為定時器周期,當計數寄存器的值遞增到等於該值時,將相關事件標志位置位。范圍為0 至 65535。

第四項 TIM_ClockDivision 為時鍾分頻,設置定時器時鍾 CK_INT 頻率與數字濾波器采樣時鍾頻率分頻比,基本定時器沒有此功能,不用設置。

第五項 TIM_RepetitionCounter 為重復計數器,屬於高級控制寄存器專用寄存器位,利用它可以非常容易控制輸出 PWM 的個數。一般的定時器不需要設置。

循環定時時間的計算:基本定時器只有內部時鍾72MHz,定時器的實際時鍾=內部時鍾 / ( 定時器預分頻值 + 1 ),那么如果 TIM_Prescaler 設置為7200-1,則內部時鍾源經過定時器預分頻后即可得到 (72MHz / (7200-1)+1)=10kHz的頻率。然后 TIM_Period 設置為5000-1(因為計數是從0開始,所以要減1),即可得到定時時間為(5000 * (1 / 10kHz))=0.5s的定時器。

除此之外還要設置中斷的類型,一般的定時器為更新中斷,即由溢出事件產生的中斷,設置的方式為:TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE),其中第一項是定時器代號,第二項為類型,這里設定為更新方式,第三項為使能。

TIM3的初始化函數:

void TIM3_Init(u16 arr,u16 psc)
{
     // 定時時間=(arr+1)*(psc+1)/72 單位為us
    TIM_TimeBaseInitTypeDef TIM_STR;
    NVIC_InitTypeDef NVIC_STR;
    // TIM3掛載在APB1上,由於預分頻系數默認不是1,所以TIM3的時鍾為2*APB1=72M
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    //初始化定時器
    TIM_STR.TIM_Period=arr;
    TIM_STR.TIM_Prescaler=psc;
    // (arr+1)*(psc+1)/TIM時鍾=定時器溢出中斷觸發周期
    TIM_STR.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_STR.TIM_CounterMode=TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3,&TIM_STR);
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
    // 初始化中斷
    // 設定為TIM3中斷
    NVIC_STR.NVIC_IRQChannel=TIM3_IRQn;
    // 先占優先級0級
    NVIC_STR.NVIC_IRQChannelPreemptionPriority=0;
    // 從優先級3級
    NVIC_STR.NVIC_IRQChannelSubPriority=3;
    // IRQ通道時能
    NVIC_STR.NVIC_IRQChannelCmd=ENABLE;
    // 中斷初始化
    NVIC_Init(&NVIC_STR);
    // 使能定時器
    TIM_Cmd(TIM3,ENABLE);
}

中斷服務函數:

TIM3的中斷函數為 TIM3_IRQHandler

中斷服務函數內包含了:判斷是否發生中斷、中斷發生后執行的內容、清除標志位三部分。

void TIM3_IRQHandler(void)
{
    // 判斷是否發生中斷
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
    {
        // 清除標志位
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
        // 執行中斷內容
    }
}

完成調用

只要在main函數里調用 TIM3_Init() 函數,並填入適當的參數,即可實現精確的定時中斷,例如獲得1秒,即(arr+1)*(psc+1)/72000000 = 1,則可分解成arr=9999,psc=7199,配置如下:

TIM3_Init(9999,7199);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM