stm32f1系列,有基本定時器、通用定時器、高級定時器三類TIM定時器。其中,TIM6/7是本文要講的基本定時器。react
基本定時器TIM6/7是16位的只能向上計數的定時器,只能用於定時。而通用定時器和高級定時器有更多的功能,如還能夠進行輸出比較、輸入捕捉等功能,相關的介紹會寫在後面的文章,這裏只講基本定時器。函數
先看看基本定時器的框圖,如圖24-1。ui
圖24-1spa
咱們查閱參考手冊RCC章節的時鐘樹能夠知道,RCC的定時器時鐘TIMxCLK,即內部時鐘CK_INT是由APB1預分頻器分頻後提供。如圖24-2所示,若是APB1預分頻係數爲1,,則頻率不變,不然頻率爲2倍。即此時用於分頻的APB1的預分頻係數爲2,因此TIMxCLK = 36 * 2 = 72MHz。3d
圖24-2code
如圖24-1的框圖,計數器時鐘由內部時鐘CK_INT提供,通過PSC預分頻器後獲得CK_CNT。PSC是一個16位的預分頻器,能夠對定時器時鐘TIMxCLK進行1~65536之間的任何一個數進行分頻。分頻後的CK_CNT值的計算在參考手冊TIMx_PSC寄存器描述裏有提到,如圖24-3。blog
圖24-3事件
即CK_CNT = CK_PSC/(PSC[15:0]+1)。ip
計數器CNT是一個16位的計數器,只能往上計數,最大計數值爲65535。get
TIMx_ARR寄存器裏存着最大的計數值,當計數到該值時,會產生中斷。固然了你得使能了中斷才能夠。
計一個數的時間是1/CK_CNT,產生一次中斷的時間爲(ARR+1)/CK_CNT。若是在中斷服務程序裏設置一個變量time用於記錄中斷次數,則定時時間爲:(ARR+1)/CK_CNT*time。
如圖24-4爲基本定時器TIM_TimeBaseInitTypeDef結構體定義。
圖24-4
例如,須要作一個1s的定時,CK_PSC=72MHz,則PSC=71,那麼CK_CNT=1MHz,
咱們用led的亮滅狀態變化來展現1s的定時。
前文提到的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,以便繼續判斷及定時。