TIM(Timer)定時器介紹
- 定時器可以對輸入的時鐘進行計數,并在計數值達到設定值時觸發中斷
- 16位計數器、預分頻器、自動重裝寄存器的時基單元,在72MHz計數時鐘下可以實現最大59.65s的定時
- 不僅具備基本的定時中斷功能,而且還包含內外時鐘源選擇、輸入捕獲、輸出比較、編碼器接口、主從觸發模式等多種功能
- 根據復雜度和應用場景分為了高級定時器、通用定時器、基本定時器三種類型
定時器分類
基本定時器
時基單元為下圖的預分頻器、計數器、自動重裝寄存器。
內部時鐘CK-INT
預分頻器之前連接的是基準計數時鐘的輸入(由于基本定時器只能選擇內部時鐘、輸入端可以直接認為內部時鐘CK-INT、所以通向時基單元的計數頻率就是72M)
預分頻器
預分頻系數實際分頻系數=預分頻器的值+1(預分頻值0:就是不分頻72M 、數值1: 就是2分頻就是36M)預分頻是16位的也就是0X0000~0XFFFF所以最大值是65535,也就是65536分頻(預分頻器的值+1)
計數器
作用是對輸入的預分頻后的計數時鐘(CK_CNT)進行計數,計數時鐘(CK_CNT)每來一個上升沿,計數器值就+1
計數器也是16位的也就是0X0000~0XFFFF所以最大值是65535,如果再加的話計數器就會回到0,當運行到目標值時就會產生UI更新中斷或U更新事件
自動重裝寄存器
作用就是存儲我們寫入的計數目標,也是16位的也就是0X0000~0XFFFF所以最大值是65535,到達目標值后就會產生UI更新中斷和U更新事件,中斷就會通向NIVC,配置好NVIC的定時器通道,定時器的事件信息就能得到CPU的相應了
主從模式觸發DAC
用途時使用DAC輸出一段波形,那就需要每隔一段時間觸發一次DAC,讓他輸出下一個電壓點。中斷容易打斷主程序運行,所以提供主模式下可以把定時器的U更新事件 映射到觸發TRGO(Trigger Out)的位置,TRGO直接接到DAC的觸發引腳上。實現了硬件的自動化
通用定時器
基本定時器只有向上計時的功能。通用定時器和高級定時器有三種計時功能:向上(0到目標值)、向下(目標值到0)、中央對其計時(0到目標值再從目標值到0,完成一次計時就觸發一次事件)
基準定時器輸入
對于基本定時器只能選擇內部時鐘也是72MHZ,通用和高級不僅可以使用內部時鐘,還可以使用外部時鐘TIMx-ETR
外部時鐘模式2——外部時鐘TIMx-ETR- ETR極性選擇…-輸入濾波-EFRF-基準時鐘選擇
外部時鐘模式1——TRGI主要是觸發輸入來使用的
-
ETR
-
ITR0
定時器的級聯
-
TI1FP1、TI2FP2
編碼器接口
可以讀取正交編碼器的輸出波形
輸出比較電路
可以用于輸出PWM波形,驅動電機。對應四個通道CH1、CH2、CH3、CH4
輸入捕獲電路
可以用于測量輸入方波的頻率和占空比。
輸入捕獲電路也對應四個通道CH1、CH2、CH3、CH4。
捕獲/比較寄存器
捕獲/比較寄存器,是輸入和輸出比較電路公用的
高級定時器
與通用定時器不相同的只有下面部分不一樣,
-
申請中斷的地方增加了一個重復的計數器
可以實現每隔幾個計數周期,才發發生一個更新事件和更新中斷事件,原來是每個計數周期都會發生更新
-
高級定時器對輸出比較模塊的升級(前三路互補波形,第四路CH4沒什么變化)
DTG(Dead Time Generate)是死區生成電路(避免開關切換的瞬間,由于器件的不理想造成短暫的直通現象,讓橋臂的上下管全都關斷。防止直通現象),輸出引腳由原來的一個,變為了兩互補的輸出,可以輸出一對互補的PWM波。這些電路可以驅動三相無刷電機比較常用。比如四軸飛行器、電動車后輪、電鉆等
圖左邊是產生短暫的直通現象,圖右邊是橋臂的上下管全都關斷 -
剎車輸入
給電機驅動提高安全保障。
實例
內部時鐘
1、開啟RCC時鐘,定時器的基準時鐘和整個外設的工作時鐘就會同時打開了。
2、選擇時基單元的時鐘源,對于定時中斷就選擇內部時鐘源。TIM_InternalClockConfig(TIM2);
3、時基單元初始化。
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //將結構體變量交給TIM_TimeBaseInit,配置TIM2的時基單元
4、配置輸出中斷控制,允許更新中斷輸出到NVIC。
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除定時器更新標志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //開啟TIM2的更新中斷
5、配置NVIC,在NVIC中打開定時器中斷通道,并分配一個優先級。
NVIC_Init(&NVIC_InitStructure);
6、允許控制,使能定時器。
TIM_Cmd(TIM2, ENABLE); //使能TIM2,定時器開始運行
#include "stm32f10x.h" // Device headervoid Timer_Init(void)
{/*開啟時鐘*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //打開定時器/*配置時鐘源*/TIM_InternalClockConfig(TIM2);//選擇TIM2為內部時鐘,若不調用此函數,TIM默認也為內部時鐘/*時基單元初始化*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定義結構體變量TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//時鐘分頻,選擇不分頻,此參數用于配置濾波器時鐘,不影響時基單元功能TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數器模式,選擇向上計數TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//計數周期,即ARR的值TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//預分頻器,即PSC的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重復計數器,高級定時器才會用到TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//將結構體變量交給TIM_TimeBaseInit,配置TIM2的時基單元 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);/*中斷輸出配置*/TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除定時器更新標志位//TIM_TimeBaseInit函數末尾,手動產生了更新事件//若不清除此標志位,則開啟中斷后,會立刻進入一次中斷//如果不介意此問題,則不清除此標志位也可 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //開啟TIM2的更新中斷/*NVIC中斷分組*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC為分組2//即搶占優先級范圍:0~3,響應優先級范圍:0~3//此分組配置在整個工程中僅需調用一次//若有多個中斷,可以把此代碼放在main函數內,while循環之前//若調用多次配置分組的代碼,則后執行的配置會覆蓋先執行的配置/*NVIC配置*/NVIC_InitTypeDef NVIC_InitStructure; //定義結構體變量NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //選擇配置NVIC的TIM2線NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC線路使能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //指定NVIC線路的搶占優先級為2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC線路的響應優先級為1NVIC_Init(&NVIC_InitStructure); //將結構體變量交給NVIC_Init,配置NVIC外設/*TIM使能*/TIM_Cmd(TIM2, ENABLE); //啟動定時器
}void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) //獲取中斷標志位{TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除標志位}
}
外部時鐘
0、開啟GPIO口,配置GPIO。
1、開啟RCC時鐘,定時器的基準時鐘和整個外設的工作時鐘就會同時打開了。
2、選擇時基單元的時鐘源,對于定時中斷就選擇內部時鐘源。
3、配置時基單元。
4、配置輸出中斷控制,允許更新中斷輸出到NVIC。
5、配置NVIC,在NVIC中打開定時器中斷通道,并分配一個優先級。
6、允許控制,使能定時器。
(這里是用對射紅外線做的,擋光10次,計數器加一)
void Timer_Init(void)
{/*開啟時鐘*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //開啟TIM2的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //開啟GPIOA的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//將PA0引腳初始化為上拉輸入/*外部時鐘配置*/TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);//選擇外部時鐘模式2,時鐘從TIM_ETR引腳輸入//注意TIM2的ETR引腳固定為PA0,無法隨意更改//最后一個濾波器參數加到最大0x0F,可濾除時鐘信號抖動/*時基單元初始化*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定義結構體變量TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //時鐘分頻,選擇不分頻,此參數用于配置濾波器時鐘,不影響時基單元功能TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數器模式,選擇向上計數TIM_TimeBaseInitStructure.TIM_Period = 10 - 1; //計數周期,即ARR的值TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //預分頻器,即PSC的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重復計數器,高級定時器才會用到TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//將結構體變量交給TIM_TimeBaseInit,配置TIM2的時基單元 /*中斷輸出配置*/TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除定時器更新標志位//TIM_TimeBaseInit函數末尾,手動產生了更新事件//若不清除此標志位,則開啟中斷后,會立刻進入一次中斷//如果不介意此問題,則不清除此標志位也可TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //開啟TIM2的更新中斷/*NVIC中斷分組*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC為分組2//即搶占優先級范圍:0~3,響應優先級范圍:0~3//此分組配置在整個工程中僅需調用一次//若有多個中斷,可以把此代碼放在main函數內,while循環之前//若調用多次配置分組的代碼,則后執行的配置會覆蓋先執行的配置/*NVIC配置*/NVIC_InitTypeDef NVIC_InitStructure; //定義結構體變量NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //選擇配置NVIC的TIM2線NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC線路使能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //指定NVIC線路的搶占優先級為2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC線路的響應優先級為1NVIC_Init(&NVIC_InitStructure);//將結構體變量交給NVIC_Init,配置NVIC外設/*TIM使能*/TIM_Cmd(TIM2, ENABLE); //使能TIM2,定時器開始運行
}/*** 函 數:返回定時器CNT的值* 參 數:無* 返 回 值:定時器CNT的值,范圍:0~65535*/
uint16_t Timer_GetCounter(void)
{return TIM_GetCounter(TIM2); //返回定時器TIM2的CNT
}/* 定時器中斷函數,可以復制到使用它的地方
void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}
*/
函數說明