[STM32F10x] 利用定時器測量脈沖寬度


硬件: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。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM