前言
本文主要基于stm32f103系列講解定時器中斷進行計時代替延時函數,其中思路和原理同時適用于其他系列的單片機。
一、使用定時器中斷的優缺點
相較于普通延時函數(delay),定時器中斷計時無論是從代碼的體量,還是使用,都要比延時函數更多更復雜,也更難理解。既然延時函數如此便捷,那我們又為什么不使用它呢?
首先在使用延時函數時,程序會停止在延時函數的位置,直到延時結束,在一些簡單程序,使用延時函數的影響確實可以忽略不計,但是過多的延時函數會使程序變得臃腫,編譯執行時間大大增加,程序的精度會下降,例如利用按鍵控制led燈時,led燈會不受按鍵控制,出現時靈時不靈的情況,這種情況就是延時函數使用過多造成的,更嚴重的甚至會造成單片機宕機。
所以,為了避免這種情況的發生,我們可以使用定時器中斷來代替延時函數,下面是我個人的一些理解和認識,如有不足,歡迎指正。
二、使用步驟
1.原理思路
首先,我們需要配置一個定時器,stm32一般選用通用定時器即可,我們可以利用定時器初始化函數設定定時器計時一次的時間,公式如下:
定時時間=(arr+1)(psc+1)/Tclk
其中arr為自動重裝載值,psc為預分頻系數,TCLK為時鐘頻率,例如:TCLK=72MHz,那么psc=71,所以可以理解為時間就是(arr+1)微妙,那么如果我想定時1ms,arr取999即可(arr,psc為定時器初始化函數形參)。
當定時器的計數器計數到自動重裝載值時,進入中斷服務函數,這時我們需要設置一個標志位(flag)和作為計數用的值(count),每次進入中斷count執行自加或自減,當其自加或自減到設置的數值時,標志位反轉。
例如:定時200ms,已知1ms進入一次中斷,標志位flag初始值為0,那么讓count自加到200,因為每次自加是1ms,自加兩百次就是200ms,這時flag置1表示到達200毫秒并可以執行相關程序。
2.相關代碼
(1).定時器初始化
(這里我初始的是TIM2)
TIMER.H
#ifndef __TIMER_H #define __TIMER_H #include "sys.h" #include "stm32f10x_tim.h" void TIM2_Int_Init(u16 arr,u16 psc);//通用定時器的初始化函數;arr:自動重裝載值psc:預分頻系數 #endif
TIMER.C
#include "TIMER.h" void TIM2_Int_Init(u16 arr,u16 psc)//通用定時器3的初始化函數 { //定義相關結構體 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue;//定義一個定時器初始化的結構體 NVIC_InitTypeDef NVIC_InitStrue;//定義中斷優先級初始化的函數 //使能定時器時鐘 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能通用定時器3的時鐘 //設置并初始化定時器TIM2 TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;//計數模式設置為向上計數 TIM_TimeBaseInitStrue.TIM_Period=arr;//計數器模式為向上計數時,定時器從0開始計數,超過arr //觸發定時中斷服務函數 TIM_TimeBaseInitStrue.TIM_Prescaler=psc;//預分頻系數,決定每一個計數的時長 TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;//一般不使用,默認為TIM_CKD_DIV1 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStrue);//根據參數初始化定時器TIM3 //使能定時器中斷 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能TIM3的中斷,中斷模式為更新中斷 //初始化定時器中斷,定時器中斷優先級設置 NVIC_InitStrue.NVIC_IRQChannel=TIM2_IRQn;//中斷通道設置為TIM3 NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//使能中斷 NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//搶占優先級為1級 NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//響應優先級為1級 NVIC_Init(&NVIC_InitStrue);//根據參數初始化中斷寄存器 //使能定時器 TIM_Cmd(TIM2,ENABLE);//使能通用定時器TIM2 }
(2).stm32f10x_it.c(該文件專門用于存放中斷服務函數)
#include "stm32f10x_it.h" extern u8 flag;//標志位 void TIM2_IRQHandler() { static u8 count; if(TIM_GetITStatus(TIM2, TIM_IT_Update)==1) //當發生中斷時狀態寄存器(TIMx_SR)的bit0會被硬件 //置1 { if(count--==0) { count=20; flag=1; } TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //狀態寄存器(TIMx_SR)的bit0置0 } }
(3).主函數main.c
#include "stm32f10x.h" #include "stm32f10x_conf.h" #include "sys.h" u8 flag=0; int main(void) { delay_init(); //初始化延時函數 LED_Init(); //初始化led燈 TIM2_Int_Init(9999,71); //定時10ms進入一次中斷 while(1) { if(flag==1) //標志位置一代表一次定時完成 { PAout(2)=~PAout(2); //led2取反 flag=0; //標志位置0,再次計時(該程序設置一次定時為200ms) } } }
3.效果:
每隔200msLED燈閃爍。
總結
以上是本人對定時器中斷的一些認識(本人小白),其中有些地方講解不到位,還望各位指正,歡迎評論區留言。
審核編輯:湯梓紅
-
單片機
+關注
關注
6035文章
44554瀏覽量
634653 -
中斷
+關注
關注
5文章
898瀏覽量
41471 -
定時器
+關注
關注
23文章
3246瀏覽量
114720 -
STM32F103
+關注
關注
33文章
477瀏覽量
63600 -
延時函數
+關注
關注
0文章
25瀏覽量
10018
發布評論請先 登錄
相關推薦
評論