STM32定時(shí)器定時(shí)中斷學(xué)習(xí)打卡(代碼注釋)
main.c
#include "stm32f10x.h"? ? ? ? ? ? ? ? ? // Device header
#include "Delay.h"
#include "OLED.h"
#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)
//{
// if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
// {
// Num ++;
// TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// }
//}
Timer.c
#include "stm32f10x.h"? ? ? ? ? ? ? ? ? // Device header
extern uint16_t Num;//使用extern聲明主函數(shù)的Num變量,可在本程序中直接使用Num變量
/*定時(shí)中斷基本結(jié)構(gòu)
第一步:RCC開啟時(shí)鐘
第二步:選擇時(shí)基單元的時(shí)鐘源(對于定時(shí)中斷選擇內(nèi)部時(shí)鐘源)
第三步:配置時(shí)基單元(包括預(yù)分頻器、自動(dòng)重裝器、技術(shù)模式等)
第四步:配置輸出中斷控制,允許更新中斷輸出到NVIC
第五步:配置NVIC,在NVIC中打開定時(shí)器中斷的通道,并分配一個(gè)優(yōu)先級
第六步:運(yùn)行控制
整個(gè)模塊配置好后還需要使能一下計(jì)數(shù)器
定時(shí)器使能后,計(jì)數(shù)器開始計(jì)數(shù),當(dāng)計(jì)數(shù)器更新時(shí),觸發(fā)中斷
最后寫中斷函數(shù),該函數(shù)每隔一定時(shí)間自動(dòng)執(zhí)行一次*/
/*本程序采用TIM2,即通用計(jì)時(shí)器*/
void Timer_Init(void)
{
//第一步,RCC開啟時(shí)鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//開啟時(shí)鐘
//這里注意需要使用APB1開啟時(shí)鐘(TIM2(通用時(shí)鐘)是APB1總線的外設(shè))
//第二步,選擇時(shí)基單元的時(shí)鐘源(對于定時(shí)中斷選擇內(nèi)部時(shí)鐘源)
TIM_InternalClockConfig(TIM2);//選擇內(nèi)部時(shí)鐘,TIM2的時(shí)基單元由內(nèi)部時(shí)鐘驅(qū)動(dòng)
//第三步,配置時(shí)基單元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定義結(jié)構(gòu)體變量
//引出各個(gè)變量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上計(jì)數(shù)的模式
//溢出頻率=72M/(PSC+1)/(ARR+1)
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//周期設(shè)定(ARR,自動(dòng)重裝器的值)
//計(jì)10000個(gè)數(shù),ARR從0自增到9999
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC,預(yù)分頻器的值
//對72MHz進(jìn)行7200分頻,得到10K的計(jì)數(shù)頻率,在10K的頻率下計(jì)10000個(gè)數(shù),即1秒
//預(yù)分頻器和計(jì)數(shù)器都有一個(gè)數(shù)的偏差,故減1
//注意:PSC和ARR的取值應(yīng)當(dāng)在0~65535之間,不要超出范圍
//PSC和ARR的取值不唯一
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重復(fù)計(jì)數(shù)器的值,在高級定時(shí)器中才需要
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
//第四步:配置輸出中斷控制,允許更新中斷輸出到NVIC
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//防止復(fù)位后(按下復(fù)位鍵)
//立即自動(dòng)執(zhí)行一次中斷(初始化完就進(jìn)行更新中斷)
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能中斷
//第五步:配置NVIC,在NVIC中打開定時(shí)器中斷的通道,并分配一個(gè)優(yōu)先級
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC優(yōu)先級分組
NVIC_InitTypeDef NVIC_InitStructure;//結(jié)構(gòu)體變量定義
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//中斷通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//搶占優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//響應(yīng)優(yōu)先級
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);//啟動(dòng)定時(shí)器
}
/*
中斷函數(shù):
當(dāng)定時(shí)器產(chǎn)生更新中斷時(shí),此函數(shù)會(huì)自動(dòng)進(jìn)行*/
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//獲取中斷標(biāo)志位,檢查中斷標(biāo)志位
{
Num++;//此處采用的方法是使用extern將主函數(shù)的變量Num聲明后使用,
//也可以將本中斷函數(shù)置于主函數(shù)main.c中
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中斷標(biāo)志位
}
}
/*
相關(guān)函數(shù):
TIM_DeInit()函數(shù):恢復(fù)缺省設(shè)置
TIM_TimeBaseInit()函數(shù):時(shí)基單元初始化
TIM_TimeBaseStrructInit()函數(shù):把結(jié)構(gòu)體變量賦一個(gè)默認(rèn)值
TIM_Cmd()函數(shù):使能計(jì)數(shù)器(運(yùn)行控制)
TIM_ITConfig()函數(shù):使能外設(shè)中斷輸出信號(hào)(中斷輸出控制)
TIM_InternalClockConfig()函數(shù):選擇內(nèi)部時(shí)鐘
TIM_ITRxExternalClockConfig()函數(shù):選擇ITRx其他定時(shí)器的時(shí)鐘,選擇要配置的定時(shí)器
InputTriggerSource()函數(shù):選擇要接入哪個(gè)其他的定時(shí)器
TIM_TIxExternalClockConfig()函數(shù):選擇TIx捕獲通道的時(shí)鐘
TIM_ETRClockMode1Config()函數(shù):選擇ETR通過外部時(shí)鐘模式1輸入的時(shí)鐘
TIM_ETRClockMode2Config()函數(shù):選擇ETR通過外部時(shí)鐘模式2輸入的時(shí)鐘
TIM_ETRConfig()函數(shù):單獨(dú)用來配置ETR引腳的預(yù)分頻器、極性、濾波器的參數(shù)
初始化結(jié)構(gòu)體內(nèi)有關(guān)參數(shù),比如自動(dòng)重裝值和預(yù)分頻值等,
為了在初始化后更改需要,而不必再次初始化函數(shù),故使用一些單獨(dú)的函數(shù)方便地更改關(guān)鍵參數(shù)
TIM_PrescalerConfig()函數(shù),用于單獨(dú)寫預(yù)分頻值
TIM_CounterModeConfig()函數(shù),用來改變計(jì)數(shù)器的計(jì)數(shù)模式
TIM_ARRPreloadConfig()函數(shù),用于自動(dòng)重裝器預(yù)裝功能配置
TIM_SetCounter()函數(shù),給計(jì)數(shù)器寫入一個(gè)值
TIM_SetAutoreload()函數(shù),給自動(dòng)重裝器寫入一個(gè)值
TIM_GetCounter()函數(shù),獲取當(dāng)前計(jì)數(shù)器的值
TIM_GetPrescaler()函數(shù),獲取當(dāng)前的預(yù)分頻器的值
*/
Timer.h
#ifndef __TIMER_H
#define __TIMER_H
void Timer_Init(void);
#endif