STM32中TIM輸出比較的三種模式
此項(xiàng)功能是用來(lái)控制一個(gè)輸出波形,或者指示一段給定的的時(shí)間已經(jīng)到時(shí)。
當(dāng)計(jì)數(shù)器與捕獲/比較寄存器的內(nèi)容相同時(shí),輸出比較功能做如下操作:
● 將輸出比較模式(TIMx_CCMRx寄存器中的OCxM位)和輸出極性(TIMx_CCER寄存器中的
CCxP位)定義的值輸出到對(duì)應(yīng)的引腳上。在比較匹配時(shí),輸出引腳可以保持它的電平
(OCxM=000)、被設(shè)置成有效電平(OCxM=001)、被設(shè)置成無(wú)效電平(OCxM=010)或進(jìn)行翻
轉(zhuǎn)(OCxM=011)。
● 設(shè)置中斷狀態(tài)寄存器中的標(biāo)志位(TIMx_SR寄存器中的CCxIF位)。
● 若設(shè)置了相應(yīng)的中斷屏蔽(TIMx_DIER寄存器中的CCxIE位),則產(chǎn)生一個(gè)中斷。
● 若設(shè)置了相應(yīng)的使能位(TIMx_DIER寄存器中的CCxDE位,TIMx_CR2寄存器中的CCDS位
選擇DMA請(qǐng)求功能),則產(chǎn)生一個(gè)DMA請(qǐng)求。
TIMx_CCMRx中的OCxPE位選擇TIMx_CCRx寄存器是否需要使用預(yù)裝載寄存器。
● 設(shè)置中斷狀態(tài)寄存器中的標(biāo)志位(TIMx_SR寄存器中的CCxIF位)。
● 若設(shè)置了相應(yīng)的中斷屏蔽(TIMx_DIER寄存器中的CCXIE位),則產(chǎn)生一個(gè)中斷。
● 若設(shè)置了相應(yīng)的使能位(TIMx_DIER寄存器中的CCxDE位,TIMx_CR2寄存器中的CCDS位選擇DMA請(qǐng)求功能),則產(chǎn)生一個(gè)DMA請(qǐng)求。
TIMx_CCMRx中的OCxPE位選擇TIMx_CCRx寄存器是否需要使用預(yù)裝載寄存器。
在輸出比較模式下,更新事件UEV對(duì)OCxREF和OCx輸出沒(méi)有影響。
同步的精度可以達(dá)到計(jì)數(shù)器的一個(gè)計(jì)數(shù)周期。輸出比較模式(在單脈沖模式下)也能用來(lái)輸出一個(gè)單脈沖。
輸出比較模式的配置步驟:
1.選擇計(jì)數(shù)器時(shí)鐘(內(nèi)部,外部,預(yù)分頻器)
2.將相應(yīng)的數(shù)據(jù)寫(xiě)入TIMx_ARR和TIMx_CCRx寄存器中
3.如果要產(chǎn)生一個(gè)中斷請(qǐng)求和/或一個(gè)DMA請(qǐng)求,設(shè)置CCxIE位和/或CCxDE位。
4.選擇輸出模式,例如:必須設(shè)置OCxM=’011’、OCxPE=’0’、CCxP=’0’和CCxE=’1’,當(dāng)計(jì)數(shù)器CNT與CCRx匹配時(shí)翻轉(zhuǎn)OCx的輸出管腳,CCRx預(yù)裝載未用,開(kāi)啟OCx輸出且高電平有效。
5.設(shè)置TIMx_CR1寄存器的CEN位啟動(dòng)計(jì)數(shù)器
TIMx_CCRx寄存器能夠在任何時(shí)候通過(guò)軟件進(jìn)行更新以控制輸出波形,條件是未使用預(yù)裝載寄存器OCxPE=’0’,否則TIMx_CCRx影子寄存器只能在發(fā)生下一次更新事件時(shí)被更新)
程序如下:
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM2, 35999, TIM_PSCReloadMode_Immediate);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;//這個(gè)地方就是改比較模式的
但是由于比較模式無(wú)論選哪個(gè)對(duì)于產(chǎn)生中斷的作用是一樣的,所以選TIMING都可以
TIM_OCInitStructure.TIM_Channel = TIM_Channel_1;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInit(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);//
TIMx_CCRx寄存器能夠在任何時(shí)候通過(guò)軟件進(jìn)行更新以控制輸出波形,條件是未使用預(yù)裝載寄存器OCxPE=’0’,否則TIMx_CCRx影子寄存器只能在發(fā)生下一次更新事件時(shí)被更新)。這里設(shè)置為Disable就是為了后面在中斷服務(wù)子程序可以修改TIMx_CCR實(shí)時(shí)起作用~
TIM_OCInitStructure.TIM_Channel = TIM_Channel_2;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OCInit(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_Channel = TIM_Channel_3;
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OCInit(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_Channel = TIM_Channel_4;
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OCInit(TIM2, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_ARRPreloadConfig(TIM2, ENABLE);//TIM_OCPreload_Enable
TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
// STM3210B-LK1, set PC.04 - PC.07
GPIO_SetBits(GPIOC, GPIO_Pin_4 |GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
TIM_Cmd(TIM2, ENABLE);
while (1)
{
}
}
中斷服務(wù)子程序:
void TIM2_IRQHandler(void)
{ u16 capture;
u16 CCR1_Val = 1000;
u16 CCR2_Val = 500;
u16 CCR3_Val = 250;
u16 CCR4_Val = 125;
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
capture = TIM_GetCapture1(TIM2);
TIM_SetCompare1(TIM2, capture + CCR1_Val);
////設(shè)置TIMx捕獲比較1寄存器值然后動(dòng)態(tài)修改其CCR的值使整個(gè)程序一直進(jìn)行下去
// PC.04
GPIO_WriteBit(GPIOC, GPIO_Pin_4, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_4)));
}
else if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
capture = TIM_GetCapture2(TIM2);
TIM_SetCompare2(TIM2, capture + CCR2_Val);
// PC.05
GPIO_WriteBit(GPIOC, GPIO_Pin_5, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_5)));
}
else if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
capture = TIM_GetCapture3(TIM2);
TIM_SetCompare3(TIM2, capture + CCR3_Val);
// PC.06
//GPIO_ResetBits(GPIOC, GPIO_Pin_6);
GPIO_WriteBit(GPIOC, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6))); }
else
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);
capture = TIM_GetCapture4(TIM2);
TIM_SetCompare4(TIM2, capture + CCR4_Val);
// PC.07
// GPIO_ResetBits(GPIOC, GPIO_Pin_7);
GPIO_WriteBit(GPIOC, GPIO_Pin_7, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_7)));
}
}
在STM32的某些應(yīng)用中,用戶(hù)有周期性執(zhí)行某些程序的要求,使用定時(shí)器可以產(chǎn)生固定的時(shí)間周期,滿(mǎn)足這樣的需求。
STM32相關(guān)特征:
STM32高級(jí)定時(shí)器TIM1、TIM8,通用定時(shí)器TIM2、TIM3、TIM4、TIM5;定時(shí)器最大時(shí)鐘72MHz,配合預(yù)分頻,提供靈活的時(shí)鐘周期;每個(gè)TIM有4個(gè)獨(dú)立捕獲/比較通道,DMA/中斷功能;通道工作在輸出比較定時(shí)模式,一個(gè)TIM至多可以提供4個(gè)不同的定時(shí)周期。
原理:TIM某輸出/捕獲通道工作在輸出比較定時(shí)模式,計(jì)數(shù)器計(jì)數(shù)至比較值時(shí)產(chǎn)生中斷,在中斷中刷新捕獲比較寄存器,這樣在相同時(shí)間間隔后可產(chǎn)生下一次中斷
TIM2時(shí)鐘設(shè)置為36MHz,預(yù)分頻設(shè)置為2,使用輸出比較-翻轉(zhuǎn)模式(Output Compare Toggle Mode)。
TIM2計(jì)數(shù)器時(shí)鐘可表達(dá)為:TIM2 counter clock = TIMxCLK / (Prescaler +1) = 12 MHz
設(shè)置TIM2_CCR1寄存器值為32768,則CC1更新頻率為T(mén)IM2計(jì)數(shù)器時(shí)鐘頻率除以CCR1寄存器值,為366.2 Hz。因此,TIM2通道1可產(chǎn)生一個(gè)頻率為183.1 Hz的周期信號(hào)。
同理,根據(jù)寄存器TIM2_CCR2 、TIM2_CCR3和 TIM2_CCR4的值,TIM2通道2可產(chǎn)生一個(gè)頻率為366.3 Hz的周期信號(hào);TIM2通道3可產(chǎn)生一個(gè)頻率為732.4 Hz的周期信號(hào);TIM2通道4可產(chǎn)生一個(gè)頻率為1464.8 Hz的周期信號(hào)。
#include "stm32f10x_lib.h"
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
vu16 CCR1_Val = 32768;
vu16 CCR2_Val = 16384;
vu16 CCR3_Val = 8192;
vu16 CCR4_Val = 4096;
ErrorStatus HSEStartUpStatus;
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
int main(void)
{
#ifdef DEBUG
debug();
#endif
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
TIM_TimeBaseStructure.TIM_Period = 65535; //這里必須是65535,設(shè)置計(jì)數(shù)溢出大小,每計(jì)1個(gè)數(shù)就產(chǎn)生一個(gè)更新事件
TIM_TimeBaseStructure.TIM_Prescaler = 2;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //管腳輸出模式:翻轉(zhuǎn)(TIM輸出比較觸發(fā)模式)
TIM_OCInitStructure.TIM_Channel = TIM_Channel_1;