新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > stm32庫函數學習篇通用定時器輸入捕獲功能

        stm32庫函數學習篇通用定時器輸入捕獲功能

        作者: 時間:2016-11-19 來源:網絡 收藏
        實現功能:PA8隨意延時驅動led燈閃爍,并且將PA8用杜邦線連接到PA7口,PA7是通用定時器TIM3的2通道,在TIM3_CH2觸發中斷程序中取反連接到PD2口的led燈,指示中斷程序運行,并且每次進入中斷后改變觸發捕獲的極性。實現兩個led燈會交替閃爍。

        本文引用地址:http://www.104case.com/article/201611/318488.htm

        先有必要了解stm32定時器的輸入觸發模塊,如下圖:

        需要注意的是,一眼望去一個定時器似乎有8個通道,左邊四個,右邊四個,但其實左邊和右邊是共用相同的IO引腳,所以名稱標注是一模一樣。也就是說,每個通用定時器都只有四個獨立通道,當某一通道作為了輸入觸發功能那就不能再作為輸出匹配功能。這一點我們也可以從其他地方找到印證。比如TIM_ITConfig()函數中如下:

        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

        我們可以看到此函數TIM_IT參數的取值范圍如下:

        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

        也就是說每個通道的捕獲和比較功能是共用一個中斷標志。

        stm32定時器輸入觸發功能其實挺簡單的,與AVR單片機幾乎一樣。就是單片機引腳上一旦出現一個有效邊沿(可以配置為上升、下降或者上升下降均觸發),那么定時器計數器CNT里面的值就會被相應的Capture/Compare X Register保存下來。這里X可以是1,2,3,4任何一個。并且中斷標志位被置位。但是此時TIM的計數寄存器CNT卻不管這一事件的發生,繼續自己的計數。此功能可以用來測量外部信號的脈寬或者是周期。

        對于定時器的時基單元TIM_TimeBaseStructure就不作說明了,在我前面的文章有專門介紹。下面就重點講解輸入觸發單元TIM_ICInitStructure。

        首先看次結構體原型的定義如下:

        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個成員,5個成員具體作用,我們只要看看3.5版本固件庫的說明就清楚了。

        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

        說實話這個成員具體作用我沒有深入了解,僅僅知道是作為對輸入信號的濾波作用,估計是讓用戶設定用多少個采樣時鐘來確定最終輸入信號,起到濾波作用,避免高頻信號干擾,反正不管它了。

        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

        這個就是觸發邊沿的極性選擇了,取值范圍如下:

        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

        這個成員是對外部信號進行分頻,也即是設置上圖中的Prescaler,可以設置為1/2/4/8分頻。

        uint16_t TIM_ICInitTypeDef::TIM_ICSelection

        Specifies the input. This parameter can be a value of TIM_Input_Capture_Selection

        這個成員的作用就必須要對照上面的示意圖才能明白。仔細看上面的圖,可以發現定時器的4個通道并不是完全獨立的,而是1、2一組,3、4一組,同組之間的通道是有聯系的。也就是可以出現交叉觸發。而TIM_ICSelection就是選擇要不要使用交叉來觸發,如果不明白可以看固件庫的說明文檔,如下是此結構體成員的取值范圍:

        #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.

        也就是說,根據不同的取值,可以講外部引腳的觸發信號連到內部不同的單元,這樣就使得單片機更加靈活了。

        下面是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; //隨意延時led取反,且將PA8作為觸發定時器電平

        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; //觸發中斷時,取反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; //先占優先級0級

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級3級

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

        NVIC_Init(&NVIC_InitStructure); //根據NVIC_InitStruct中指定的參數初始化外設NVIC寄存器

        }

        void tim3_cfg()

        {

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

        TIM_DeInit(TIM3);

        TIM_InternalClockConfig(TIM3);

        //預分頻系數為36000-1,這樣計數器時鐘為72MHz/36000 = 2kHz

        TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1;

        //設置時鐘分割

        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

        //設置計數器模式為向上計數模

        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

        //設置計數溢出大小,每計2000個數就產生一個更新事件

        TIM_TimeBaseStructure.TIM_Period = 2000 - 1;

        //將配置應用到TIM2中

        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

        //禁止ARR預裝載緩沖器

        TIM_ARRPreloadConfig(TIM3, DISABLE);

        //下面是對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; /*選擇輸入比較濾波器,濾波設置,經歷幾個周期跳變認定波形穩定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外設

        }

        /

        * @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();

        }

        }

        注意定時器3通道2引腳設置為浮空輸入。

        下面是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);

        //每次進入中斷就改變捕獲觸發方式,且翻轉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);

        }

        }

        }

        程序運行后,可以看到板子上兩個led燈交替閃爍。

        我并沒有對捕獲值作任何處理,因為我只是測試程序是否能順利進入捕獲中斷。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 仙桃市| 青岛市| 杭锦旗| 平果县| 石泉县| 上饶市| 大新县| 临沂市| 岳普湖县| 彝良县| 南投市| 苍南县| 屯昌县| 班玛县| 洪洞县| 建昌县| 醴陵市| 博白县| 滨州市| 汤阴县| 吉林市| 鄱阳县| 喀喇沁旗| 松江区| 哈巴河县| 水城县| 大埔县| 甘南县| 汉川市| 邢台县| 堆龙德庆县| 华蓥市| 浦东新区| 皮山县| 惠水县| 慈溪市| 剑川县| 西盟| 汤阴县| 冕宁县| 民丰县|