一、STM32 定時器概述
1. 定時器的概述定時器的基本功能,但是 STM32 的定時器除了具有定時功能之外,也具有定時器中斷功能,還具有輸入捕獲(檢測外部信號)以及輸出比較功能(輸出不同的脈沖),可以利用 STM32定時器輸出某種頻率的脈沖信號來控制產品(控制燈的亮度、控制直流電機的轉速、控制舵機的角度.......)
2. 定時器的種類STM32 由于資源豐富,所以提供了多種定時器,一共提供 14 個定時器(不包含系統定時器、不包含看門狗定時器),分為高級定時器(TIM1 和 TIM8)、通用定時器(TIM2~TIM5 +TIM9~TIM14,一共 10 個)、基本定時器(TIM6 和 TIM7)。
3. 定時器的使用
基本定時器STM32 提供 TIM6 和 TIM7 作為基本定時器,屬于 STM32 內部資源,都是 16bit 定時器,并沒有和 GPIO 引腳連接,TIM6 和 TIM7 都掛載在 APB1 總線下,而 APB1 定時器時鐘頻率為84MHZ。 ? ??
?時基單元包括:
1計數器寄存器? ? ? ? ?CNT? ? ? ?記錄當前計數的次數
2預分頻器寄存器? ? ? ? PSC? ? ? ? 設置計數一次的周期
3自動重裝載寄存器? ? ARR? ? ? ? ? ? 設置定時的次數(定時時間)
TIM6 的時鐘頻率為 84MHZ,如果想要降低頻率,公式:1MHZ = 84MHZ /(83+1),頻率就降為 1MHZ,也就意味著 TIM_CNT 寄存器累計計數 1 次的時間是 1us,如果打算利用TIM6 定時 1ms,也就是說 TIM_ARR 寄存器的值應該設置為 1000-1,只要 TIM_CNT == TIM_ARR,
就說明時間到了,如果時間到了則 TIM_CNT 清 0,然后重新開始計數
對時鐘進行分頻的目的就是為了延長定時時間
1設置定時器的分頻系數 TIM_Prescaler 范圍 0x0000 and 0xFFFF
設置分頻n,分頻系數n-1
2設置定時器的計數模式TIM_CounterMode 基本定時器只能選擇向上計數
3設置定時器的計數周期 TIM_Period 指的是重載寄存器中的值 0x0000 and 0xFFFF
4設置定時器的時鐘分頻因子 TIM_ClockDivision 在輸入捕獲的采樣使用 不需要設置
5設置定時器的重復計數器 TIM_RepetitionCounter 只有高級定時器需要設置
設置中斷源函數:
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
函數參數參數一:TIMx 打算產生中斷的定時器號 如 TIM6
參數二:TIM_IT 指定定時器的中斷源 一般為 TIM_IT_Update 表示更新時中斷
參數三:NewState 打開或關閉中斷源 ENABLE or DISABLE
初始化定時器:
可以調用 TIM_TimeBaseInit 函數實現函數原型
voidTIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct)函數參數參數一:TIMx 打算配置參數的定時器號 如 TIM6
參數二:TIM_TimeBaseInitStruct 指的是配置的參數信息 記得取地址 &
#include "stm32f4xx.h" ?
__IO uint32_t TimingDelay;
//LED初始化
void LED_Init(void)
{
?? ?GPIO_InitTypeDef ? GPIO_InitStructure;
?? ?RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
?? ?
?? ?GPIO_InitStructure.GPIO_Mode ?? ?= GPIO_Mode_OUT;?? ??? ??? ?//輸出模式
?? ?GPIO_InitStructure.GPIO_OType?? ?= GPIO_OType_PP;?? ??? ??? ?//推挽輸出
?? ?GPIO_InitStructure.GPIO_Speed?? ?= GPIO_Speed_100MHz;?? ??? ?//輸出速率
?? ?GPIO_InitStructure.GPIO_PuPd ?? ?= GPIO_PuPd_NOPULL;?? ??? ??? ?//無上下拉
?? ?GPIO_InitStructure.GPIO_Pin ?? ?= GPIO_Pin_9;?? ??? ??? ??? ?//引腳編號
?? ?GPIO_Init(GPIOF, &GPIO_InitStructure);
?? ?
?? ?GPIO_SetBits(GPIOF,GPIO_Pin_9); //默認不亮
}
//TIM6定時器的初始化
void TIM6_Init(void)
{
?? ?TIM_TimeBaseInitTypeDef ? ?TIM_TimeBaseStructure ;
?? ?
?? ?NVIC_InitTypeDef ? NVIC_InitStructure ;
//1.打開時鐘
?? ?RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
//2.配置定時時間,定時200ms,APB1定時時鐘84MHZ ?1us數84次 ?200ms: ?84*1000*200(次)
//?? ??? ??? ??? ?定時200ms,經過8400分頻,8400us數84次,即100us數1次,1ms=1000us,10次即可,200ms 2000次
?? ?TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;//預分頻
?? ?TIM_TimeBaseStructure.TIM_Period = 2000-1;//計數周期
?? ?TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//計數模式,向上計數
?? ?TIM_TimeBaseInit ( TIM6 , &TIM_TimeBaseStructure);
?? ?
//3.配置NVIC (中斷通道+優先級)?? ?
?? ?NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;//中斷通道去f4xx.h里面找
?? ?NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//搶占優先級
?? ?NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//響應優先級
?? ?NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中斷通道
?? ?NVIC_Init(&NVIC_InitStructure);
?? ?
//4.選擇TIM6的中斷源
?TIM_ITConfig(TIM6,TIM_IT_Update, ENABLE);//更新事件
?
?//5.使能定時器
?TIM_Cmd(TIM6,ENABLE);
}
void Delay_ms(__IO uint32_t nTime)
{
?? ?TimingDelay=nTime;
?? ?while(TimingDelay);
}
int main()
{
?? ?//1.硬件初始化
?? ?LED_Init();
?? ?TIM6_Init();
?? ?
?? ?
?? ?
?? ?//2.進入死循環
?? ?while(1)
?? ?{
?? ??? ?
?? ?}
?? ?
}
void TIM6_DAC_IRQHandler(void)
{
?? ?//檢測中斷是否發生
?? ?if (TIM_GetITStatus(TIM6, TIM_IT_CC1) != RESET)
?? ?{
?? ??? ?TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);//清空中斷標志
?? ??? ?//異常處理
?? ??? ?GPIO_ToggleBits(GPIOF,GPIO_Pin_9);//翻轉
?? ?}
}
?
優化:
?通用定時器
STM32 一共提供 10 個通用定時器(TIM2~TIM5、TIM9~TIM14),TIM2 和 TIM5 是 32bit 定時器,其他的定時器都是 16bit 定時器。
? ? ?TIM2~TIM5 的計數方式有多種可以選擇,分別為遞增計數、遞減計數、遞增/遞減計數。
遞增計數:計數器從 0 計數到自動重載值(TIMx_ARR 寄存器的內容),然后重新從 0 開始計數并生成計數器上溢事件。
遞減計數:計數器從自動重載值(TIMx_ARR 寄存器的內容)開始遞減計數到 0,然后重新從自動重載值開始計數并生成計數器下溢事件。
中心對齊:計數器從 0 開始計數到自動重載值(TIMx_ARR 寄存器的內容)— 1,生成計數器上溢事件;然后從自動重載值開始向下計數到 1 并生成計數器下溢事件。之后從 0 開始重新計數。 ?