stm32庫(kù)函數(shù)學(xué)習(xí)篇通用定時(shí)器輸入捕獲功能
先有必要了解stm32定時(shí)器的輸入觸發(fā)模塊,如下圖:
需要注意的是,一眼望去一個(gè)定時(shí)器似乎有8個(gè)通道,左邊四個(gè),右邊四個(gè),但其實(shí)左邊和右邊是共用相同的IO引腳,所以名稱標(biāo)注是一模一樣。也就是說(shuō),每個(gè)通用定時(shí)器都只有四個(gè)獨(dú)立通道,當(dāng)某一通道作為了輸入觸發(fā)功能那就不能再作為輸出匹配功能。這一點(diǎn)我們也可以從其他地方找到印證。比如TIM_ITConfig()函數(shù)中如下:
void TIM_ITConfig | ( | TIM_TypeDef * | TIMx, |
uint16_t | TIM_IT, | ||
FunctionalState | NewState | ||
) |
Enables or disables the specified TIM interrupts.
Parameters:
TIMx,: | where x can be 1 to 17 to select the TIMx peripheral. |
TIM_IT,: | specifies the TIM interrupts sources to be enabled or disabled. This parameter can be any combination of the following values: TIM_IT_Update: TIM update Interrupt source TIM_IT_CC1: TIM Capture Compare 1 Interrupt source TIM_IT_CC2: TIM Capture Compare 2 Interrupt source TIM_IT_CC3: TIM Capture Compare 3 Interrupt source TIM_IT_CC4: TIM Capture Compare 4 Interrupt source TIM_IT_COM: TIM Commutation Interrupt source TIM_IT_Trigger: TIM Trigger Interrupt source TIM_IT_Break: TIM Break Interrupt source |
我們可以看到此函數(shù)TIM_IT參數(shù)的取值范圍如下:
TIM_IT_Update: TIM update Interrupt source
TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
TIM_IT_COM: TIM Commutation Interrupt source
TIM_IT_Trigger: TIM Trigger Interrupt source
TIM_IT_Break: TIM Break Interrupt source
也就是說(shuō)每個(gè)通道的捕獲和比較功能是共用一個(gè)中斷標(biāo)志。
stm32定時(shí)器輸入觸發(fā)功能其實(shí)挺簡(jiǎn)單的,與AVR單片機(jī)幾乎一樣。就是單片機(jī)引腳上一旦出現(xiàn)一個(gè)有效邊沿(可以配置為上升、下降或者上升下降均觸發(fā)),那么定時(shí)器計(jì)數(shù)器CNT里面的值就會(huì)被相應(yīng)的Capture/Compare X Register保存下來(lái)。這里X可以是1,2,3,4任何一個(gè)。并且中斷標(biāo)志位被置位。但是此時(shí)TIM的計(jì)數(shù)寄存器CNT卻不管這一事件的發(fā)生,繼續(xù)自己的計(jì)數(shù)。此功能可以用來(lái)測(cè)量外部信號(hào)的脈寬或者是周期。
對(duì)于定時(shí)器的時(shí)基單元TIM_TimeBaseStructure就不作說(shuō)明了,在我前面的文章有專門介紹。下面就重點(diǎn)講解輸入觸發(fā)單元TIM_ICInitStructure。
首先看次結(jié)構(gòu)體原型的定義如下:
typedef struct
{
uint16_t TIM_Channel; /*!< Specifies the TIM channel.
This parameter can be a value of @ref TIM_Channel */
uint16_t TIM_ICPolarity; /*!< Specifies the active edge of the input signal.
This parameter can be a value of @ref TIM_Input_Capture_Polarity */
uint16_t TIM_ICSelection; /*!< Specifies the input.
This parameter can be a value of @ref TIM_Input_Capture_Selection */
uint16_t TIM_ICPrescaler; /*!< Specifies the Input Capture Prescaler.
This parameter can be a value of @ref TIM_Input_Capture_Prescaler */
uint16_t TIM_ICFilter; /*!< Specifies the input capture filter.
This parameter can be a number between 0x0 and 0xF */
} TIM_ICInitTypeDef;
它一共有5個(gè)成員,5個(gè)成員具體作用,我們只要看看3.5版本固件庫(kù)的說(shuō)明就清楚了。
uint16_t TIM_ICInitTypeDef::TIM_Channel |
Specifies the TIM channel. This parameter can be a value of TIM_Channel
其中TIM_Channel的取值范圍如下:
TIM_Channel_1.
TIM_Channel_2
TIM_Channel_3
TIM_Channel_4
uint16_t TIM_ICInitTypeDef::TIM_ICFilter |
Specifies the input capture filter. This parameter can be a number between 0x0 and 0xF
說(shuō)實(shí)話這個(gè)成員具體作用我沒(méi)有深入了解,僅僅知道是作為對(duì)輸入信號(hào)的濾波作用,估計(jì)是讓用戶設(shè)定用多少個(gè)采樣時(shí)鐘來(lái)確定最終輸入信號(hào),起到濾波作用,避免高頻信號(hào)干擾,反正不管它了。
uint16_t TIM_ICInitTypeDef::TIM_ICPolarity |
Specifies the active edge of the input signal. This parameter can be a value of TIM_Input_Capture_Polarity
這個(gè)就是觸發(fā)邊沿的極性選擇了,取值范圍如下:
TIM_ICPolarity_BothEdge
TIM_ICPolarity_Rising
TIM_ICPolarity_Falling
uint16_t TIM_ICInitTypeDef::TIM_ICPrescaler |
Specifies the Input Capture Prescaler. This parameter can be a value of TIM_Input_Capture_Prescaler
這個(gè)成員是對(duì)外部信號(hào)進(jìn)行分頻,也即是設(shè)置上圖中的Prescaler,可以設(shè)置為1/2/4/8分頻。
uint16_t TIM_ICInitTypeDef::TIM_ICSelection |
Specifies the input. This parameter can be a value of TIM_Input_Capture_Selection
這個(gè)成員的作用就必須要對(duì)照上面的示意圖才能明白。仔細(xì)看上面的圖,可以發(fā)現(xiàn)定時(shí)器的4個(gè)通道并不是完全獨(dú)立的,而是1、2一組,3、4一組,同組之間的通道是有聯(lián)系的。也就是可以出現(xiàn)交叉觸發(fā)。而TIM_ICSelection就是選擇要不要使用交叉來(lái)觸發(fā),如果不明白可以看固件庫(kù)的說(shuō)明文檔,如下是此結(jié)構(gòu)體成員的取值范圍:
#define TIM_ICSelection_DirectTI((uint16_t)0x0001) |
TIM Input 1, 2, 3 or 4 is selected to be connected to IC1, IC2, IC3 or IC4, respectively
#define TIM_ICSelection_IndirectTI((uint16_t)0x0002) |
TIM Input 1, 2, 3 or 4 is selected to be connected to IC2, IC1, IC4 or IC3, respectively.
#define TIM_ICSelection_TRC((uint16_t)0x0003) |
TIM Input 1, 2, 3 or 4 is selected to be connected to TRC.
也就是說(shuō),根據(jù)不同的取值,可以講外部引腳的觸發(fā)信號(hào)連到內(nèi)部不同的單元,這樣就使得單片機(jī)更加靈活了。
下面是main.c文件
#include "stm32f10x.h"
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
void delay()
{
u32 i,j;
for(i=0;i<1000;i++)
for(j=0;j<5000;j++)
;
}
void rcc_cfg()
{
;
}
void gpio_cfg()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //隨意延時(shí)led取反,且將PA8作為觸發(fā)定時(shí)器電平
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //觸發(fā)中斷時(shí),取反PD2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* TIM3 channel 2 pin (PA.07) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void nvic_cfg()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the TIM3 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占優(yōu)先級(jí)0級(jí)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優(yōu)先級(jí)3級(jí)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)NVIC_InitStruct中指定的參數(shù)初始化外設(shè)NVIC寄存器
}
void tim3_cfg()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_DeInit(TIM3);
TIM_InternalClockConfig(TIM3);
//預(yù)分頻系數(shù)為36000-1,這樣計(jì)數(shù)器時(shí)鐘為72MHz/36000 = 2kHz
TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1;
//設(shè)置時(shí)鐘分割
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//設(shè)置計(jì)數(shù)器模式為向上計(jì)數(shù)模式
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//設(shè)置計(jì)數(shù)溢出大小,每計(jì)2000個(gè)數(shù)就產(chǎn)生一個(gè)更新事件
TIM_TimeBaseStructure.TIM_Period = 2000 - 1;
//將配置應(yīng)用到TIM2中
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
//禁止ARR預(yù)裝載緩沖器
TIM_ARRPreloadConfig(TIM3, DISABLE);
//下面是對(duì)TIM_ICInitStructure的配置
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0; /*選擇輸入比較濾波器,濾波設(shè)置,經(jīng)歷幾個(gè)周期跳變認(rèn)定波形穩(wěn)定0x0~0xF*/
TIM_ICInit(TIM3, &TIM_ICInitStructure);
//開啟TIM2的中斷
TIM_ClearFlag(TIM3, TIM_IT_CC2);
TIM_ITConfig(TIM3,TIM_IT_CC2,ENABLE);
TIM_Cmd(TIM3, ENABLE); //使能TIMx外設(shè)
}
/
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
rcc_cfg();
gpio_cfg();
nvic_cfg();
tim3_cfg();
while (1)
{
/* Set PA8 */
GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
delay();
/* Reset PA8 */
GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
delay();
}
}
注意定時(shí)器3通道2引腳設(shè)置為浮空輸入。
下面是stm32f10x_it.c文件
#include "stm32f10x_it.h"
u8 flag=0;
extern TIM_ICInitTypeDef TIM_ICInitStructure;
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == SET)
{
/* Clear TIM3 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
//每次進(jìn)入中斷就改變捕獲觸發(fā)方式,且翻轉(zhuǎn)PD2的電平
if(flag==0)
{
flag=1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_RESET);
}
else
{
flag=0;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_SET);
}
}
}
程序運(yùn)行后,可以看到板子上兩個(gè)led燈交替閃爍。
我并沒(méi)有對(duì)捕獲值作任何處理,因?yàn)槲抑皇菧y(cè)試程序是否能順利進(jìn)入捕獲中斷。
評(píng)論