沒簽合同網站做不好百度極簡網址
文章目錄
- 1、TIM定時器
- 1.1定時器類型
- 1.2定時中斷的基本結構
- 2 定時器初始化
- 2.2 初始化定時器的步驟
- 2.3 TIM庫函數
- 2.4 配置TIM
- 2.4.1 Timer.c
- 2.4.2 Timer.c
- 2.4.3 main.c
1、TIM定時器
定時器的功能可以對輸入的時鐘進行計數,并在計數值達到設定值時觸發(fā)中斷。
- 他包含16位計數器(CNT)、預分頻器(PSC)、自動重裝寄存器(ARR)的時基單元,在72MHz計數時鐘下可以實現最大59.65s的定時。
- 不僅具備基本的定時中斷功能,而且還包含內外時鐘源選擇、輸入捕獲、輸出比較、編碼器接口、主從觸發(fā)模式等多種功能。
- 根據復雜度和應用場景分為了高級定時器、通用定時器、基本定時器三種類型。
計數器(CNT):用來執(zhí)行計數定時的一個寄存器,每來一個時鐘,計數器加1;
預分頻器(PSC):對計數器的時鐘進行分頻,使奇數更加靈活;
自動重裝寄存器(RCC):使計數值的目標值,也就是想要多少個時鐘申請中斷。
1.1定時器類型
- STM32F103C8T6定時器資源有:TIM1、TIM2、TIM3、TIM4
基本定時器從基準時鐘,到預分頻器,再到計數器,計數器計數自增,同時不斷地與自動重裝寄存器進行比較;他們相等時,即計時時間到,這時會產生一個更新中斷和中斷事件,CPU響應更新中斷,最后完成定時中斷的任務?;径〞r器僅支持向上計數這一模式。
通用定時器和高級定時器不僅支持向上計數模式,還支持向下計數模式和中央對齊模式。
STM32定時器的一大特色,就是主從觸發(fā)模式DAC的功能,他能讓硬件在不受程序的控制下實現自動運行。如果運用得當,在某些情景下可以極大的減輕CPU的負擔。
1.2定時中斷的基本結構
定時中斷和內外時鐘源選擇所涉及的結構如下圖所示:
PSC、CNT和ARR三個部分構成了時基單元;下面是運行控制,控制寄存器的一些位,比如啟動停止、向上或向下計數等等,操作這些寄存器就能控制時基單元的運行了。
左邊是為時基單元提供時鐘的部分;右邊是計時時間到,產生新更新中斷后的信號去向。如果是高級定時器,在右邊部分還會多一個重復計數器。
2 定時器初始化
我們通過定時中斷的整個框架結構圖,將圖中的每個模塊都打通,就能讓定時器工作了。
2.2 初始化定時器的步驟
這里以初始化TIM2定時器為例:
1.RCC開啟時鐘,TM2是APB1總線的外設,所以要使用APB1的開啟時鐘函數;
2.選擇時基單元的時鐘源,對于定時中斷,我們就選擇內部時鐘源;
3.配置時基單元,包括其中的PSC、ARR、CNT等等;
4.配置輸出中斷控制,允許更新中斷輸出到NVIC;
5.配置NVIC,在NVIC中打開定時器中斷的通道,并分配一個優(yōu)先級;
6.運行控制,整個模塊配置完成后,需要使能一下計數器;當定時器使能后,計數器就會開始計數,當計數器更新時,觸發(fā)中斷;最后寫一個定時器的中斷函數,這樣這個中斷函數每隔一段時間就能自動執(zhí)行一次了。
2.3 TIM庫函數
下面我們來介紹一部分與TIM有關的庫函數:
1.TIM_DeInit,恢復缺省配置。
2.TIM_TimeBaseInit,時基單元初始化,有兩個參數,第一個TIMx選擇某個定時器,第二個是結構體,包含了配置時基單元的一些參數。
3.TIM_TimeBaseStructInit,可以把結構體賦一個默認值。
4.TIM_Cmd,使能計數器,2個參數,第一個TIMx選擇定時器;第二個NewState新的狀態(tài),也就是選擇使能或者失能。
5.TIM_ITConfig,用來使能輸出信號,3個參數,第一個TIMx,選擇定時器;第二個TIM_IT,選擇配置哪個中斷輸出;第三個NewState,新的狀態(tài)選擇使能還是失能。
6.TIM_InternalClockConfig,選擇內部時鐘。
7.TIM_ITRxExternalClockConfig,選擇TIMx其他定時器的時鐘,第一個參數選擇要配置的定時器;第二個參數選擇要接入哪個其他的定時器。
8.TIM_TIxExternalClockConfig,選擇TIx捕獲通道的時鐘,4個參數,第一個參數TIMx;第二個參數選擇TIx的某個引腳;第三個參數,選擇輸入的極性;第四個參數,選擇濾波器。
9.TIM_ETRClockMode1Config,選擇ETR通過外部時鐘模式1輸入的時鐘,4個參數,第一個參數TIMx;第二個參數外部觸發(fā)預分頻器,這里可以對ETR的外部時鐘再提前做一個分頻;第三、四個參數分別是選擇極性和濾波器。
10.TIM_ETRClockMode2Config,選擇ETR通過外部時鐘模式2輸入的時鐘,參數與上面一樣。
11.TIM_ETRConfig,單獨用來配置ETR引腳的預分頻器、極性、濾波器等參數。
總結:
1、第6-11個函數,總共6個函數,對應的是時基單元的時鐘選擇部分,可選擇RCC內部時鐘、ETR外部時鐘、ITRx其他定時器、ITx捕獲通道等。
2、第9-10個函數,總共2個函數,對于ETR外部時鐘而言,這兩個函數是等效的,參數也是一樣的;若不需要觸發(fā)輸入的功能,那么這兩個函數原則上是可以互換的。
12.TIM_PrescalerConfig,單獨寫預分頻的值,第二個參數就是要寫入預分頻的值;第三個參數是選擇寫入的模式。預分頻器有一個緩沖器,寫入的值是在更新事件發(fā)生后才有效的,所以這里有個寫入模式,可以選擇聽從安排在更新事件生效;或是在寫入后,手動產生一個更新事件,讓這個值立刻生效。
13.TIM_CounterModeConfig,用來改變計數器的計數模式,第二個參數用來選擇新的計數器模式。
14.TIM_ARRPreloadConfig,自動重裝器預裝功能配置。
15.TIM_SetCounter,給計數器寫入一個值。
16.TIM_SetAutoreload,給自動重裝器寫入一個值。
17.uint16_t TIM_GetCounter,獲取當前計數器的值,他的返回值就是當前計數器的值。
18.uint16_t TIM_GetPrescaler,獲取當前預分頻器的值。
19.FlagStatus TIM_GetFlagStatus
20.TIM_ClearFlag,主要用于清除定時器的中斷標志位。
21.ITStatus TIM_GetITStatus
22.TIM_ClearITPendingBit,主要用于清除中斷線路的中斷掛起位。
這4個函數是用來獲取標志位和清除標志位。
2.4 配置TIM
我們定一個時間,讓定時器每隔一個時間產生中斷,來實現每隔一個固定時間執(zhí)行一段程序,如下:
2.4.1 Timer.c
#include "stm32f10x.h" void Timer_Init(void)
{
//1.開啟時鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//2.選擇時基單元的時鐘(定時器上電后默認就是使用內部時鐘,若不調用這個函數,那也是使用的內部時鐘) TIM_InternalClockConfig(TIM2);//選擇內部時鐘
//3.配置時基單元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//選擇1分頻TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//選擇向上計數模式//若想定時1s,定時頻率=72M/(PSC+1)/(ARR+1),預分頻器和計數器都有1個數的偏差,所以要-1TIM_TimeBaseInitStructure.TIM_Period=10000-1;//ARR自動重裝的值TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//預分頻器的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重復計數器,是高級定時器才有的TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);TIM_ClearFlag(TIM2,TIM_FLAG_Update);//手動把更新中斷標志位清除一下,避免剛初始化完就進入中斷//4.使能更新中斷TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
//5.配置NVIC NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//優(yōu)先級分組NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//選擇定時器TIM2在NVIC里的通道NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//搶占優(yōu)先級NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//響應優(yōu)先級NVIC_Init(&NVIC_InitStructure);
//6.啟動定時器TIM_Cmd(TIM2,ENABLE);
}
2.4.2 Timer.c
#ifndef __TIMER_H_
#define __TIMER_H_void Timer_Init(void);#endif
2.4.3 main.c
#include "stm32f10x.h" // Device header
#include "TIMER.H"uint16_t Num;
int main(void)
{OLED_Init();Timer_Init();OLED_ShowString(1,1,"Num:");while(1){OLED_ShowNum(1,5,Num,5);}
}void TIM2_IRQHandler(void)//定時器2的中斷函數
{if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//檢查中斷標志位{Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除標志位}
}