stm32f1系列,有基本定時器、通用定時器、高級定時器三類TIM定時器。其中,TIM6/7是本文要講的基本定時器。
基本定時器TIM6/7是16位的只能向上計數的定時器,只能用於定時。而通用定時器和高級定時器有更多的功能,如還可以進行輸出比較、輸入捕捉等功能,相關的介紹會寫在后面的文章,這里只講基本定時器。
先看看基本定時器的框圖,如圖24-1。

圖24-1
時鍾源
我們查閱參考手冊RCC章節的時鍾樹可以知道,RCC的定時器時鍾TIMxCLK,即內部時鍾CK_INT是由APB1預分頻器分頻后提供。如圖24-2所示,如果APB1預分頻系數為1,,則頻率不變,否則頻率為2倍。即此時用於分頻的APB1的預分頻系數為2,所以TIMxCLK = 36 * 2 = 72MHz。

圖24-2
計數器時鍾
如圖24-1的框圖,計數器時鍾由內部時鍾CK_INT提供,經過PSC預分頻器后得到CK_CNT。PSC是一個16位的預分頻器,可以對定時器時鍾TIMxCLK進行1~65536之間的任何一個數進行分頻。分頻后的CK_CNT值的計算在參考手冊TIMx_PSC寄存器描述里有提到,如圖24-3。

圖24-3
即CK_CNT = CK_PSC/(PSC[15:0]+1)。
計數器
計數器CNT是一個16位的計數器,只能往上計數,最大計數值為65535。
自動重裝載寄存器TIMx_ARR
TIMx_ARR寄存器里存着最大的計數值,當計數到該值時,會產生中斷。當然了你得使能了中斷才可以。
定時時間計算
計一個數的時間是1/CK_CNT,產生一次中斷的時間為(ARR+1)/CK_CNT。如果在中斷服務程序里設置一個變量time用於記錄中斷次數,則定時時間為:(ARR+1)/CK_CNT*time。
TIM_TimeBaseInitTypeDef
如圖24-4為基本定時器TIM_TimeBaseInitTypeDef結構體定義。

圖24-4
TIM_Prescaler:指定定時器預分頻器數值,由TIMx_PSC寄存器配置,可設置范圍為0x0000~0xFFFF,即0~65535;
TIM_CounterMode:計數模式,可分為向上計數、向下計數以及三種中心對齊模式。而基本定時器只能向上計數;
TIM_Period:計數器周期,即自動重裝載寄存器TIMx_ARR的值,在事件生成時更新到影子寄存器,由TIMx_CR1寄存器的ARPE位配置是否使能緩沖;
TIM_ClockDivision:時鍾分頻,配置定時器時鍾CK_INT頻率與數字濾波器采樣時鍾頻率分頻比,基本定時器沒有這個功能,不用設置;
TIM_RepetitionCounter:重復計數器,屬於高級控制寄存器專用寄存器位,利用它可以很容易控制輸出PWM個數,這里不用設置。
定時1s實驗
例如,需要做一個1s的定時,CK_PSC=72MHz,則PSC=71,那么CK_CNT=1MHz,
計一個數時間:1/CK_CNT = 1/1MHz = 1us,
中斷一次的時間:(ARR+1)/CK_CNT = (999+1)/1MHz = 1ms,
則定時時間:(ARR+1)/CK_CNT*time = 1ms*1000 = 1s
我們用led的亮滅狀態變化來展示1s的定時。
初始化TIM_TimeBaseInitTypeDef
前文提到的TIM_TimeBaseInitTypeDef結構體有5個成員,但基本定時器TIM6/7只用到了TIM_Prescaler和TIM_Period這兩個成員,其他三個是通用定時器和高級定時器才會用到的。
/** * @brief 基本定時器配置 * @param 無 * @retval 無 */ static void BASIC_TIM_Mode_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); // 內部時鍾72MHz TIM_TimeBaseStructure.TIM_Period = 999; // 自動重裝載寄存器的值 TIM_TimeBaseStructure.TIM_Prescaler= 71; // 預分頻器數值 TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); TIM_ClearFlag(TIM6, TIM_FLAG_Update); // 清除計數器中斷標志位 TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); TIM_Cmd(TIM6, ENABLE); }
中斷優先級配置
有關中斷配置相關已經在之前的文章介紹過,有不清楚的地方可移步閱讀。這里只說幾個配置的關鍵點。可配置中斷優先級分組為0,即0位搶占優先級,4位子優先級。配置中斷源為TIM6_IRQn。
/** * @brief 中斷優先級配置 * @param 無 * @retval 無 */ static void BASIC_TIM_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
中斷函數
中斷函數在stm32f10x_it.c文件里配置。
extern volatile uint32_t time; // 該變量定義在main()函數里 void TIM6_IRQHandler(void) { if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) { time++; // 每中斷一次,time值加1,中斷一次時間為1ms,需要中斷1000次才可定時1s,即time值為1000 TIM_ClearITPendingBit(TIM6, TIM_FLAG_Update); } }
最后在main()函數里調用led和定時器的初始化配置函數,在一個循環里判斷time變量的值是否為1000,如果已經達到1000,則led燈狀態變化(亮或滅)一次,並且time變量值重賦為0,以便繼續判斷及定時。
最后給大家分享些smt32方面的資料便於學習參考
(STM32中斷系統)
http://www.makeru.com.cn/live/1392_1124.html?s=45051
(定時器)
http://www.makeru.com.cn/live/1392_1199.html?s=45051
基於STM32-WiFi智能小車機器人開發實戰
http://www.makeru.com.cn/course/details/3008?s=45051