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