硬件:STM32F103C8T6
平台: ARM-MDk V5.11
前面一篇文章講過如何利用定時器測量信號的頻率(),使用的是定時器的捕獲/比較單元(Capture/compare),它也可以測量輸入信號的脈沖寬度。
利用定時器測量脈沖寬度有兩種方法。
方法1:
在捕獲中斷函數里改變捕獲信號的觸發沿(上升沿觸發改為下降沿觸發,或者下降沿觸發改為上升沿觸發),通過兩次觸發得到的計數器的差值,來計算出脈沖寬度。這種
方法需要定時器的配置方法是一樣的,不同的地方在中斷函數里修改觸發沿,以TIM2, 捕獲通道2為例:
if(CapState == 0) { /* First time capture */ Val1 = TIM_GetCapture2(TIM2); CapState = 1; /* Change the trigger */ TIM2->CCER |= 1UL << 5; } else if(CapState == 1) { /* Second time capture */ Val2 = TIM_GetCapture2(TIM2); /* Change the trigger */ TIM2->CCER &= ~(1UL << 5); /* Capture computation */ if (Val2 > Val1) { CapVal = Val2 - Val1; } else { CapVal = ((0xFFFF - Val1) + Val2); } CapState = 0; }
當然,在第一次捕獲的時候將計數器清零,然后第二次捕獲直接讀取捕獲值也是一個不錯的選擇,如下,
if(CapState == 0) { /* First time capture */ TIM_GetCapture2(TIM2); CapState = 1; /* Change the trigger */ TIM2->CCER |= 1UL << 5; /* Clear CNT */ TIM_SetCounter(TIM2, 0); } else if(CapState == 1) { /* Second time capture */ CapVal = TIM_GetCapture2(TIM2); /* Change the trigger */ TIM2->CCER &= ~(1UL << 5); CapState = 0; }
觸發沿的配置在CCER這個寄存器里面,這里直接對寄存器進行操作,具體請查閱STM32F10x的參考說明書。
方法2:
利用定時器的PWM輸入模式(PWM input mode)。所謂的PWM模式,其實就是利通了定時器捕獲單元映射功能,定時器捕獲單元1(IC1)和捕獲單元2(IC2)可以映射
到同一個捕獲通道,一個捕獲單元配置成捕獲上升沿信號,另一個捕獲單元配置成捕獲下降沿信號,那么兩個捕獲值的差就是脈沖寬度的值。還是以TIM2, 捕獲通道2
為例,配置代碼如下:
void CaptureConfig(void) { TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_PWMIConfig(TIM2, &TIM_ICInitStructure); /* TIM enable counter */ TIM_Cmd(TIM2, ENABLE); /* Enable the CC1, CC2 Interrupt Request */ TIM_ITConfig(TIM2, TIM_IT_CC2 | TIM_IT_CC1, ENABLE); }
各行代碼的意思:
L2: 指定捕獲單元的映射方式,TIM_ICSelection_IndirectTI 說明捕獲單元1(IC1)和捕獲單元2(IC2)映射到捕獲通道2(TI2,這里是指捕獲通道2,區別
定時器TIM2),假如該值為TIM_ICSelection_DirectTI,則捕獲單元1(IC1)和捕獲單元2(IC2)映射到捕獲通道1(TI1)。
L8, L9: 指定捕獲單元觸發的信號沿(上升沿還是下降沿)。TIM_Channel_1對應捕獲單元1(IC1),TIM_Channel_2對應捕獲單元2(IC2)注意這里
只需要指定一個捕獲單元,另一個捕獲單元將會在調用初始化函數TIM_PWMICConfig時設定為相反的邊沿。
L16: 允許捕獲單元1和捕獲單元2的中斷。
這樣,當捕獲通道2(TI2)檢測到上升沿時,捕獲單元1(IC1)將會記錄下計數器的值,同時捕獲單元1的中斷標志位(CC1IF)將置位;
當捕獲通道2(TI2)檢測到下降沿時,捕獲單元2(IC2)將會記錄下計數器的值,同時捕獲單元2的中斷中斷標志位(CC2F)將置位。
中斷處理函數示例代碼如下:
if(TIM_GetITStatus(DEMOD_CAPTURE_TIM, TIM_IT_CC1) == SET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); TIM_GetCapture1(TIM2); TIM_SetCounter(TIM2, 0); } else if(TIM_GetITStatus(DEMOD_CAPTURE_TIM, TIM_IT_CC2) == SET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); CapVal = TIM_GetCapture2(TIM2); } }
總結:
STM32F10x系列的定時器是一個很靈活的東西,想靈活應用它首先要理解它的原理和運作的過程。定時器的捕獲單元和捕獲通道是比較容易混淆的兩個東西
簡單來說,STM32F10x的每個通用定時器有4個捕獲通道(TI1, TI2, TI3, TI4, 對應4個GPIO口),每個捕獲通道對應一個捕獲單元,即IC1, IC2, IC3, IC4,
其中捕獲單元1和捕獲單元2可以映射到同一個捕獲通道,TI1或者TI2。