基本概念
STM32中有三種定時器,高級定時器,通用定時器,基本定時器,具體如下圖:
發生如下事件將產生中斷/DMA
- 更新:計數器向上溢出/向下溢出,計數器初始化
- 觸發事件:計數器啟動、停止、初始化或者由內部/外部觸發計數
- 輸入捕獲
- 輸出比較
- 支持針對定位的增量(正交)編碼器和霍爾傳感器電路
- 觸發事件作為外部時鐘或者按周期的電流管理
計數器模式
- 向上計數:計數器從0計數到自動加載值ARR,然后重新沖0開始計數并且產生一個計數器溢出事件
- 向下計數模式:計數器從自動裝入的值ARR開始向下計數到0,然后從自動裝載值重新開始,并產生一個計數器向下溢出事件
- 終于對齊模式(向上/向下計數):計數器從0開始計數到自動裝載值的值-1,產生一個計數器溢出事件,然后向下計數到1并產生一個計數器溢出事件,然后再從0開始重新計數
定時器中斷實現步驟
- 使能定時器
__HAL_RCC_TIM3_CLK_ENABLE();
- 初始化定時器,配置ARR,PSC
HAL_TIM_Base_Init();
- 開啟定時器中斷
HAL_TIM_Base_Start();
HAL_TIM_Base_Start_IT();
- 設置中斷優先級
HAL_NVIC_SetPriority();
HAL_NVIC_EnableIRQ();
- 編寫中斷服務函數
TIMx_IRQHandler();//中斷服務函數
HAL_TIM_IRQHandler(); //HAL庫定時器中斷通用處理函數
HAL_TIM_PeriodElapsedCallback(); //定時器更新中斷回調函數
具體代碼
使用TIM3讓LED1每500ms亮一次
- 使能定時器,我們放在第二步
- 初始化定時器,配置ARR,PSC
TIM_HandleTypeDef time_handler;
void time_init(void)
{time_handler.Instance = TIM3; //可以取TIM1-TIM14time_handler.Init.CounterMode = TIM_COUNTERMODE_UP; //計數模式,向上/下time_handler.Init.Period = 5000-1; //自動裝載值,即ARR的值time_handler.Init.Prescaler = 9000-1;//預分配系數,即PSC的值 //定時時間=(Period+1)(Prescaler+1)/Tclk=90000000(9Mhz)//time_handler.Init.ClockDivision= 時鐘分頻因子:定時器時鐘與數字濾波器分頻比//time_handler.Init.RepetitionCounter= 重復計數次數:高級定時器使用HAL_TIM_Base_Init(&time_handler);
}void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){__HAL_RCC_TIM3_CLK_ENABLE();HAL_NVIC_EnableIRQ(TIM3_IRQn);HAL_NVIC_SetPriority(TIM3_IRQn,3,3);HAL_TIM_Base_Start_IT(&time_handler); //開啟定時器并更新中斷,以后每次更新中斷,都會調用TIM3_IRQHandler}}
HAL_TIM_Base_Init初始化定時器后,會調用HAL_TIM_Base_MspInit函數,我們可以在HAL_TIM_Base_MspInit中使能TIM3,HAL_TIM_Base_MspInit還開啟TIM3中斷以及設置中斷優先級
對于Init參數
- Instance 可以取值TIM1到TIM14,表示使用哪個定時器
- CounterMode :計數模式,向上/下
- Period :自動裝載值,即ARR的值
- Prescaler :預分配系數,即PSC的值
- ClockDivision: 時鐘分頻因子,定時器時鐘與數字濾波器分頻比
- RepetitionCounter:重復計數次數,高級定時器使用
定時時間=(Period+1)(Prescaler+1)/Tclk
Tclk:輸入時鐘頻率,TIM3為90M,計算得出定時時間=0.5s
- 開啟定時器中斷,在步驟2中完成
- 設置中斷優先級,在步驟2中完成
步驟1-4是配置TIM3定時器中斷,步驟5是來處理TIM3定時器中斷
- 編寫中斷服務函數
void TIM3_IRQHandler(void)
{HAL_TIM_IRQHandler(&time_handler); //HAL定時器中斷通用函數
}//定時器通用更新中斷回調函數
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){LED1 = !LED1;}}
當定時器TIM3時間到了時,會調用TIM3_IRQHandler函數,每個定時器都用一個中斷服務處理函數,在TIM3_IRQHandler中,我們使用了HAL庫定時器通用處理函數HAL_TIM_IRQHandler,HAL_TIM_IRQHandler內部會調用HAL_TIM_PeriodElapsedCallback更新回調函數,我們在HAL_TIM_PeriodElapsedCallback寫邏輯處理就可以了
main函數調用time_init即可,具體代碼
int main(void)
{//u8 press;HAL_Init();Stm32_Clock_Init(360,25,2,8);delay_init(180);Rcc_Init();LED_Init();KEY_Init();time_init();while(1){}}