STM32F429總共有14個:
高級定時器:TIM1 和TIM8
通用定時器:TIM2-TIM5,TIM9-TIM14
基本定時器:TIM6 和 TIM7
掛載的總線:高級定時器及TIM9-TIM11的時鐘來自APB2,其他來自APB1;
APB2:TIM1 和 TIM8 、TIM9-TIM11
APB1:TIM2-TIM5、TIM6 和 TIM7、TIM12-TIM14
定時器簡介
STM32F429 的通用定時器包含一個 16 位或 32 位自動重載計數器( CNT),該計數器由可編程預分頻器( PSC) 驅動。
STM32F429 的通用定時器可以被用於:測量輸入信號的脈衝長度(輸入捕獲)或者產生輸出波形(輸出比較和 PWM)等。
使用定時器預分頻器和 RCC 時鐘控制器預分頻器,脈衝長度和波形週期可以在幾個微秒到幾個毫秒間調整。
STM32F429 的每個通用定時器都是完全獨立的,沒有互相共享的任何資源。
STM32 的通用 TIMx (TIM2~TIM5 和 TIM9~TIM14)定時器功能包括:
-
16 位/32 位(僅 TIM2 和 TIM5)向上、向下、向上/向下自動裝載計數器(TIMx_CNT),注意: TIM9~TIM14 只支持向上(遞增)計數方式。
-
16 位可編程(可以實時修改)預分頻器(TIMx_PSC),計數器時鐘頻率的分頻係數爲 1~65535 之間的任意數值。
-
4 個獨立通道(TIMx_CH14TIM9TIM14 最多 2 個通道),這些通道可以用來作爲:
A.輸入捕獲
B.輸出比較
C. PWM 生成(邊緣或中間對齊模式) ,注意: TIM9~TIM14 不支持中間對齊模式
D.單脈衝模式輸出
-
可使用外部信號( TIMx_ETR)控制定時器和定時器互連(可以用 1 個定時器控制另外
一個定時器)的同步電路。 -
如下事件發生時產生中斷/DMA( TIM9~TIM14 不支持 DMA):
A.更新:計數器向上溢出/向下溢出,計數器初始化(通過軟件或者內部/外部觸發)
B.觸發事件(計數器啓動、停止、初始化或者由內部/外部觸發計數)
C.輸入捕獲
D.輸出比較
E.支持針對定位的增量(正交)編碼器和霍爾傳感器電路( TIM9~TIM14 不支持)
F.觸發輸入作爲外部時鐘或者按週期的電流管理( TIM9~TIM14 不支持)
常用的寄存器
TIMx_CR1:(Control Register 1)控制寄存器1
TIM1 和 TIM8:
TIM2-TIM5:
TIM9-TIM12
TIM6 和 TIM7:
qq空間圖片
不會做點進去就是圖片的鏈接,好尷尬。
TIMx_CR2:(Control Register 2)控制寄存器2
分類同TIMx_CR1
TIMx_DIER:(DMA Interrupt Enable Register)DMA/中斷使能寄存器
TIMx_PSC:(Prescaler)預分頻寄存器
TIMx_ARR:(auto-reload register)重裝載寄存器
該寄存器在物理上實際對應着 2 個寄存器,一個是程序員可以直接操作的,另外一個是程序員看不到的,這個看不到的寄存器在《 STM32F4xx 中文參考手冊》裏面被叫做影子寄存器。事實上真正起作用的是影子寄存器。 根
據 TIMx_CR1 寄存器中 APRE 位的設置:APRE=0 時,預裝載寄存器的內容可以隨時傳送到影子寄存器,此時 2 者是連通的;而 PRE=1 時,在每一次更新事件( UEV)時,才把預裝載寄存器( ARR) 的內容傳送到影子寄存器。
TIMx_SR:(status register)狀態寄存器
步驟
- 1) TIM3 時鐘使能。
這裏我們通過 APB1ENR 的第 1 位來設置 TIM3 的時鐘,因爲 Stm32_Clock_Init 函數裏面
把 APB1的分頻設置爲 4了,所以我們的 TIM3時鐘就是 APB1時鐘的 2倍,等於系統時鐘 ( 90M)。
- 2) 設置 TIM3_ARR 和 TIM3_PSC 的值。
通過這兩個寄存器,我們來設置自動重裝的值,以及分頻係數。這兩個參數加上時鐘頻率就決定了定時器的溢出時間。
- 3) 設置 TIM3_DIER 允許更新中斷。
因爲我們要使用 TIM3 的更新中斷,所以設置 DIER 的 UIE 位爲 1,使能更新中斷。
- 4) 允許 TIM3 工作。
光配置好定時器還不行,沒有開啓定時器,照樣不能用。我們在配置完後要開啓定時器,通過 TIM3_CR1 的 CEN 位來設置。
- 5) TIM3 中斷分組設置。
在定時器配置完了之後,因爲要產生中斷,必不可少的要設置 NVIC 相關寄存器,以使能TIM3 中斷。
- 6) 編寫中斷服務函數。
在最後,還是要編寫定時器中斷服務函數,通過該函數來處理定時器產生的相關中斷。在中斷產生後,通過狀態寄存器的值來判斷此次產生的中斷屬於什麼類型。然後執行相關的操作,我們這裏使用的是更新(溢出)中斷,所以在狀態寄存器 SR 的最低位。在處理完中斷之後應該向 TIM3_SR 的最低位寫 0,來清除該中斷標誌
示例代碼
- 寄存器
/************************/
//C文件內容
#include "tim3.h"
void TIM3_IRQHandler(void)
{
if (TIM3->SR&0x0001) //溢出中斷 SR狀態寄存器
{
LED0=!LED0;
}
TIM3->SR&=~(1<<0); //狀態寄存器清零
}
void TIM4_IRQHandler(void)
{
if (TIM4->SR&0x0001) //溢出中斷 SR狀態寄存器
{
LED1=!LED1;
}
TIM4->SR&=~(1<<0); //狀態寄存器清零
}
//通用定時器 3 中斷初始化
//這裏時鐘選擇爲 APB1 的 2 倍,而 APB1 爲 45M
//arr:自動重裝值。
//psc:時鐘預分頻數
//定時器溢出時間計算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定時器工作頻率,單位:Mhz
//這裏使用的是定時器 3!
void TIM3_Int_Init(u16 arr,u16 psc)
{ //0 1 2 3 ...
RCC->APB1ENR|=1<<1; //TIM2 TIM3 TIM4 TIM5 ...
TIM3->ARR=arr; //自動重裝載寄存器
TIM3->PSC=psc; //時鐘預分頻寄存器
TIM3->DIER|=1<<0; //允許更新中斷
TIM3->CR1|=0x01; //控制寄存器1 使能定時器3
MY_NVIC_Init(1,3,TIM3_IRQn,2); //搶佔1 ,子優先級 3
}
void TIM4_Int_Init(u16 arr,u16 psc)
{ //0 1 2 3 ...
RCC->APB1ENR|=1<<2; //TIM2 TIM3 TIM4 TIM5 ...
TIM4->ARR=arr; //自動重裝載寄存器
TIM4->PSC=psc; //時鐘預分頻寄存器
TIM4->DIER|=1<<0; //允許更新中斷
TIM4->CR1|=0x01; //控制寄存器1 使能定時器3
MY_NVIC_Init(2,3,TIM4_IRQn,2); //搶佔1 ,子優先級 3
}
/************************/
//頭文件內容
#ifndef __TIM3_H_
#define __TIM3_H
#include "sys.h"
#include "led.h"
void TIM3_Int_Init(u16 arr,u16 psc);
void TIM4_Int_Init(u16 arr,u16 psc);
#endif
- 庫函數
/*********************/
//c文件
#include "timer.h"
TIM_HandleTypeDef TIM2_Handler;
TIM_HandleTypeDef TIM3_Handler;
//arr:自動重裝載
//psc:時鐘分頻數
void TIM2_Init(u16 arr,u16 psc)
{
TIM2_Handler.Instance=TIM2;
TIM2_Handler.Init.Prescaler=psc;
TIM2_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;
TIM2_Handler.Init.Period=arr;
TIM2_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&TIM2_Handler);
//使能
HAL_TIM_Base_Start_IT(&TIM2_Handler);
}
void TIM3_Init(u16 arr,u16 psc)
{
TIM3_Handler.Instance=TIM3;
TIM3_Handler.Init.Prescaler=psc;
TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;
TIM3_Handler.Init.Period=arr;
TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&TIM3_Handler);
//使能
HAL_TIM_Base_Start_IT(&TIM3_Handler);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
if (htim==&TIM2_Handler)
{
__HAL_RCC_TIM2_CLK_ENABLE(); //使能 TIM3 時鐘
HAL_NVIC_SetPriority(TIM2_IRQn,0,3); //設置中斷優先級,搶佔 1,子優先級 3
HAL_NVIC_EnableIRQ(TIM2_IRQn); //開啓 ITM3 中斷
}
if (htim==&TIM3_Handler)
{
__HAL_RCC_TIM3_CLK_ENABLE(); //使能 TIM3 時鐘
HAL_NVIC_SetPriority(TIM3_IRQn,1,3); //設置中斷優先級,搶佔 1,子優先級 3
HAL_NVIC_EnableIRQ(TIM3_IRQn); //開啓 ITM3 中斷
}
}
//
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM2_Handler);
}
//
void TIM3_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM3_Handler);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim==&TIM2_Handler)
{
LED1=!LED1;
}
if (htim==&TIM3_Handler)
{
LED0=!LED0;
}
}
/************************************/
//頭文件
#ifndef __TIMER_H__
#define __TIMER_H__
#include "sys.h"
#include "led.h"
void TIM2_Init(u16 arr,u16 psc);
void TIM3_Init(u16 arr,u16 psc);
#endif