簡介
STM32中有三種定時器,包括高級定時器,通用定時器,基本定時器。以STM32F103ZET6爲例,有高級定時器(TIM1,TIM8),通用定時器(TIM2~TIM5),基本定時器(TIM6,TIM7)。(三種定時器功能區別)本篇主要講解通用定時器。
STM32F1 的通用定時器是一個通過可編程預分頻器(PSC)驅動的 16 位自動裝載計數器(CNT)構成。
工作框圖
時鐘來源:
1) 內部時鐘(CK_INT)
2) 外部時鐘模式 1:外部輸入腳(TIx)
3) 外部時鐘模式 2:外部觸發輸入(ETR)
4) 內部觸發輸入(ITRx):使用 A 定時器作爲 B 定時器的預分頻器(A 爲 B 提供時鐘)。
預分頻器:將計數器的時鐘頻率按1到65536之間的任意值分頻。它是基於一個(在TIMx_PSC寄存器中的)16位寄存器控制的16位計數器。這個控制寄存器帶有緩衝器,它能夠在工作時被改變。預分頻器參數在下一次更新事件到來時被採用。
計數器模式:
1.向上計數模式 :計數器從0計數到自動加載值(TIMx_ARR計數器的內容),然後重新從0開始計數並且產生一個計數器溢出事件;
2. 向下計數模式 :計數器從自動裝入的值(TIMx_ARR計數器的值)開始向下計數到0,然後從自動裝入的值重新開始並且產生一個計數器向下溢出事件;
3.中央對齊模式(向上/向下計數) :計數器從0開始計數到自動加載的值(TIMx_ARR寄存器)-1,產生一個計數器溢出事件,然後向下計數到1並且產生一個計數器下溢事件;然後再從0開始重新計數。
每次計數器溢出時可以產生更新事件,在TIMx_EGR寄存器中(通過軟件方式或者使用從模式控制器)設置UG位也同樣可以產生一個更新事件。
定時時間計算
以RCC的TIMxCLK作爲時鐘來源爲例子,其頻率爲72MHz,則TimeOut=(ARR+1)(PSC+1)/Tclk。即溢出時間=(自動裝載值+1)(預分頻係數+1)/頻率。此時一般使得預分頻係數爲71或7199等,便於計算。
初始化相關參數
typedef struct
{
uint16_t TIM_Prescaler;//預分頻係數
uint16_t TIM_CounterMode;//計數模式
uint16_t TIM_Period; //自動裝入值
uint16_t TIM_ClockDivision;//設置時鐘分頻因子
uint8_t TIM_RepetitionCounter; //重複計數器
} TIM_TimeBaseInitTypeDef;
使用步驟
1.使能定時器時鐘;RCC_APB1PeriphClockCmd();
2.初始化定時器,配置ARR,PSC;TIM_TimeBaseInit();
3.開啓定時器中斷,配置NVIC;TIM_ITConfig(); NVIC_Init();
4.使能定時器;TIM_Cmd();
5.編寫相應中斷服務函數。TIM3_IRQHandler();
設置一個500ms的定時器中斷爲例:
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitSrtue;//初始化相應結構體
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能定時器時鐘
TIM_TimeBaseInitSrtue.TIM_Prescaler=psc;//預分頻係數
TIM_TimeBaseInitSrtue.TIM_CounterMode=TIM_CounterMode_Up;//向上計數
TIM_TimeBaseInitSrtue.TIM_Period=arr;//自動裝載值
TIM_TimeBaseInitSrtue.TIM_ClockDivision=TIM_CKD_DIV1;//設置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitSrtue);//初始化TIMx的時間基數單位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//使能定時器的更新中斷
//中斷優先級NVIC設置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先佔優先級0級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級3級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3,ENABLE);//使能定時器
}
void TIM3_IRQHandler(void)//中斷服務函數
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
LED1=!LED1;
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//清除相應標誌位
}
之後,在主函數裏使用該函數並使用相應參數即可
TIM3_Int_Init(4999,7199);//500ms