通用定時器基礎知識
參考資料:STM32F1xx官方資料:《STM32中文參考手冊V10》-第14章通用定時器
通用定時器工作過程:
時鐘選擇
計數器時鐘可以由下列時鐘源提供:
① 內部時鐘(CK_INT)
② 外部時鐘模式1:外部輸入腳(TIx)
③ 外部時鐘模式2:外部觸發輸入(ETR)
④ 內部觸發輸入(ITRx):使用一個定時器作為另一個定時器的預分頻器,如可以配置一個定時器Timer1而作為另一個定時器Timer2的預分頻器。
內部時鐘選擇:
時鐘計算方法:
默認調用SystemInit函數情況下:
SYSCLK=72M
AHB時鐘=72M
APB1時鐘=36M
所以APB1的分頻系數=AHB/APB1時鐘=2
所以,通用定時器時鐘CK_INT=2*36M=72M
計數器模式
通用定時器可以向上計數、向下計數、向上向下雙向計數模式。
① 向上計數模式:計數器從0計數到自動加載值(TIMx_ARR),然后重新從0開始計數并且產生一個計數器溢出事件。
② 向下計數模式:計數器從自動裝入的值(TIMx_ARR)開始向下計數到0,然后從自動裝入的值重新開始,并產生一個計數器向下溢出事件。
③ 中央對齊模式(向上/向下計數):計數器從0開始計數到自動裝入的值-1,產生一個計數器溢出事件,然后向下計數到1并且產生一個計數器溢出事件;然后再從0開始重新計數。
向上計數模式(時鐘分頻因子=1)
向下計數模式(時鐘分頻因子=1)
中央對齊計數模式(時鐘分頻因子=1 ARR=6)
定時器中斷實驗相關寄存器(常用寄存器和庫函數配置)
常見中斷類型(圖參考):
TIM_IT_Update:更新中斷,計數器向上溢出/向下溢出,計數器初始化(通過軟件或者內部/外部觸發) TIM_IT_CC1~4:都是捕獲/比較中斷,貌似都是平等的,即輸入捕獲,輸出比較TIM_IT_Trigger:觸發事件(計數器啟動、停止、初始化或者由內部/外部觸發計數)使用的時候都是調用函數TIM_ITConfig()來使能指定的中斷類型,調用TIM_GetITStatus()函數來查看是否有中斷發生,入口參數都是平等的。可能就是不同的事件導致中斷的發生略有不同
中斷類型 | 宏 | 說明 |
---|---|---|
更新中斷 | TIM_IT_Update | 計數器溢出 |
比較中斷 | TIM_IT_CCx | CNT = CCRx |
觸發中斷 | TIM_IT_Trigger | 外部/同步/軟件觸發 |
定時器中斷原理
通用定時器通過以下機制產生中斷:
計數器計滿(向上數到 ARR,或向下數到 0)
觸發“更新事件(UEV)”
觸發 UIF 標志位(TIMx_SR 寄存器)
如果 UIE 允許(TIMx_DIER),則進入中斷服務函數(TIMx_IRQHandler)
通用定時器常用寄存器和庫函數
通用定時器常用寄存器
寄存器名 | 位名 | 功能說明 |
---|---|---|
TIMx_PSC | PSC[15:0] | 預分頻器值,CNT時鐘 = TIMxCLK / (PSC+1) |
TIMx_ARR | ARR[15:0] | 自動重裝載寄存器,決定計數上限 |
TIMx_CNT | CNT[15:0] | 當前計數器數值 |
TIMx_CR1 | CEN | 使能計數器(1為啟動) |
DIR | 計數方向:0為向上,1為向下 | |
CMS[1:0] | 中心對齊模式 | |
ARPE | 自動重裝載緩沖使能 | |
TIMx_DIER | UIE | 允許更新中斷 |
CCxIE | 允許比較中斷(CC1~CC4) | |
TIMx_SR | UIF | 更新中斷標志位(需手動清除) |
CCxIF | 捕獲/比較中斷標志位 | |
TIMx_EGR | UG | 軟件強制生成更新事件(UEV) |
計數器當前值寄存器CNT:
預分頻寄存器TIMx_PSC:
自動重裝載寄存器(TIMx_ARR):
控制寄存器1(TIMx_CR1):
DMA中斷使能寄存器(TIMx_DIER):
補充說明:
- ARR緩沖控制:ARPE 位決定 ARR 是否緩沖(CR1 寄存器)
- 中斷標志手動清除:UIF 必須手動清除,否則中斷會持續進入
- 定時器時鐘來源:
- APB1 × 2(如果 APB1分頻 ≠ 1)
- TIMxCLK = 72MHz(如 STM32F103)
常用庫函數:
定時器參數初始化:
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
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_TimeBaseStructure.TIM_Period = 4999;
TIM_TimeBaseStructure.TIM_Prescaler =7199;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
定時器使能函數:
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
定時器中斷使能函數:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
狀態標志位獲取和清除:
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus<