TIM簡介
TIM(Timer)定時器
????????定時器可以對輸入的時鐘進行計數,并在計數值達到設定值時觸發中斷
????????16位計數器、預分頻器、自動重裝寄存器的時基單元,在72MHz計數時鐘下可以實現最大59.65s的定時
????????不僅具備基本的定時中斷功能,而且還包含內外時鐘源選擇、輸入捕獲、輸出比較、編碼器接口、主從觸發模式等多種功能
????????根據復雜度和應用場景分為了高級定時器、通用定時器、基本定時器三種類型
定時器類型
定時中斷基本結構
計數器時序:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? = CK_PSC (72M)/ (PSC + 1) / (ARR + 1)
預分頻器時序:
定時器中斷代碼:?
TIM函數介紹:
????????下面的函數對應著定時中斷的結構
//時基單元初始化
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);//將結構體變量賦一個默認值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);//使能計數器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);//使能中斷輸出信號
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);//選擇內部時鐘
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);//選擇ITRx其他定時器時鐘
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);//選擇TIx捕獲通道的時鐘
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);//選擇ETR通過外部時鐘模式1輸入的時鐘
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);//選擇ETR通過外部時鐘模式2輸入的時鐘
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);//單獨配置ETR引腳的預分頻器、極性、濾波器這些參數
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
參數更改函數:
//單獨寫預分頻值
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);//用來更改計數器的計數模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);//自動重裝器預裝功能配置
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);//給計數器寫入一個值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);//給自動重裝器寫入一個值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);//獲取當前計數器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);//獲取當前的預分頻器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
配置定時器(內部時鐘):
打開時鐘
這次初始化TIM2,也就是通用定時器,TIM2是APB1的總線外設。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打開TIM2的外設時鐘
選擇內部時鐘
這里不寫這行代碼也行,因為定時器上電后默認就是使用內部時鐘
TIM_InternalClockConfig(TIM2);//選擇內部時鐘
配置時基單元
//-----------------------------配置時基單元---------------------------------TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定義TIM結構體變量TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ; //時鐘分頻TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//計數器模式 這里選擇向上計數TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //周期 就是ARR自動重裝器的值TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; //是PSC預分頻器的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重復計數器的值(這個是高級寄存器才有的,這里不需要用直接給0)TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //TIM初始化//-----------------------------配置時基單元---------------------------------
使能更新中斷
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //開啟更新中斷到NVIC通路
NVIC配置
這里的中斷通道選擇TIM2的中斷通道。
//-----------------------------NVIC配置-------------------------------------NVIC_InitTypeDef NVIC_InitStructure;//定義NVIC結構體變量NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//選擇中斷分組2NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//選擇中斷通道NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中斷通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//搶占優先級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //響應優先級NVIC_Init(&NVIC_InitStructure);//NVIC初始化//-----------------------------NVIC配置-------------------------------------
啟動定時器:
TIM_Cmd(TIM2,ENABLE);//啟動定時器
整體函數:
void Timer_Init(void)
{//---------------------------定義結構體變量-------------------------------TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定義TIM結構體變量NVIC_InitTypeDef NVIC_InitStructure;//定義NVIC結構體變量//---------------------------定義結構體變量-------------------------------RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打開TIM2的外設時鐘TIM_InternalClockConfig(TIM2);//選擇內部時鐘//-----------------------------配置時基單元---------------------------------TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ; //時鐘分頻TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數器模式 這里選擇向上計數TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //周期 就是ARR自動重裝器的值TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; //是PSC預分頻器的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重復計數器的值(這個是高級寄存器才有的,這里不需要用直接給0)TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //TIM初始化//-----------------------------配置時基單元---------------------------------TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //開啟更新中斷到NVIC通路//-----------------------------NVIC配置-------------------------------------NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//選擇中斷分組2NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//選擇中斷通道NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中斷通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//搶占優先級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //響應優先級NVIC_Init(&NVIC_InitStructure);//NVIC初始化//-----------------------------NVIC配置-------------------------------------TIM_Cmd(TIM2,ENABLE);//啟動定時器
}
中斷函數:
實現定時器計時功能。
uint16_t Num = 0;
//中斷函數void TIM2_IRQHandler(void)
{//獲取中斷標志位,判斷是否觸發中斷if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中斷標志位}}
這里定義了一個變量Num,所以需要在頭文件了extern一下,讓其他工程文件也能用這個變量。
主函數:
完成了定時器計時功能,沒過一秒,Num + 1.在屏幕上顯示出來。
#include "timer.h"
int main(void)
{LED_Init();OLED_Init();Timer_Init();OLED_ShowString(1, 3, "Num:");while(1){OLED_ShowNum(1, 5, Num, 5);} }
這里上電以及復位不是從零開始,需要在NVIC配置之前清除一下標志位
配置外部時鐘:
選擇外部時鐘模式
與內部時鐘配置一樣,只需要選擇外部時鐘模式以及加一個GPIO配置。
配置GPIO
//-----------------------------GPIO配置-------------------------------------GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO結構體變量GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //選擇上拉輸入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //配置引腳GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率GPIO_Init(GPIOA, &GPIO_InitStructure);//GPIO初始化//-----------------------------GPIO配置-------------------------------------
整體函數配置:
void Timer_Init(void)
{//---------------------------定義結構體變量-------------------------------TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定義TIM結構體變量NVIC_InitTypeDef NVIC_InitStructure; //定義NVIC結構體變量GPIO_InitTypeDef GPIO_InitStructure; //定義GPIO結構體變量//---------------------------定義結構體變量-------------------------------RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打開TIM2的外設時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打開GPIO A族時鐘TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted,0x0F);//選擇外部時鐘模式//-----------------------------GPIO配置-------------------------------------GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //選擇上拉輸入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //配置引腳GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率GPIO_Init(GPIOA, &GPIO_InitStructure);//GPIO初始化//-----------------------------GPIO配置-------------------------------------//-----------------------------配置時基單元---------------------------------TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ; //時鐘分頻TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數器模式 這里選擇向上計數TIM_TimeBaseInitStructure.TIM_Period = 10 - 1; //周期 就是ARR自動重裝器的值TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //是PSC預分頻器的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重復計數器的值(這個是高級寄存器才有的,這里不需要用直接給0)TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //TIM初始化//-----------------------------配置時基單元---------------------------------TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //開啟更新中斷到NVIC通路TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除標志位//-----------------------------NVIC配置-------------------------------------NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//選擇中斷分組2NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//選擇中斷通道NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中斷通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//搶占優先級NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //響應優先級NVIC_Init(&NVIC_InitStructure);//NVIC初始化//-----------------------------NVIC配置-------------------------------------TIM_Cmd(TIM2,ENABLE);//啟動定時器
}
功能中斷函數:
uint16_t Num = 0;
//中斷函數void TIM2_IRQHandler(void)
{//獲取中斷標志位,判斷是否觸發中斷if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中斷標志位}}uint16_t Timer_Getcount(void)
{return TIM_GetCounter(TIM2);
}
主函數:
#include "timer.h"
int main(void)
{LED_Init();OLED_Init();Timer_Init();OLED_ShowString(1, 1, "Num:");OLED_ShowString(2, 1, "CNT:");while(1){OLED_ShowNum(1, 5, Num, 5);OLED_ShowNum(2, 5, Timer_Getcount(), 5);}
}