【STM32】定时器程序
00. 目錄
文章目錄
- 00. 目錄
- 01. 通用定時(shí)器簡(jiǎn)介
- 02. 通用定時(shí)器時(shí)鐘
- 03. 定時(shí)器配置步驟
- 04. 硬件設(shè)計(jì)
- 05. 程序示例
- 06. 附錄
- 07. 聲明
01. 通用定時(shí)器簡(jiǎn)介
STM32F4 的通用定時(shí)器包含一個(gè) 16 位或 32 位自動(dòng)重載計(jì)數(shù)器(CNT),該計(jì)數(shù)器由可編程預(yù)分頻器(PSC)驅(qū)動(dòng)。STM32F4 的通用定時(shí)器可以被用于:測(cè)量輸入信號(hào)的脈沖長(zhǎng)度(輸入捕獲)或者產(chǎn)生輸出波形(輸出比較和 PWM)等。 使用定時(shí)器預(yù)分頻器和 RCC 時(shí)鐘控制器預(yù)分頻器,脈沖長(zhǎng)度和波形周期可以在幾個(gè)微秒到幾個(gè)毫秒間調(diào)整。STM32F4 的每個(gè)通用定時(shí)器都是完全獨(dú)立的,沒(méi)有互相共享的任何資源。
STM3 的通用 TIMx (TIM2~TIM5 和 TIM9~TIM14)定時(shí)器功能包括:
16 位/32 位(僅 TIM2 和 TIM5)向上、向下、向上/向下自動(dòng)裝載計(jì)數(shù)器(TIMx_CNT),注意:TIM9~TIM14 只支持向上(遞增)計(jì)數(shù)方式。
16 位可編程(可以實(shí)時(shí)修改)預(yù)分頻器(TIMx_PSC),計(jì)數(shù)器時(shí)鐘頻率的分頻系數(shù)為 1~65535 之間的任意數(shù)值。
3)4 個(gè)獨(dú)立通道(TIMx_CH14,TIM9TIM14 最多 2 個(gè)通道),這些通道可以用來(lái)作為:
A.輸入捕獲
B.輸出比較
C.PWM 生成(邊緣或中間對(duì)齊模式) ,注意:TIM9~TIM14 不支持中間對(duì)齊模式
D.單脈沖模式輸出
4)可使用外部信號(hào)(TIMx_ETR)控制定時(shí)器和定時(shí)器互連(可以用 1 個(gè)定時(shí)器控制另外一個(gè)定時(shí)器)的同步電路。
5)如下事件發(fā)生時(shí)產(chǎn)生中斷/DMA(TIM9~TIM14 不支持 DMA):
A.更新:計(jì)數(shù)器向上溢出/向下溢出,計(jì)數(shù)器初始化(通過(guò)軟件或者內(nèi)部/外部觸發(fā))
B.觸發(fā)事件(計(jì)數(shù)器啟動(dòng)、停止、初始化或者由內(nèi)部/外部觸發(fā)計(jì)數(shù))
C.輸入捕獲
D.輸出比較
E.支持針對(duì)定位的增量(正交)編碼器和霍爾傳感器電路(TIM9~TIM14 不支持)
F.觸發(fā)輸入作為外部時(shí)鐘或者按周期的電流管理(TIM9~TIM14 不支持)
02. 通用定時(shí)器時(shí)鐘
定時(shí)器的時(shí)鐘來(lái)源有 4 個(gè):
1)內(nèi)部時(shí)鐘(CK_INT)
2)外部時(shí)鐘模式 1:外部輸入腳(TIx)
3)外部時(shí)鐘模式 2:外部觸發(fā)輸入(ETR),僅適用于 TIM2、TIM3、TIM4
4)內(nèi)部觸發(fā)輸入(ITRx):使用 A 定時(shí)器作為 B 定時(shí)器的預(yù)分頻器(A 為 B 提供時(shí)鐘)。
這些時(shí)鐘,具體選擇哪個(gè)可以通過(guò) TIMx_SMCR 寄存器的相關(guān)位來(lái)設(shè)置。這里的 CK_INT時(shí)鐘是從 APB1 倍頻的來(lái)的,除非 APB1 的時(shí)鐘分頻數(shù)設(shè)置為 1(一般都不會(huì)是 1),否則通用定時(shí)器 TIMx 的時(shí)鐘是 APB1 時(shí)鐘的 2 倍,當(dāng) APB1 的時(shí)鐘不分頻的時(shí)候,通用定時(shí)器 TIMx的時(shí)鐘就等于 APB1 的時(shí)鐘。這里還要注意的就是高級(jí)定時(shí)器以及 TIM9~TIM11 的時(shí)鐘不是來(lái)自 APB1,而是來(lái)自 APB2 的。
這里順帶介紹一下 TIMx_CNT 寄存器,該寄存器是定時(shí)器的計(jì)數(shù)器,該寄存器存儲(chǔ)了當(dāng)前定時(shí)器的計(jì)數(shù)值。
03. 定時(shí)器配置步驟
3.1 TIM3 時(shí)鐘使能。
TIM3 是掛載在 APB1 之下,所以我們通過(guò) APB1 總線下的時(shí)鐘使能函數(shù)來(lái)使能 TIM3。調(diào)用的函數(shù)是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能 TIM3 時(shí)鐘3.2 初始化定時(shí)器參數(shù) 數(shù), 設(shè)置 自動(dòng)重裝值 , 分頻系數(shù) ,計(jì)數(shù)方式 等。
在庫(kù)函數(shù)中,定時(shí)器的初始化參數(shù)是通過(guò)初始化函數(shù) TIM_TimeBaseInit 實(shí)現(xiàn)的:
void TIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);第一個(gè)參數(shù)是確定是哪個(gè)定時(shí)器,這個(gè)比較容易理解。第二個(gè)參數(shù)是定時(shí)器初始化參數(shù)結(jié)構(gòu)體指針,結(jié)構(gòu)體類(lèi)型為T(mén)IM_TimeBaseInitTypeDef,下面我們看看這個(gè)結(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;這個(gè)結(jié)構(gòu)體一共有 5 個(gè)成員變量,要說(shuō)明的是,對(duì)于通用定時(shí)器只有前面四個(gè)參數(shù)有用,最后一個(gè)參數(shù) TIM_RepetitionCounter 是高級(jí)定時(shí)器才有用的,這里不多解釋。
第一個(gè)參數(shù) TIM_Prescaler 是用來(lái)設(shè)置分頻系數(shù)的,剛才上面有講解。
第二個(gè)參數(shù) TIM_CounterMode 是用來(lái)設(shè)置計(jì)數(shù)方式,上面講解過(guò),可以設(shè)置為向上計(jì)數(shù),向下計(jì)數(shù)方式還有中央對(duì)齊計(jì)數(shù)方式,比較常用的是向上計(jì)數(shù)模式 TIM_CounterMode_Up 和向下計(jì)數(shù)模式 TIM_CounterMode_Down。
第三個(gè)參數(shù)是設(shè)置自動(dòng)重載計(jì)數(shù)周期值,這在前面也已經(jīng)講解過(guò)。
第四個(gè)參數(shù)是用來(lái)設(shè)置時(shí)鐘分頻因子。
針對(duì) TIM3 初始化范例代碼格式:
TIM_TimeBaseInitTypeDef TIM_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.3 設(shè)置 TIM3_DIER 允許更新中斷。
因?yàn)槲覀円褂?TIM3 的更新中斷,寄存器的相應(yīng)位便可使能更新中斷。在庫(kù)函數(shù)里面定時(shí)器中斷使能是通過(guò) TIM_ITConfig 函數(shù)來(lái)實(shí)現(xiàn)的:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);第一個(gè)參數(shù)是選擇定時(shí)器號(hào),這個(gè)容易理解,取值為 TIM1~TIM17。
第二個(gè)參數(shù)非常關(guān)鍵,是用來(lái)指明我們使能的定時(shí)器中斷的類(lèi)型,定時(shí)器中斷的類(lèi)型有很多種,包括更新中斷 TIM_IT_Update,觸發(fā)中斷 TIM_IT_Trigger,以及輸入捕獲中斷等等。
第三個(gè)參數(shù)就很簡(jiǎn)單了,就是失能還是使能。
例如我們要使能 TIM3 的更新中斷,格式為:
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );3.4 TIM3 中斷優(yōu)先級(jí)設(shè)置。
在定時(shí)器中斷使能之后,因?yàn)橐a(chǎn)生中斷,必不可少的要設(shè)置 NVIC 相關(guān)寄存器,設(shè)置中斷優(yōu)先級(jí)。之前多次講解到用 NVIC_Init 函數(shù)實(shí)現(xiàn)中斷優(yōu)先級(jí)的設(shè)置。
3.5 允許 TIM3 工作,也就是使能 TIM3 。
光配置好定時(shí)器還不行,沒(méi)有開(kāi)啟定時(shí)器,照樣不能用。我們?cè)谂渲猛旰笠_(kāi)啟定時(shí)器,通過(guò) TIM3_CR1 的 CEN 位來(lái)設(shè)置。在固件庫(kù)里面使能定時(shí)器的函數(shù)是通過(guò) TIM_Cmd 函數(shù)來(lái)實(shí)現(xiàn)的:
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)這個(gè)函數(shù)非常簡(jiǎn)單,比如我們要使能定時(shí)器 3,方法為:
TIM_Cmd(TIM3, ENABLE); //使能 TIMx 外設(shè)3.6 編寫(xiě)中斷服務(wù)函數(shù)。
在最后,還是要編寫(xiě)定時(shí)器中斷服務(wù)函數(shù),通過(guò)該函數(shù)來(lái)處理定時(shí)器產(chǎn)生的相關(guān)中斷。在中斷產(chǎn)生后,通過(guò)狀態(tài)寄存器的值來(lái)判斷此次產(chǎn)生的中斷屬于什么類(lèi)型。然后執(zhí)行相關(guān)的操作,我們這里使用的是更新(溢出)中斷,所以在狀態(tài)寄存器 SR 的最低位。在處理完中斷之后應(yīng)該向 TIM3_SR 的最低位寫(xiě) 0,來(lái)清除該中斷標(biāo)志。
在固件庫(kù)函數(shù)里面,用來(lái)讀取中斷狀態(tài)寄存器的值判斷中斷類(lèi)型的函數(shù)是
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t)該函數(shù)的作用是,判斷定時(shí)器 TIMx 的中斷類(lèi)型 TIM_IT 是否發(fā)生中斷。比如,我們要判斷定時(shí)器 3 是否發(fā)生更新(溢出)中斷,方法為:
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}固件庫(kù)中清除中斷標(biāo)志位的函數(shù)是:
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)該函數(shù)的作用是,清除定時(shí)器 TIMx 的中斷 TIM_IT 標(biāo)志位。使用起來(lái)非常簡(jiǎn)單,比如我們?cè)赥IM3 的溢出中斷發(fā)生后,我們要清除中斷標(biāo)志位,方法是:
TIM_ClearITPendingBit(TIM3, TIM_IT_Update )這里需要說(shuō)明一下,固件庫(kù)還提供了兩個(gè)函數(shù)用來(lái)判斷定時(shí)器狀態(tài)以及清除定時(shí)器狀態(tài)標(biāo)志位的函數(shù) TIM_GetFlagStatus 和 TIM_ClearFlag,他們的作用和前面兩個(gè)函數(shù)的作用類(lèi)似。只是在 TIM_GetITStatus 函數(shù)中會(huì)先判斷這種中斷是否使能,使能了才去判斷中斷標(biāo)志位,而TIM_GetFlagStatus 直接用來(lái)判斷狀態(tài)標(biāo)志位。
04. 硬件設(shè)計(jì)
用到的硬件資源有:
1) 指示燈 DS0 和 DS1
2) 定時(shí)器 TIM3
將通過(guò) TIM3 的中斷來(lái)控制 DS1 的亮滅,DS1 是直接連接到 PF10 上的,這個(gè)前面已經(jīng)有介紹了。而 TIM3 屬于 STM32F4 的內(nèi)部資源,只需要軟件設(shè)置即可正常工作。
05. 程序示例
timer.h
#ifndef __TIMER_H__ #define __TIMER_H__#include "sys.h"//定時(shí)器初始化 void TIM3_Int_Init(u16 arr, u16 psc);#endif /*__TIMER_H__*/timer.c
#include "timer.h" #include "led.h"//定時(shí)器初始化 //arr:自動(dòng)重裝值。 //psc:時(shí)鐘預(yù)分頻數(shù) //定時(shí)器溢出時(shí)間計(jì)算方法:Tout=((arr+1)*(psc+1))/Ft us. //Ft=定時(shí)器工作頻率,單位:Mhz //這里使用的是定時(shí)器3! void TIM3_Int_Init(u16 arr, u16 psc) {TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;NVIC_InitTypeDef NVIC_InitStruct;//初始化定時(shí)器時(shí)鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//初始化定時(shí)器TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period = arr;TIM_TimeBaseInitStruct.TIM_Prescaler = psc;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);//使能更新中斷TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//中斷初始化NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStruct);//使能定時(shí)器TIM_Cmd(TIM3, ENABLE);}//中斷處理函數(shù) void TIM3_IRQHandler(void) {if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){LED2 = !LED2;}//清除中斷標(biāo)志位TIM_ClearITPendingBit(TIM3, TIM_IT_Update); }main.c
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "beep.h" #include "key.h" #include "exti.h" #include "iwdg.h" #include "wwdg.h" #include "timer.h"int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);delay_init(168);LED_Init();KEY_Init();LED1 = 0;LED2 = 0;//定時(shí)器初始化TIM3_Int_Init(5000 - 1, 8400 - 1);while(1){LED1 = !LED1;delay_ms(300);} }結(jié)果驗(yàn)證
DS1 不停閃爍(每 600ms 閃爍一次),而 DS0 也是不停的閃爍,但是閃爍時(shí)間較 DS0 慢(1s 一次)
06. 附錄
6.1 【STM32】STM32系列教程匯總
網(wǎng)址:【STM32】STM32系列教程匯總
07. 聲明
該教程參考了正點(diǎn)原子的《STM32 F4 開(kāi)發(fā)指南》
總結(jié)
以上是生活随笔為你收集整理的【STM32】定时器程序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【STM32】定时器相关函数和类型
- 下一篇: 【STM32】PWM程序