stm32之TIM-基本定時器應用實例(詳細)

  • 開發環境:Window 7
  • 開發工具:Keil uVision4
  • 硬件:STM32F103VCT6

定時器最基本的功能就是定時處理事情。比如定時發送USART數據、定時採集AD數據、定時檢測IO口電位、還可以通過IO口輸出波形等。可以實現非常豐富的功能。

STM32系列的定時器分爲基本定時器、通用定時器、高級控制定時器。後者包括前者的全部功能。所以先掌握基本定時器可以更好理解後面功能繁多的定時器。

通常地,STM32高級定時器TIM1、TIM8,通用定時器TIM2、TIM3、TIM4、TIM5,基本定時器TIM6、TIM7。

有用過STM32的話都知道,STM32所有的外設初始化都是使用標準庫裏的初始化結構體和初始化函數,下面先說一下IM_TimeBaseInitTypeDef structure 結構體成員的含義。

TIM_TimeBaseInitTypeDef 定義於文件“stm32f10x_tim.h”:

typedef struct 
{ 
u16 TIM_Period; 
u16 TIM_Prescaler; 
u8 TIM_ClockDivision; 
u16 TIM_CounterMode; 
u8 TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
  1. TIM_Period:定時器週期,當計數寄存器的值遞增到等於該值時,將相關事件標誌位置位。範圍0~65535。
  2. TIM_Prescaler:定時器預分頻設置。時鐘源經該預分頻器纔是定時器時鐘。範圍0~65535。
  3. TIM_ClockDivision:時鐘分頻。基本定時器沒有這個功能,無需設置。
  4. TIM_CounterMode:定時器計數方式設置。基本定時器只能向上計數,無需設置。
  5. TIM_RepetitionCounter :重複計數器,基本定時器沒有這個功能,無需設置。

雖然定時器初始化結構體有5個成員,但是對於基本定時器只需設置其中兩個就可以了。下面是一個定時0.5s翻轉IO口電平的例子。

循環定時時間的計算:基本定時器只有內部時鐘72MHz,定時器的實際時鐘=內部時鐘/(定時器預分頻+1),那麼TIM_Prescaler設置爲7200-1,內部時鐘源經過定時器預分頻後即可得到10kHz(72MHz/((7200-1)+1))的頻率。然後TIM_Period設置爲5000-1,(這裏因爲計數是從0開始的,所以要減1),即可以得到定時爲0.5s(5000*(1/10kHz))的定時器。代碼如下:

創建一個TIME_base.h

#ifndef __TIMER_BASE_H
#define __TIMER_BASE_H
#include "stm32f10x.h"
    void TIME_NVIC_Configuration(void);
    void TIME_Configuration(void);
    void GPIO_Config(void);
#endif

創建一個TIME_base.c

#include "TIME_base.h"
void TIME_NVIC_Configuration(void)//如果系統會產生多種中斷,那麼就存在中斷響應的優先級
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);           //設置優先級分組
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;           //指定IRQ通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //指定先佔優先級
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //從優先級
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //定義的IRQ是被使能還是失能
    NVIC_Init(&NVIC_InitStructure);  
}

void TIME_Configuration(void)//配置TIM6
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); 
    TIM_TimeBaseStructure.TIM_Period = 5000; //設置了在下一個更新事件裝入活動的自動重裝載寄存器週期的值 範圍是0x0000-0xFFFF
    TIM_TimeBaseStructure.TIM_Prescaler =(7200-1); //設置了用來作爲 TIMx 時鐘頻率除數的預分頻值
    TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); 
    TIM_ITConfig(TIM6,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//使能或者失能 TIM 的中斷,詳見附錄圖1
    TIM_Cmd(TIM6, ENABLE);  
}

void GPIO_Config(void)//配置一個IO口:
{		
    /*定義一個GPIO_InitTypeDef類型的結構體*/
     GPIO_InitTypeDef GPIO_InitStructure;
    /*開啓GPIOB的外設時鐘*/
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    /*選擇要控制的GPIOB引腳*/	   
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	
    /*設置引腳模式爲通用推輓輸出*/
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    /*設置引腳速率爲50MHz */   
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    /*調用庫函數,初始化GPIOB*/
     GPIO_Init(GPIOB, &GPIO_InitStructure);
    /*PB.0 輸出高*/
     GPIO_SetBits(GPIOB,GPIO_Pin_0);   
}

附錄圖1:

在stm32f10x_it.c添加定時器觸發的中斷處理函數:

void TIM6_IRQHandler(void)   
{
    if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)  //獲取中斷狀態
    {
        TIM_ClearITPendingBit(TIM6, TIM_IT_Update  );  //清除中斷標誌
        //在這裏做中斷需要處理的事情,儘可能精簡,避免過長時間停留在中斷裏面
        GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)(1-(GPIO_ReadOutputDataBit(GPIOB,  GPIO_Pin_0))));
    }

}

創建一個main.c

#include "TIME_base.h"
int main(void)
{	  
    /* IO端口配置 */ 
    GPIO_Config();	
    /* TIM6 定時配置 */
    TIME_NVIC_Configuration();
    TIME_Configuration();
    while(1){
    }
}

將上面的TIM6全部換成TIM7也是可以的。

然後就可以把編譯好的程序下載到開發板了,可以在PB.0引腳處接一個led,那麼led就會每0.5s閃爍一次。

水平有限,僅供參考,錯誤以及不足之處還望多多指教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章