STM32 Timer (2) 定時器中斷代碼框架


3. 代碼框架

3.1 分頻系數的計算

         x1/x2                /N(預分頻) APB1時鍾------->F(CK_PSC)--------------->CK_CNT 如果APB1的分頻系數為1, CK_INT的倍頻系數就是x1 如果APB1的分頻系數不為1, CK_INT的倍頻系數就是x2
 
STM32F1(MHz)

STM32F4(MHz)

STM32F7(MHz)
SYSCLK 72 168 216
AHB 72 168 216
APB1 (AHB/4) 18 42 54
CK_INT(x1/x2) 36 84 108
PSC預分頻      

 

舉例:實現 0.5s 的led閃爍
當前使用F7 所以 

CK_INT = 108MHz
PSC預分頻:Prescaler
自動重裝載寄存器: Period

time =  (Period)(Prescaler)/CK_INT

0.5 = (Period)(Prescaler)/108000000

預分頻 Prescaler 方便計算 設置為 108000(整除),
自動重裝載 Period 設置為 500
計算: 500*108000/108000000 = 0.5

但是,因為受到16位寄存器的約束, 108000 超過的65535(2的16次方)
所以稍微調整:
5000 * 10800 同樣滿足要求。 

所以配置:
Prescaler = 10800
Period = 5000


根據定時需求調整
time =  (Period)(Prescaler)/CK_INT

 

3.2 代碼細講

int main()
{
    
}開始了解定時器的實現
// 1.使能定時器時鍾
__HAL_RCC_TIM3_CLK_ENABLE();

//2. 初始話定時器,配置Prescaler,Period
HAL_TIM_Base_Init();

// 3. 開啟定時器/中斷
HAL_TIM_Base_Start();
HAL_TIM_Base_Start_IT();

// 4. 設置中斷優先級
HAL_NVIC_SetPriority(); HAL_NVIC_EnableIRQ();

// 5. 編寫中斷服務函數
TIMx_IRQHandler();    //中斷服務函數
HAL_TIM_IRQHandler(); //中斷處理入口函數
HAL_TIM_PeriodElapsedCallback();//定時器更新中斷回調函數
//正式開始
// 1. 自定義一個TIM初始化函數
void TIM3_Init()
{
    //...
    
}

int main()
{
    TIM3_Init();
}
//Tim3_Init()做些什么事?
void TIM3_Init()
{
    //1. 定時器初始化函數
    HAL_TIM_Base_Init(); //需要一個參數
}

//函數原型: HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
//所以設置TIM句柄 
TIM_HandleTypeDef htim3;

//設置了句柄,就要對其中的參數進行初始化
htim3.Instance = TIM3;
htim3.Init.Prescaler = 10800-1;                     //預分頻系數
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;        //計數模式
htim3.Init.Period = 5000-1;                         //自動裝載值
//結果:
    
TIM_HandleTypeDef htim3;
void TIM3_Init()
{
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 10800-1;                     //預分頻系數
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;        //計數模式
    htim3.Init.Period = 5000-1;                         //自動裝載值
    HAL_TIM_Base_Init(htim3);
}
//2. 然后嘞就要使能時鍾定時器
//在HAL_TIM_Base_Init(htim3) 函數中有:
HAL_TIM_Base_MspInit(htim);

//這個函數Msp 表示回調函數, 一般在文件stm32f4xx_hal_msp.c文件中,如果沒有,自己實現也是一樣
// 這個函數主要實現 時鍾的開啟, GPIO的配置, 中斷優先級的配置
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
    if(htim_base->Instance==TIM3)
    {
        __HAL_RCC_TIM3_CLK_ENABLE();    
    }
}

//因為HAL_TIM_Base_Init 這個函數不僅僅針對與TIM3, 所以在Msp函數中, 要進行if判斷
htim_base->Instance==TIM3
//在這個函數中, 進行 TIM時鍾的開啟  
__HAL_RCC_TIM3_CLK_ENABLE();
// 3.開啟Tim3且中斷
void TIM3_Init()
{
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 10800-1;                     //預分頻系數
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;        //計數模式
    htim3.Init.Period = 5000-1;                         //自動裝載值
    HAL_TIM_Base_Init(htim3);
    
    //new
    HAL_TIM_Base_Start_IT(&htim3);                         //開啟定時器中斷
}
//4 .開啟了中斷后,就要設置中斷優先級
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
    if(htim_base->Instance==TIM3)
    {
        __HAL_RCC_TIM3_CLK_ENABLE();
 
        //中斷優先級
        HAL_NVIC_EnableIRQ(TIM3_IRQn);
        HAL_NVIC_SetPriority(TIM3_IRQn,1,3);
    
    }
}

 

// 5. 編寫中斷服務函數
//在start.s文件中,有中斷觸發函數列表,查找之。
void TIM3_IRQHandler(void)
{
    //待編寫
}
//寫什么呢,TIM的api中,有中斷觸發函數
HAL_TIM_IRQHandler(&htim3);

--->
void TIM3_IRQHandler(void)
{
   HAL_TIM_IRQHandler(&htim3);
} 

//繼續跟蹤  HAL_TIM_IRQHandler(&htim3);
 /* TIM Update event */
  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET)
  {
    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET)
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->PeriodElapsedCallback(htim);
#else
      HAL_TIM_PeriodElapsedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }

//有各種各樣的中斷,這里實現更新中斷, 調用了 HAL_TIM_PeriodElapsedCallback(htim);
//所以重寫回調函數HAL_TIM_PeriodElapsedCallback(htim);
//time更新回調函數
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    //LED 反轉
}

 

3.3 全代碼

其中LED的初始化基於RT-thread, 若非RTOS自行替換,跟框架無關。

main.c

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>


#define LED0    GET_PIN(B,0)
#define LED1    GET_PIN(B,1)

static rt_uint8_t flag = 0;
TIM_HandleTypeDef htim3;
void TIM3_Init()
{
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 10800-1;                    //預分頻系數
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;        //計數模式
    htim3.Init.Period = 5000-1;                         //自動裝載值
    
    HAL_TIM_Base_Init(&htim3);
    
    HAL_TIM_Base_Start_IT(&htim3);                      //開啟tim3中斷
    
    //因為開啟了中斷,所以要設置中斷優先級
    //本來要自己實現中斷函數HAL_TIM_Base_MspInit 的,但是在
    //stm32f7xx_hal_msp.c文件中已經寫了,所以去這個文件編寫中斷優先級
}
//中斷配置后,實現中斷服務函數
//中斷服務函數
void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim3);
}

//time更新回調函數
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(flag == 0)
    {
        rt_pin_write(LED0,PIN_LOW);
        flag = 1;
        return;
    }
    
    if(flag == 1)
    {
        rt_pin_write(LED0,PIN_HIGH);
        flag = 0;
        return;
    }
}

void LED_Init(void)
{
    rt_pin_mode(LED0,PIN_MODE_OUTPUT);  
}

int main(void)
{
    LED_Init();
    TIM3_Init();

    return 0;
}

 

htm32f7xx_hal_msp.c

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
    if(htim_base->Instance==TIM3)
    {
        __HAL_RCC_TIM3_CLK_ENABLE();
 
        //中斷優先級
        HAL_NVIC_EnableIRQ(TIM3_IRQn);
        HAL_NVIC_SetPriority(TIM3_IRQn,1,3);
    
    }
 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM