新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > stm32庫(kù)函數(shù)學(xué)習(xí)篇通用定時(shí)器輸入捕獲功能

stm32庫(kù)函數(shù)學(xué)習(xí)篇通用定時(shí)器輸入捕獲功能

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
實(shí)現(xiàn)功能:PA8隨意延時(shí)驅(qū)動(dòng)led燈閃爍,并且將PA8用杜邦線連接到PA7口,PA7是通用定時(shí)器TIM3的2通道,在TIM3_CH2觸發(fā)中斷程序中取反連接到PD2口的led燈,指示中斷程序運(yùn)行,并且每次進(jìn)入中斷后改變觸發(fā)捕獲的極性。實(shí)現(xiàn)兩個(gè)led燈會(huì)交替閃爍。

本文引用地址:http://butianyuan.cn/article/201611/318488.htm

先有必要了解stm32定時(shí)器的輸入觸發(fā)模塊,如下圖:

需要注意的是,一眼望去一個(gè)定時(shí)器似乎有8個(gè)通道,左邊四個(gè),右邊四個(gè),但其實(shí)左邊和右邊是共用相同的IO引腳,所以名稱(chēng)標(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ō)明了,在我前面的文章有專(zhuān)門(mén)介紹。下面就重點(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);

//開(kāi)啟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)論


技術(shù)專(zhuān)區(qū)

關(guān)閉