通用定時器工作過程:
時鐘選擇:
計數器時鐘可以由下列時鐘源提供:
- 內部時鐘(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
計數器模式: 通用定時器可以向上計數、向下計數、向上向下雙向計數模式。
- 向下計數模式(時鐘分頻因子=1(意思就是:CK_PSC=CK_CNT))
-
向上計數模式(時鐘分頻因子=1)
-
中央對齊計數模式(時鐘分頻因子=1 ARR=6)
定時器中斷實驗相關寄存器: -
計數器當前值寄存器CNT
-
預分頻寄存器TIMx_PSC
- 自動重裝載寄存器(TIMx_ARR)
- 控制寄存器1(TIMx_CR1)
- DMA中斷使能寄存器(TIMx_DIER)
常用庫函數
定時器參數初始化:
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
ypedef 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(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
定時器中斷實現步驟:
- 能定時器時鐘。
RCC_APB1PeriphClockCmd();
- 初始化定時器,配置ARR,PSC。
TIM_TimeBaseInit();
- 開啟定時器中斷,配置NVIC。
void TIM_ITConfig();NVIC_Init();
- 使能定時器。
TIM_Cmd();
- 編寫中斷服務函數。
TIMx_IRQHandler();//中斷函數要判斷中斷標志位,和手動清除中斷標志位
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
Tout(溢出時間)=(ARR+1)(PSC+1)/Tclk
其中arr為你重裝的值,
psc是預分頻計時器的值(預分頻系數),
Tclk是時鐘頻率
Tclk/(psc+1)是定時器的時鐘
(psc+1))/Tclk*1是計算的計數器 減少/增加 一個數所用的時間;
那么(psc+1))/Tclk*(arr+1)就是一次定時器的時間:
然后繼續重裝arr再次計數,計時:
就構成一個循環;
- TIM2-TIM5的時鐘不是直接來自于APB1,而是來自于輸入為APB1的一個倍頻器。這個倍頻器的作用是:當APB1的預分頻系數為1時,這個倍頻器不起作用,當APB1的預分頻系數為其他數值時(即預分頻系數為2、4、8或16),這個倍頻器起作用,定時器的時鐘頻率等于APB1的頻率的2倍。
- 分頻系數就是對定時器時鐘進行多少分頻之后在使用,最好設置為定時器時鐘的倍數,方便運算;重新裝載值是計算這么多值,時間到了之后重新開始計算的值,每一次計數的時間為分頻之后時鐘的到時;
假設定時器時鐘為72M,分頻系數設置為7200-1,那現在定時器的時鐘為10kHz,每計一個數花費1/(10000)秒,重裝值設置為5000-1,那一次溢出的時間為500ms。
分頻值是是指你將系統時鐘的頻率減小,假設時鐘頻率是 72Mhz,然后分頻值是 7199,現在你的定時器值就是 10kHz,表示每計一個數,然后過了 1/(10^4)秒,然后你的重裝值就是你的時間了,如果值是 9999,就表示定時時間為 1s。
定時器配置代碼:
void TIM4_Init(u16 ar,u16 rs)
{TIM_TimeBaseInitTypeDef TIM_InitStrue;NVIC_InitTypeDef NVIC_InitStrue;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能定時器時鐘TIM_InitStrue.TIM_Period=ar;//自動裝載值TIM_InitStrue.TIM_Prescaler=rs;//預分頻系數的設置TIM_InitStrue.TIM_CounterMode=TIM_CounterMode_Up;TIM_InitStrue.TIM_ClockDivision=TIM_CKD_DIV1;//設置時鐘分割:TDTS = Tck_timTIM_TimeBaseInit(TIM4,&TIM_InitStrue);//初始化定時器,對定時器進行配置TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//開啟定時器中斷NVIC_InitStrue.NVIC_IRQChannel=TIM4_IRQn;NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStrue.NVIC_IRQChannelSubPriority=2;NVIC_Init(&NVIC_InitStrue);//初始化中斷,設置中斷的優先級TIM_Cmd(TIM4,ENABLE);//使能定時器
}void TIM4_IRQHandler(void)
{if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET){LED1=!LED1;TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清除中斷標志位}
}
實驗現象:LED0閃爍,時間間隔就是定時器的溢出時間