STM32F4 定時器TIM(1)定時器控制輸出
高級時鐘控制定時器TIM1&TIM8簡介:
STM32F4的高級控制定時器包含一個自動重裝載計(jì)數(shù)器,計(jì)數(shù)器的輸入是一個被預(yù)分頻的系統(tǒng)時鐘。
這個定時器有多種用途,包括車輛輸入信號長度(輸入捕獲模式)或者產(chǎn)生波形輸出(輸出捕獲,PWM,帶死區(qū)插入的互補(bǔ)PWM輸出等)
脈沖長度和波形周期可在通過定時器的預(yù)分頻器或者RCC的預(yù)分頻器在幾個微秒時鐘內(nèi)調(diào)整。
高級控制定時器和通用定時器完全獨(dú)立,不共享任何資源。
高級時鐘控制定時器TIM1&TIM8的主要特性:
1、16位向上、向下、雙向自動重裝載計(jì)數(shù)器2、16位預(yù)分頻器,分頻值從1打655353、4個獨(dú)立通道4、帶死去輸出的互補(bǔ)輸出5、控制外部信號的同步電路6、剎車輸入7、產(chǎn)生中斷和DMA強(qiáng)求8、可外部觸發(fā)
等等。。
TIM定時器確實(shí)很強(qiáng)大。至于怎么用,ST的手冊不出奇的難看,完全沒有條理可言。昨天看一天,都沒明白是在說什么。配套的固件庫也是,各種函數(shù)的介紹,函數(shù)名結(jié)構(gòu)體定義完全沒有邏輯可言。于是只能參照網(wǎng)友的介紹,從最基礎(chǔ)的部分弄起。
參考資料見:STM32入門篇之通用定時器徹底研究
【實(shí)驗(yàn)1、TIM1的計(jì)時功能】
【實(shí)驗(yàn)描述】
利用TIM1的技術(shù)功能,產(chǎn)生2Hz的中斷每次中斷LED1反轉(zhuǎn),LED1反轉(zhuǎn)頻率為1Hz。
根據(jù)時鐘配置,系統(tǒng)時鐘為168MHz,APB2時鐘為84MHz。TIM1掛接在APB2上,所以APB2 時鐘為84MHz。
因此預(yù)分頻系數(shù)設(shè)置成了10000即0x2710,自動重裝載計(jì)數(shù)器ARR(TIM_Period)設(shè)置成了4200即0x1068。每次計(jì)數(shù)滿產(chǎn)生中斷。
中斷頻率f= 84MHz /4200 / 10000 = 2Hz
【代碼實(shí)現(xiàn)】
1、首先開啟TIM1的時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
2、時基單元的初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 0x1068;
TIM_TimeBaseInitStructure.TIM_Prescaler = 0x2710;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM1,TIM_FLAG_Update); //必須先清除配置時候產(chǎn)生的更新標(biāo)志
TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE); //使能中斷,中斷事件為定時器工薪事件
TIM_Cmd(TIM1,ENABLE); //使能定時器
3、中斷處理函數(shù)
沒什么可說的,反轉(zhuǎn)LED燈而已。每次中斷反轉(zhuǎn)一次,2Hz的中斷產(chǎn)生1Hz的閃爍。
中斷名字是庫里邊定義的,跟TIM10全局中斷公用。
void TIM1_UP_TIM10_IRQHandler(void)
{
TIM_ClearFlag(TIM1,TIM_FLAG_Update);//進(jìn)入中斷先清除更新標(biāo)志
LEDTog(LED1);
}
之后我們就可以看到LED以大約1Hz的頻率在閃爍了。
【實(shí)驗(yàn)2、強(qiáng)制輸出模式實(shí)驗(yàn)】
百度來的強(qiáng)制輸出模式的定義:在程序編程中,IO口一般都可以作為輸入輸出的。而有些數(shù)據(jù)要在讓其執(zhí)行時候必須執(zhí)行,所以讓其強(qiáng)制性的輸出。這是IO口只能做一件事。
看完之后還是一頭霧水。
簡單 點(diǎn)說,就是不管當(dāng)時IO輸出的是什么,都能強(qiáng)制將其設(shè)為0或者為1.
【實(shí)驗(yàn)描述】
為了實(shí)驗(yàn)方便,這個實(shí)驗(yàn)使用TIM4的強(qiáng)制輸出功能,點(diǎn)亮與GPIOD Pin13引腳相連的LED3。對于強(qiáng)制輸出功能,高級定時器和通用定時器是完全一樣的。
TIM4的CH2被復(fù)用在GPIOD 的Pin13。所以可以將這個輸出強(qiáng)制為高,將LED點(diǎn)亮。
【代碼實(shí)現(xiàn)】
1、首先將GPIO初始化為AF復(fù)用功能。
CM4的引腳復(fù)用功能和CM3的實(shí)現(xiàn)方法不同,要特別注意。按照CM3的寫法將不會有輸出
void TIM4_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_initStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
GPIO_initStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_initStructure.GPIO_OType = GPIO_OType_PP;
GPIO_initStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_initStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_initStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD,&GPIO_initStructure);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource12,GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource13,GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_TIM4);
}
2、TIM4的初始化
這里的時鐘我沒有計(jì)算,因?yàn)檫@個實(shí)驗(yàn)不太關(guān)注這個。
void TIM4_Config1(void)
{
TIM4_GPIO_Config();
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period =0x1068;
TIM_TimeBaseInitStructure.TIM_Prescaler = 0x2710;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
TIM_ARRPreloadConfig(TIM4,ENABLE);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active;; //設(shè)置成什么模式都行。
TIM_OCInitStructure.TIM_Pulse= 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OC2Init(TIM4,&TIM_OCInitStructure);
TIM_Cmd(TIM4,ENABLE);
}
3、在主函數(shù)中強(qiáng)制輸出。
初始化完成之后,在任何時候都能強(qiáng)制引腳電平,只需要一個函數(shù)即可:
TIM_ForcedOC2Config(TIM4,TIM_ForcedAction_Active);
這個函數(shù)設(shè)置TIM的CCMR1的OCxM位為101或者100實(shí)現(xiàn)輸出的拉高或拉低
【實(shí)驗(yàn)三、比較輸出】
一直不理解這里的比較是哪兩個東西在進(jìn)行比較。今天翻ST參考手冊 reference manual發(fā)現(xiàn)這么句話:
當(dāng)OCxM位為000時:The comparison between the output compare register TIMx_CCR1 and the counter TIMx_CNT has no effect on the outputs.
即這里的“比較”是TIMx_CCR1和TIMx_CNT的比較。兩個相等時,觸發(fā)事件。這個事件發(fā)生時,TIm根據(jù)CCMRx寄存器的OCxM位進(jìn)行輸出。
OCxM不同設(shè)置的不同功能如下表所示:
OCxM[2..0]值功能000對輸出不影響001相等時輸出強(qiáng)制為1010相等時輸出強(qiáng)制為0011輸出反轉(zhuǎn)100不管是否相等,強(qiáng)制為0101不管是否相等,強(qiáng)制為1110PWM模式1(先正后負(fù))111PWM模式2(先負(fù)后正)結(jié)合庫中的定義,可以很方便地改變輸出方式:
#define TIM_OCMode_Timing ((uint16_t)0x0000)
#define TIM_OCMode_Active ((uint16_t)0x0010)
#define TIM_OCMode_Inactive ((uint16_t)0x0020)
#define TIM_OCMode_Toggle ((uint16_t)0x0030)
#define TIM_OCMode_PWM1 ((uint16_t)0x0060)
#define TIM_OCMode_PWM2 ((uint16_t)0x0070)
【實(shí)驗(yàn)現(xiàn)象】
LED周期閃爍
【代碼實(shí)現(xiàn)】
只需要將上邊的代碼中的TIM_OCMode改成PWM即可。
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
參數(shù)TIM_Pulse對這種模式?jīng)]影響,TIM_OCPolarity只影響先輸出的是低電平還是高電平。
【實(shí)驗(yàn)4、PWM輸出】
這是輸出部分的傳統(tǒng)了。所有的開發(fā)板的TIM例子都是一個PWM輸出。
時基單元好了,設(shè)置一下輸出模式,反轉(zhuǎn)時機(jī)(TIM_Pulse)。然后開啟哥哥通道的OC即可。對于每個Tim的所有通道,由于時基配置是一樣的所以只能改變各個通道的占空比。
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//PWM2也行
TIM_OCInitStructure.TIM_Pulse= 2000;//CCR,設(shè)置占空比。反轉(zhuǎn)模式時候無效
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_ClearFlag(TIM4,TIM_FLAG_CC2);
TIM_OC2Init(TIM4,&TIM_OCInitStructure);
當(dāng)然,引腳初始化不能少的。
【實(shí)驗(yàn)5、單脈沖方式】
只需要在上邊的代碼之后加一句:
TIM_SelectOnePulseMode(TIM4,TIM_OPMode_Single);
這樣講產(chǎn)生一個負(fù)脈沖,效果是LED滅一下之后保持常亮。如果要要讓LED亮一下,輸出正脈沖還需要改下輸出的極性:
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
到這里,TIM控制輸出的實(shí)驗(yàn)基本就做完了。馬上開始TIM控制輸入部分,包括輸入捕獲、PWM輸入等。