新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > STM32學習筆記一時鐘和定時器

STM32學習筆記一時鐘和定時器

作者: 時間:2016-11-19 來源:網(wǎng)絡 收藏
由于近期在準備海洋航行器比賽,正好趁此機會學習一下ARM,看到周圍很多同學都在使用32,所以我也買了一塊STM32F103ZET6,準備好好地學習一下。

STM32的時鐘系統(tǒng)相當?shù)膹碗s,包含了5個時鐘源,分別是HSI HSE LSI LSE PLL,HSI是高速內(nèi)部時鐘、RC振蕩器,頻率為8M,HSE是高速外部時鐘,即晶振,我的核心板上晶振為8M。LSI為低速內(nèi)部時鐘、RC振蕩器,頻率40k,LSE為低速外部時鐘,接32.768kHz晶振,作為RTC時鐘源。PLL為鎖相環(huán)倍頻輸出,最大不超過72M。

本文引用地址:http://butianyuan.cn/article/201611/318495.htm

我在學習定時器時先看的是TIM3,它掛載在APB1分頻器上,APB1上面掛載的是低速外設,APB2上掛載高速外設。

在system_stm32f10x.c文件下,有默認定義SYSCLK_FREQ_72MHz,同時在SystemInit()函數(shù)下調(diào)用了SetSysClock(),根據(jù)宏定義將時鐘設為72M。

讀取SystemCoreClock變量即可獲得系統(tǒng)時鐘頻率。

在默認情況下,系統(tǒng)的各個時鐘頻率如下:

SYSCLK:72M

AHB:72M

APB1(PCLK1):36M

APB2(PCLK2):72M

PLL:72M

詳細的定時器設定如下:

①首先要搞清楚定時器的計數(shù)時鐘頻率,在預分頻系數(shù)≠1的時候,TIM2~7的時鐘頻率為APB1的2倍,即72MHz,預分頻系數(shù)的默認值不是1,但我并未查到該如何設置該值。

②定時器的設置主要包括定時器的初始化和中斷的初始化。

2.1 定時器初始化:

首先定義TIM_TimeBaseInitTypeDef類型的結構體,它包含了如下的內(nèi)容:

typedef struct{uint16_t TIM_Prescaler;        uint16_t TIM_CounterMode;     uint16_t TIM_Period;           uint16_t TIM_ClockDivision;   uint8_t TIM_RepetitionCounter; } TIM_TimeBaseInitTypeDef;

第一項TIM_Prescaler是預分頻值,它與TIM_Period(重載周期值)的乘積即為計數(shù)的總值。

第二項TIM_CounterMode為計數(shù)模式,它的內(nèi)容如下:

#define TIM_CounterMode_Up                 ((uint16_t)0x0000)#define TIM_CounterMode_Down               ((uint16_t)0x0010)#define TIM_CounterMode_CenterAligned1     ((uint16_t)0x0020)#define TIM_CounterMode_CenterAligned2     ((uint16_t)0x0040)#define TIM_CounterMode_CenterAligned3     ((uint16_t)0x0060)

后面三項為中心對齊模式,指的是計數(shù)到一定的值,產(chǎn)生溢出事件,再向下計數(shù)到0。常用的為向上計數(shù)模式,即TIM_CounterMode_Up

第四項TIM_ClockDivision為時鐘分割,對于時鐘分割沒有查到太多的描述,一般設定為TIM_CKD_DIV1,或者直接填入0x0000。

第五項TIM_RepetitionCounter為PWM模式的一些設定,一般的定時器不用設置。

除此之外還要設置中斷的類型,一般的定時器為更新中斷,即由溢出事件產(chǎn)生的中斷,設置的方式為:TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE),其中第一項是定時器代號,第二項為類型,這里設定為更新方式,第三項為使能。

根據(jù)上述內(nèi)容我們知道,初始化的過程如下:

3

TIM_TimeBaseInitTypeDef TIM_STR;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//TIM3掛載在APB1上//由于預分頻系數(shù)默認不是1,所以TIM3的時鐘為2*APB1=72MTIM_STR.TIM_Period=arr;TIM_STR.TIM_Prescaler=psc;//(arr+1)*(psc+1)/TIM時鐘=定時器溢出中斷觸發(fā)周期TIM_STR.TIM_ClockDivision=TIM_CKD_DIV1;TIM_STR.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3,&TIM_STR);TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);

2.2 中斷初始化:

中斷初始化為操作NVIC(嵌套向量中斷控制器)函數(shù)。 設置方式如下:

NVIC_STR.NVIC_IRQChannel=TIM3_IRQn;//設定為TIM3中斷NVIC_STR.NVIC_IRQChannelPreemptionPriority=0;//先占優(yōu)先級0級NVIC_STR.NVIC_IRQChannelSubPriority=3;//從優(yōu)先級3級NVIC_STR.NVIC_IRQChannelCmd=ENABLE;//IRQ通道時能NVIC_Init(&NVIC_STR);//中斷初始化TIM_Cmd(TIM3,ENABLE);//TIM3定時器使能

2.3 把這些都封裝成一個函數(shù),既可作為TIM3的初始化函數(shù)。如下:

void TIM3_Init(u16 arr,u16 psc){//定時時間=(arr+1)*(psc+1)/72 單位為usTIM_TimeBaseInitTypeDef TIM_STR;NVIC_InitTypeDef NVIC_STR;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//初始化定時器TIM_STR.TIM_Period=arr;TIM_STR.TIM_Prescaler=psc;TIM_STR.TIM_ClockDivision=TIM_CKD_DIV1;TIM_STR.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3,&TIM_STR);TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//初始化中斷NVIC_STR.NVIC_IRQChannel=TIM3_IRQn;NVIC_STR.NVIC_IRQChannelPreemptionPriority=0;NVIC_STR.NVIC_IRQChannelSubPriority=3;NVIC_STR.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_STR);//使能定時器TIM_Cmd(TIM3,ENABLE);}

③中斷服務函數(shù):

中斷函數(shù)的名字,TIM3的為TIM3_IRQHandler

中斷服務函數(shù)內(nèi)包含了:判斷是否發(fā)生中斷、中斷發(fā)生后執(zhí)行的內(nèi)容、清除標志位三部分。

首先是判斷是否發(fā)生了更新中斷,利用庫函數(shù)TIM_GetITStatus(P1,P2),它的參數(shù)P1為代號,這里是TIM3,P2為中斷類型,這里為更新中斷TIM_IT_Update,當它為1時即發(fā)生了更新中斷,這里為了增強可讀性,采用一個RESET代表0,當函數(shù)返回值不是RESET的時候,即發(fā)生了置位(中斷)。

清除標志位采用的是庫函數(shù)TIM_ClearITPendingBit(P1,P2),參數(shù)與判斷的函數(shù)一樣。

具體函數(shù)如下:

void TIM3_IRQHandler(void){if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET){TIM_ClearITPendingBit(TIM3,TIM_IT_Update);//在這里執(zhí)行中斷內(nèi)容}}

④完成調(diào)用

只要在main函數(shù)里調(diào)用TIM3_Init()函數(shù),并填入適當?shù)膮?shù),即可實現(xiàn)精確的定時中斷,例如獲得一秒,即72M個數(shù)字中斷一次,可分解為10000*7200,配置如下:

TIM3_Init(9999,7199);


評論


技術專區(qū)

關閉