這一課我們將介紹CKS32F4XX系列產(chǎn)品的定時器使用,CKS32F4XX的定時器功能十分強(qiáng)大,包含2個高級控制定時器,8個普通定時器,2個基礎(chǔ)定時器,以及兩個看門狗定時器和一個系統(tǒng)定時器,總共15個定時器之多。關(guān)于定時器部分內(nèi)容的講解我們將分3個部分展開,本節(jié)將介紹定時器的基本特征和定時操作。
1、計(jì)數(shù)器分辨率:指定時器一個計(jì)數(shù)周期,例如同樣是84Mhz的工作時鐘,
對于TIM2,其分辨率的范圍為:1*(1000ns/ 84)~(2^32)*(1000ns/84);
對于TIM3,其分辨率的范圍為:1*(1000ns/84)~(2^16)*(1000ns/84)。
2、計(jì)數(shù)器類型:這個參數(shù)按照計(jì)數(shù)的方向來劃分:
向上計(jì)數(shù)指的是從0開始到1,2...直到自己設(shè)置的計(jì)數(shù)上限值N,達(dá)到后再次從0開始計(jì)數(shù),周而復(fù)始;
向下計(jì)數(shù)指的是從設(shè)置的計(jì)數(shù)上限值N開始到N-1,N-2,...直到0,達(dá)到后再次從N開始計(jì)數(shù),周而復(fù)始;向上向下計(jì)數(shù)指的是從0,1,2...N,然后再從N,N-1,N-2...0,周而復(fù)始。
3、預(yù)分頻系數(shù):可以通過設(shè)置該系數(shù)來配置時基,如定時器工作在84Mhz下,配置不分頻則一個計(jì)數(shù)時基為11.9ns,配置成2分頻則一個計(jì)數(shù)時基為23.8ns。
4、產(chǎn)生DMA請求:定時器的更新會發(fā)出DMA請求,這是因?yàn)樵贒MA通道中為Timer預(yù)留了一個通道。
5、捕獲比較通道:捕獲就是定時器可以捕捉到通道的上升沿或者下降沿信號,比較就是定時器可以將計(jì)數(shù)器的值和裝載值做比較,關(guān)于這部分將會在下后續(xù)章節(jié)展開。
6、互補(bǔ)輸出:互補(bǔ)輸出指的是輸出的兩個通道兩個波形完全相反,通常運(yùn)用在橋式電路中的互補(bǔ)PWM輸出,這一部分將在后續(xù)章節(jié)展開。
7、最大接口時鐘和最大工作時鐘:定時器的時鐘來源是APB,通過APB預(yù)分頻器的配置,最大工作時鐘可以是PCLKx的兩倍。
CKS32F4XX定時器的定時操作
定時器的定時操作原理其實(shí)很簡單,就像家里用的微波爐一樣,需要加熱食物時,先設(shè)定一個加熱時間,然后按下開關(guān),開始計(jì)時,當(dāng)達(dá)到我們設(shè)置的定時時間以后,微波爐就會停止工作,并會有一個聲音提示我們,定時時間到了。當(dāng)然,在完成定時操作之前,必須要對Timer進(jìn)行一些配置,下面我們以timer3為例,為大家演示。
1、Timer3時鐘使能
TIM3時鐘來自于APB1域,我們通過APB1總線下的時鐘使能函數(shù)來使能TIM3的時鐘。調(diào)用的函數(shù)是:
//>>使能 TIM3 時鐘 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);typedefstruct
2、定時器參數(shù)初始化
在庫函數(shù)中定時器的初始化通過TIM_TimeBaseInit實(shí)現(xiàn)的:
void TIM_TimeBaseInit(TIM_TypeDef *TIMx, TIM_TimeBaseInitTypeDef * TIM_TimeBaseInitStruct);
?參數(shù)結(jié)構(gòu)體指針,結(jié)構(gòu)體類型為TIM_TimeBaseInitTypeDef,下面是結(jié)構(gòu)體的定義:
typedef struct { uint16_t TIM_Prescaler; uint16_t TIM_CounterMode; uint16_t TIM_Period; uint16_t TIM_ClockDivision; uint8_t TIM_RepetitionCounter; } TIM_TimeBaseInitTypeDef;typedefstruct
這個結(jié)構(gòu)體一共有5個成員變量,要說明的是,對于通用定時器只有前面四個參數(shù)有用,最后參數(shù)TIM_RepetitionCounter是高級定時器才有用的,后續(xù)章節(jié)會詳解,在此不贅述。
第一個參數(shù)TIM_Prescaler是用來設(shè)置分頻系數(shù)的,對應(yīng)上表中的預(yù)分頻系數(shù)。
第二個參數(shù)TIM_CounterMode是用來設(shè)置計(jì)數(shù)方式,如上表所述,可以設(shè)置為向上計(jì)數(shù),向下計(jì)數(shù)方式還有向上向下計(jì)數(shù)(中央對齊計(jì)數(shù))方式,比較常用的是向上計(jì)數(shù)TIM_CounterMode_Up和向下計(jì)數(shù) TIM_CounterMode_Down。
第三個參數(shù)是設(shè)置自動重載計(jì)數(shù)周期值,可以通俗的理解成要定時的次數(shù),這個是根據(jù)定時時間和時基做除法換算得到的,比如定時器現(xiàn)在計(jì)數(shù)1次,時間經(jīng)過了250ns,要定時100us,那自動重載計(jì)數(shù)周期值為400。
第四個參數(shù)是用來設(shè)置時鐘分頻因子,這個參數(shù)與定時器的其他功能有密切,本節(jié)操作先按照TIM_CKD_DIV1來配置(不分頻)。
針對TIM3初始化范例代碼格式:
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period=5000; TIM_TimeBaseStructure.TIM_Prescaler=7199; TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
3、設(shè)置TIM3_DIER允許更新中斷
因?yàn)槲覀円_(dá)到定時時間到后有一個到時提醒的效果,這就需要用到TIM3的更新中斷,在庫函數(shù)里面定時器中斷使能是通過TIM_ITConfig函數(shù)來實(shí)現(xiàn)的:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
第一個參數(shù)是選擇定時器號,取值為 TIM1~TIM17。
第二個參數(shù)非常關(guān)鍵,是用來指明我們使能的定時器中斷的類型,定時器中斷的類型有很多種,包括更新中斷TIM_IT_Update,觸發(fā)中斷TIM_IT_Trigger,以及輸入捕獲中斷等等。
第三個參數(shù)就很簡單了,就是失能還是使能。
例如我們要使能TIM3的更新中斷,格式為:
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
4、TIM3中斷優(yōu)先級設(shè)置
在定時器中斷使能之后,因?yàn)橐a(chǎn)生中斷,必不可少的要設(shè)置NVIC(向量中斷控制器)來設(shè)置中斷優(yōu)先級。關(guān)于NVIC_Init函數(shù)實(shí)現(xiàn)中斷優(yōu)先級的設(shè)置請到NVIC章節(jié)參考,這里就不重復(fù)講解。
5、使能TIM3
配置好定時器后,不要忘記開啟定時器,就像按下微波爐的開關(guān)一樣,定時器才會進(jìn)入工作狀態(tài),在固件庫里面使能定時器的函數(shù)是通過TIM_Cmd函數(shù)來實(shí)現(xiàn)的:
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
這個函數(shù)非常簡單,比如我們要使能定時器3,方法為:
//>>使能 TIMx 外設(shè) TIM_Cmd(TIM3, ENABLE);
6、編寫中斷服務(wù)函數(shù)
最后,要編寫定時器中斷服務(wù)函數(shù),類似于聽到微波爐結(jié)束工作的聲音后,我們需要進(jìn)行把加熱的食物取出或者繼續(xù)加熱等操作,通過該函數(shù)來處理定時器產(chǎn)生的相關(guān)中斷。在中斷產(chǎn)生后,通過狀態(tài)寄存器的值來判斷此次產(chǎn)生的中斷屬于什么類型。然后執(zhí)行相關(guān)的操作,我們這里使用的是更新(溢出)中斷,在處理完中斷之后應(yīng),該向TIM3_SR的最低位寫0,來清除該中斷標(biāo)志,在固件庫函數(shù)里面,用來讀取中斷狀態(tài)寄存器的值判斷中斷類型的函數(shù)是:ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t)
該函數(shù)的作用是,判斷定時器TIMx的中斷類型 TIM_IT是否發(fā)生中斷。比如,我們要判斷定時器3 是否發(fā)生更新(溢出)中斷,方法為:
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){} IT_Update) != RESET){}
固件庫中清除中斷標(biāo)志位的函數(shù)是:
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
該函數(shù)的作用是,清除定時器TIMx的中斷TIM_IT 標(biāo)志位。使用起來非常簡單,比如我們在TIM3的溢出中斷發(fā)生后,我們要清除中斷標(biāo)志位,方法是:
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
這里需要說明一下,固件庫還提供了兩個函數(shù)用來判斷定時器狀態(tài)以及清除定時器狀態(tài)標(biāo)
志位的函數(shù)TIM_GetFlagStatus 和TIM_ClearFlag,他們的作用和前面兩個函數(shù)的作用類似。只 是在TIM_GetITStatus函數(shù)中會先判斷這種中斷是否使能,使能了才去判斷中斷標(biāo)志位,而TIM_GetFlagStatus 直接用來判斷狀態(tài)標(biāo)志位。通過以上幾個步驟,我們就可以達(dá)到我們的目的了,使用通用定時器的更新中斷,來實(shí)現(xiàn)定時并產(chǎn)生定時中斷信號。
代碼實(shí)例
/**通用定時器3中斷初始化
>>arr:自動重裝值。psc:時鐘預(yù)分頻數(shù)
>>定時器溢出時間計(jì)算方法:Tout=((arr+1)*(psc+1))/Ft us.
>>Ft=定時器工作頻率,單位:Mhz
這里使用的是定時器3**/
void TIM3_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; NVIC_InitTypeDef NVIC_InitStructure; //>> ①使能 TIM3 時鐘 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //>>自動重裝載值 TIM_TimeBaseInitStructure.TIM_Period = arr; //>>定時器分頻 TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //>>向上計(jì)數(shù)模式 TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; // ②初始化定時器 TIM3 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); //③允許定時器 3 更新中斷 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //定時器 3 中斷 NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //搶占優(yōu)先級 1 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //響應(yīng)優(yōu)先級 3 NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; // ④初始化 NVIC NVIC_Init(&NVIC_InitStructure); //⑤使能定時器 3 TIM_Cmd(TIM3,ENABLE); } //⑥定時器 3 中斷服務(wù)函數(shù) void TIM3_IRQHandler(void) { //>>溢出中斷 if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) { } //>>清除中斷標(biāo)志位 TIM_ClearITPendingBit(TIM3,TIM_IT_Update); }
這里列出了一個中斷服務(wù)函數(shù)和一個定時器3中斷初始化函數(shù),中斷服務(wù)函數(shù)中,在每次中斷后,判斷 TIM3的中斷類型,如果中斷類型正確,則執(zhí)行自己需要執(zhí)行的操作并清除中斷標(biāo)志,TIM3_Int_Init 函數(shù)就是執(zhí)行我們上面介紹的那5個步驟,使得 TIM3開始工作,并開啟中斷。這里我們分別用標(biāo)號①~⑤來標(biāo)注定時器初始化的五個步驟。該函數(shù)的2 個參數(shù)用來設(shè)置TIM3的溢出時間。假設(shè)系統(tǒng)初始化 SystemInit函數(shù)里面已經(jīng)初始化APB1的時鐘為 4分頻,所以APB1的時鐘為42M,這也是timer3的最大接口時鐘,而從CKS32F4的內(nèi)部時鐘樹圖得知:當(dāng)APB1的時鐘分頻數(shù)為1的時候,TIM2~7以及TIM12~14的時鐘為APB1的時鐘,而如果APB1的時鐘分頻數(shù)不為1,那么TIM2~7以及TIM12~14的時鐘頻率將為APB1時鐘的兩倍。因此,TIM3的時鐘為84M,再根據(jù)我們設(shè)計(jì)的arr和psc的值,就可以計(jì)算中斷時間了。計(jì)算公式如下:
Tout=((arr+1)*(psc+1))/Tclk;
其中:
Tclk:TIM3的輸入時鐘頻率(單位為Mhz)。
Tout:TIM3溢出時間(單位為us)。
本節(jié)我們介紹了CKS32F4XX各定時器概況,以及如何設(shè)置最基礎(chǔ)的定時功能,包括開啟定時器的時鐘,配置定時器的時基,定時次數(shù)以及計(jì)數(shù)的方向等,此外定時器其他的功能如輸入捕獲,比較輸出和PWM輸出等功能將會在后續(xù)章節(jié)展開。
審核編輯:湯梓紅
-
mcu
+關(guān)注
關(guān)注
146文章
17148瀏覽量
351185 -
計(jì)數(shù)器
+關(guān)注
關(guān)注
32文章
2256瀏覽量
94562 -
定時器
+關(guān)注
關(guān)注
23文章
3248瀏覽量
114792 -
dma
+關(guān)注
關(guān)注
3文章
561瀏覽量
100583 -
Timer
+關(guān)注
關(guān)注
1文章
64瀏覽量
12786
原文標(biāo)題:MCU微課堂|CKS32F4xx系列產(chǎn)品Timer的基本使用方法-定時操作
文章出處:【微信號:中科芯MCU,微信公眾號:中科芯MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論