飛書文檔https://x509p6c8to.feishu.cn/wiki/A749wx8T0ioqfgkzZKlc9poknUf
SMT32F1系列共有8個定時器:
- 基本定時器(TIM6、TIM7)
- 通用定時器(TIM2、TIM3、TIM4、TIM5)
- 高級定時器(TIM1、TIM8)
高級定時器(TIM1,TIM8)的主要功能:
通用定時器(TIM2~TIM5)的主要功能:
基本定時器功能(TIM6、TIM7):
功能對比
定時器種類 | 位數 | 計數器模式 | 捕獲/比較通道 | 互補輸出 | 特殊應用場景 |
高級定時器 | 16 | 向上,向下,中心對齊 | 4 | 有 | 定時計數,DAC/ADC時鐘、PWM輸出,輸入捕獲,輸出比較,帶可編程死區的互補輸出 |
通用定時器 | 16 | 向上,向下,中心對齊 | 4 | 無 | 定時計數,DAC/ADC時鐘、PWM輸出,輸入捕獲,輸出比較 |
基本定時器 | 16 | 向上 | 0 | 無 | 定時計數,DAC時鐘 |
基本定時器框圖說明
基礎定時器只有定時功能,使用基礎定時器進行定時的工作流程如下: |
定時器配置的一些參數
雖然有3類定時器但,不管怎樣,只要是配置作為定時器,那么便總是與基本定時器是類似的。
在下文配置的時候要注意:我們配置的是進入定時器中斷的頻率,然后要定的時間要跟據這個頻率來定時的。
Prescaler(PSC): 定時器預分頻設置,16位,設置 0~65535 以達到 1 至 65536 的分頻。
Counter Mode : 定時器的計數方式,基本定時器只能向上(UP)計數
定時器有如下3種計數模式:
|
Counter Period : 定時器周期,16位,設置 0~65535 以達到 1 至 65536 的周期。每當定時器達到 設定值時,置位。
InternalCLock Division(CKD): 內部時鐘分頻因子,指設置定時器時鐘頻率與數字濾波器使用的采樣頻率之間的分頻比例的(與輸入捕獲相關)。
Auto-reload preload :自動重載。一般每次觸發以后需要重新填充。
Disable:自動重裝載寄存器寫入新值后,計數器立即產生計數溢出,然后開始新的計數周期
Enable:自動重裝載寄存器寫入新值后,計數器完成當前舊的計數后,再開始新的計數周期
Trigger Output Parameters : 觸發輸出 (TRGO) ,當定時器的定時時間到達的時候輸出一個信號(如:定時器更新產生TRGO信號來觸發ADC的同步轉換)
Repetition Counter:重復計數器(RCR -8 bits),屬于高級控制寄存器專用寄存器位,利用它可以非常容易控制輸出 PWM 的個數。
Master/Slave Mode(MSM bit) :主從模式
定時器一般是通過軟件設置而啟動,STM32的每個定時器也可以通過外部信號觸發而啟動,還可以通過另外一個定時器的某一個條件被觸發而啟動。這里所謂某一個條件可以是定時到時間、定時器超時、比較成功等許多條件。 這種通過一個定時器觸發另一個定時器的工作方式稱為定時器的同步,發出觸發信號的定時器工作于主模式,接受觸發信號而啟動的定時器工作于從模式。 定時器的四種主從機模式:外部觸發模式1、IRC重置模式、門控模式、觸發模式。 |
基本定時器的使用:
創建工程,設置SWD調試,HSE時鐘,系統時鐘為72MHz
然后打開Timers配置TIM6,設置為Activated激活定時器
Activated: |
?
然后如何設置定時器的定時時間呢?首先我們要知道定時器的時鐘來自哪里?
從芯片手冊的時鐘樹中可以知道,STM32F103定時器的時鐘源:
TIM1、TIM8:來自APB2總線上的TIMxCLK
TIM2到TIM7:來自APB1總線上的TIMxCLK
所以TIM6的APB1時鐘是72MHz。
Counter Setting:計數設置 |
如果想要使其50ms觸發一次定時中斷,可以把72MHz通過7200分頻后,使其速度降為10KHz,也就意味著每計數10次需要1ms,那么50ms就需要計數500次。因為是從0為第一位開始計數,所以參數都需要減一。
72000000Hz/7200 = 10000Hz = 10KHz = 1s 10000次 = 1ms 10次
也可以通過公式計算 |
然后設置定時器中斷
關于中斷優先級,在實際工程項目中,根據具體業務需要,當中斷過多時,才需要設置中斷優先級,測試工程無需設置。
同時,為了方便查看效果,添加LPA6為LED1
點擊生成代碼
main.c
void MX_TIM6_Init(void)
{TIM_MasterConfigTypeDef sMasterConfig = {0};htim6.Instance = TIM6;htim6.Init.Prescaler = 7200-1;htim6.Init.CounterMode = TIM_COUNTERMODE_UP;htim6.Init.Period = 500-1;htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_Base_Init(&htim6) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK){Error_Handler();}
}stm32f1xx_it.c
/*** @brief This function handles TIM6 global interrupt.*/
void TIM6_IRQHandler(void)
{HAL_TIM_IRQHandler(&htim6);
}進入HAL_TIM_IRQHandler(&htim6)函數,這里面的代碼很長,就是不同的中斷類型,進入不同的中斷回調函數,這里找到HAL_TIM_PeriodElapsedCallback(htim);
進入這個回調函數,我們看到是個虛函數,需要我們重寫,在main.c中添加。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){??if(htim == &htim6)? //判斷中斷是否來自于定時器6{//do something//例如:HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);? //翻轉LED燈的狀態//可以把500-1改為5000-1設置500ms的定時中斷}
}最后,需要啟動定時器,需要在main函數里使能中斷/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim6);/* USER CODE END 2 */
同理,其它定時器的定時器中斷可以通過同樣的方式設置
記得設置完參數后,打開中斷哦,否則將不會產生中斷。
基本定時器
高級定時器
然后代碼中也要手動啟動定時器
??main.c/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim6)/* USER CODE END 2 */