利用定時(shí)器測(cè)量脈沖寬度有兩種方法。
方法1:
在捕獲中斷函數(shù)里改變捕獲信號(hào)的觸發(fā)沿(上升沿觸發(fā)改為下降沿觸發(fā),或者下降沿觸發(fā)改為上升沿觸發(fā)),通過兩次觸發(fā)得到的計(jì)數(shù)器的差值,來計(jì)算出脈沖寬度。這種
方法需要定時(shí)器的配置方法是一樣的,不同的地方在中斷函數(shù)里修改觸發(fā)沿,以TIM2, 捕獲通道2為例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
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;
}
|
當(dāng)然,在第一次捕獲的時(shí)候?qū)⒂?jì)數(shù)器清零,然后第二次捕獲直接讀取捕獲值也是一個(gè)不錯(cuò)的選擇,如下,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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;
}
|
觸發(fā)沿的配置在CCER這個(gè)寄存器里面,這里直接對(duì)寄存器進(jìn)行操作,具體請(qǐng)查閱STM32F10x的參考說明書。
方法2:
利用定時(shí)器的PWM輸入模式(PWM input mode)。所謂的PWM模式,其實(shí)就是利通了定時(shí)器捕獲單元映射功能,定時(shí)器捕獲單元1(IC1)和捕獲單元2(IC2)可以映射
到同一個(gè)捕獲通道,一個(gè)捕獲單元配置成捕獲上升沿信號(hào),另一個(gè)捕獲單元配置成捕獲下降沿信號(hào),那么兩個(gè)捕獲值的差就是脈沖寬度的值。還是以TIM2, 捕獲通道2
為例,配置代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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,區(qū)別
定時(shí)器TIM2),假如該值為TIM_ICSelection_DirectTI,則捕獲單元1(IC1)和捕獲單元2(IC2)映射到捕獲通道1(TI1)。
L8, L9: 指定捕獲單元觸發(fā)的信號(hào)沿(上升沿還是下降沿)。TIM_Channel_1對(duì)應(yīng)捕獲單元1(IC1),TIM_Channel_2對(duì)應(yīng)捕獲單元2(IC2)注意這里
只需要指定一個(gè)捕獲單元,另一個(gè)捕獲單元將會(huì)在調(diào)用初始化函數(shù)TIM_PWMICConfig時(shí)設(shè)定為相反的邊沿。
L16: 允許捕獲單元1和捕獲單元2的中斷。
這樣,當(dāng)捕獲通道2(TI2)檢測(cè)到上升沿時(shí),捕獲單元1(IC1)將會(huì)記錄下計(jì)數(shù)器的值,同時(shí)捕獲單元1的中斷標(biāo)志位(CC1IF)將置位;
當(dāng)捕獲通道2(TI2)檢測(cè)到下降沿時(shí),捕獲單元2(IC2)將會(huì)記錄下計(jì)數(shù)器的值,同時(shí)捕獲單元2的中斷中斷標(biāo)志位(CC2F)將置位。
中斷處理函數(shù)示例代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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);
}
}
|
總結(jié):
STM32F10x系列的定時(shí)器是一個(gè)很靈活的東西,想靈活應(yīng)用它首先要理解它的原理和運(yùn)作的過程。定時(shí)器的捕獲單元和捕獲通道是比較容易混淆的兩個(gè)東西
簡(jiǎn)單來說,STM32F10x的每個(gè)通用定時(shí)器有4個(gè)捕獲通道(TI1, TI2, TI3, TI4, 對(duì)應(yīng)4個(gè)GPIO口),每個(gè)捕獲通道對(duì)應(yīng)一個(gè)捕獲單元,即IC1, IC2, IC3, IC4,
其中捕獲單元1和捕獲單元2可以映射到同一個(gè)捕獲通道,TI1或者TI2。