STM32F4 TIM輸入捕獲(測頻)【使用庫函數】


在輸入捕獲模式下,當檢測到ICx信號上升/下降邊沿時,計數器的當前值被存儲在捕獲比較寄存器TIMx_CCRx中。

當捕獲事件發生時,相應的CCxIF 標志(TIMx_SR 寄存器) 被置1。如果中斷或者DMA功能被使能,就會產生中斷或者DMA請求。如果捕獲發生時,CCxIF標志已經被置位,這時過采樣標志CCxOF就會被置位。向CCxIF寫0或者讀去TIM_CCRx中的數據,將清除捕獲標志。CCxOF位只能通過手動寫入0進行清除。

假如我設置為上升沿捕獲,那么當一個上升沿到來的時候,定時器當前的計數值(TIMx_CNT)就會寫入TIMx_CCRx中。我們讀取這個數據。等到下一個上升沿到了時,就會有另一個計數器值TIMx_CNT記錄。根據這兩個數據值差,我們能算出來輸入數據的周期。當然,我們還有處理定時器溢出這個問題,定時器溢出了就不准了。

如果要測占空比,就需要同時捕獲上升沿和下降沿。相鄰兩個上升沿之間的計數是輸入的周期,相鄰兩次捕獲(一個上升沿一個下降沿)之間的時間是占或者空的時間。根據這個可以計算占空比或者PPM之類的東西。

【實驗內容】

本次實驗,使用TIM4產生一個1K的頻率輸出,用TIM1進行捕獲。並測出頻率計算

TIM1 的時基單元配置:關於TIM1的時基設置問題前文已經討論過了。這里只有一點需要明確的,就是為了盡量減少更新事件,將TIM_Period設置到最大即0xFFFF。定時器時鍾設置成2M,這樣定時器的更新頻率就是30Hz,不會造成兩次捕獲之間產生多次更新。

TIM1的完整配置代碼如下:

void TIM1_ICConfig(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
//   //時基初始化
  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //死區控制用。
  TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  //計數器方向
  TIM_TimeBaseInitStructure.TIM_Prescaler = 84-1;   //Timer clock = sysclock /(TIM_Prescaler+1) = 2M
  TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInitStructure.TIM_Period = 0xFFFF;    //Period = (TIM counter clock / TIM output clock) - 1 = 40Hz 
  TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  TIM_ICInitStructure.TIM_ICFilter = 0;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

  TIM_ICInit(TIM1,&TIM_ICInitStructure);
  TIM_Cmd(TIM1,ENABLE);
}

TIM4的配置就是基本的輸出配置,沒什么可說的。代碼如下:

void TIM4_OCConfig(void)
{
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInitStructure.TIM_Prescaler =  0;
  TIM_TimeBaseInitStructure.TIM_RepetitionCounter =0;
  TIM_TimeBaseInitStructure.TIM_Period = 42000-1;   //周期:42M/(42000)= 1K
 
  TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
 
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 10000;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
 
  TIM_OC1Init(TIM4,&TIM_OCInitStructure);
  TIM_Cmd(TIM4,ENABLE);
}

這個輸出頻率,在示波器上可以看到的:

IMAG2208

之后就是在主函數里邊進行測量了:

CaptureNumber = 0;
 
while(1)
{
    if(TIM_GetFlagStatus(TIM1,TIM_FLAG_CC1)==SET)
    {
       TIM_ClearFlag(TIM1,TIM_FLAG_CC1);
       if(CaptureNumber == 0)
       {
         counter = TIM_GetCapture1(TIM1);  //第一次捕獲
         CaptureNumber = 1;
        
       }
       else if(CaptureNumber == 1)  //處理第二次捕獲
       {
         if(TIM_GetFlagStatus(TIM1,TIM_FLAG_Update) != SET)//兩次捕獲間沒有發生溢出的處理
         {
           Time = TIM_GetCapture1(TIM1);
           Time = Time - counter;
         }
         else
         {
           TIM_ClearFlag(TIM1,TIM_FLAG_Update);   //產生了更新事件
           Time = 0xFFFF - counter + TIM_GetCapture1(TIM1)+1;  //如果有更新事件產生時候的計算方式
         }
         CaptureNumber = 0;
         if(Time!=0)
         {
           freq= 2000000/Time;  //計算頻率
         }
         freq = freq;  //避免變量freq被編譯器優化掉
       }
    }
}


免責聲明!

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



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