x1/x2 /N(預分頻) APB1時鍾------->F(CK_PSC)--------------->CK_CNT 如果APB1的分頻系數為1, CK_INT的倍頻系數就是x1 如果APB1的分頻系數不為1, CK_INT的倍頻系數就是x2
|
|
|||||
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
從 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 反轉 }
#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); } }