電子產業(yè)一站式賦能平臺

PCB聯(lián)盟網

搜索
查看: 30|回復: 0
收起左側

STM32實現(xiàn)等精度測頻

[復制鏈接]

454

主題

454

帖子

2398

積分

三級會員

Rank: 3Rank: 3

積分
2398
跳轉到指定樓層
樓主
發(fā)表于 2020-3-17 23:21:00 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
上一章介紹了利用STM32的TIM的捕獲功能實現(xiàn)頻率測量的方法,但測量誤差受被測信號頻率的影響,不適合測量頻率變化較大的 。本章將介紹等精度測頻的方法以及STM32的實現(xiàn)。

  •     STM32硬件電路板及仿真器(以STM32F072C8單片機為例)
  •     Keil v5以上版本(MDK-ARM)

    基本原理
    首先看一張圖:

    傳統(tǒng)的測頻方式,閘門放時間是固定的,閘門時間內被測信號的計數(shù)個數(shù)Nx不一定是整數(shù)個,因此會有一定的誤差,且誤差與被測信號頻率有關。而等精度測頻的方法,閘門時間不是固定的,而是被測信號的整數(shù)倍。 因此消除了對被測信號計數(shù)的±1誤差,其誤差只與標準信號的計數(shù)個數(shù)Ns的±1誤差有關?梢钥闯,閘門時間越長,標準頻率Fs越大,Ns的計數(shù)值越大,±1誤差的影響就小。在相同的閘門時間內,被測信號的頻率Fx=Nx*Fs/Ns。

    STM32的實現(xiàn)
    實現(xiàn)等精度測頻用到兩個定時器,其中一個定時器用于產生閘門時間,另外一個用于捕獲被測信號和標準信號計數(shù)。
    實現(xiàn)步驟:
    TIM1設置約1秒的閘門時間。TIM3捕獲到被測信號上升沿后,將TIM1計數(shù)器清零。閘門時間開始,TIM3開始捕獲計數(shù)同時本身計數(shù)器也開始計數(shù)。閘門時間到后,標志置位。TIM3檢測到標志置位且捕獲到上升沿后,記錄當前捕獲計數(shù)的值Nx和本身計數(shù)器的計數(shù)值Ns。計算被測信號頻率Fx=Nx*Fs/Ns,其中Fs為定時器時鐘頻率48MHz。[/ol]
    STM32CubeMX的TIM配置如下:

    TIM1作為產生閘門時間的定時器,其計數(shù)周期設置為47999,時鐘為系統(tǒng)時鐘,1000分頻。則溢出周期即閘門時間為1秒,打開溢出中斷:

    TIM3作為捕獲被測信號的定時器,其配置如下,通道1設置為捕獲模式,捕獲上升沿,定時周期設置為最大65535,時鐘為系統(tǒng)時鐘,不分頻。打開中斷(TIM3捕獲和溢出為同一個中斷)。




    程序實現(xiàn):
    按照之前介紹的步驟設置其它外設,并生成代碼。初始化后,啟動TIM1和TIM3中斷。
  •   HAL_TIM_Base_Start_IT(&htim1);  HAL_TIM_Base_Start_IT(&htim3);  HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);編寫中斷回調函數(shù)。
  • #define Fs 48000000L  //定時器時鐘頻率uint32_t TIM3_Cnt_Value[2];//定時器3捕獲值uint32_t TIM3_Over_Cnt=0;//定時器3溢出次數(shù)uint32_t TIM1_Over_Flag=0;//定時器1溢出標志uint32_t Ns,Nx;//標志信號計數(shù)值  被測信號計數(shù)值double Fx;//被測頻率
    //定時器溢出中斷 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
      if(htim->Instance == TIM1)  {    TIM1_Over_Flag = 1;  }  if(htim->Instance == TIM3)  {    TIM3_Over_Cnt++;    if(TIM3_Over_Cnt==0xffffffff)TIM3_Over_Cnt=0xfffffffe;  }
    }
    //定時器捕獲中斷void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){  if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)  {    if(TIM1_Over_Flag == 0)    {      __HAL_TIM_SET_COUNTER(&htim1,0);//TIM1清零 開始閘門時間      TIM3_Cnt_Value[0] = __HAL_TIM_GET_COUNTER(&htim3);      Nx++;    }    else if(TIM1_Over_Flag == 1)//閘門時間到    {      Nx++;      TIM3_Cnt_Value[1] = __HAL_TIM_GET_COUNTER(&htim3);      Ns = (TIM3_Over_Cnt16) + TIM3_Cnt_Value[1] - TIM3_Cnt_Value[0];//計算標準信號的計數(shù)值      TIM1_Over_Flag = 2;//一次測量完成 標志置位    }  }}//計算被測頻率void CalcFx(void){  if(TIM1_Over_Flag == 2)  {    Fx = (double)Nx * Fs / Ns;//計算頻率    Nx=0; //計數(shù)清零    TIM1_Over_Flag = 0;//標志清零,可以開始下一次測量  }}
    在主函數(shù)中調用CalcFx()函數(shù)即可獲取被測信號的頻率。
    以上即為利用STM32定時器實現(xiàn)等精度測頻的全部內容,STM32定時器的功能還有很多,如觸發(fā)ADC采樣、編碼器模式等。不再一一做介紹,下一章開始介紹STM32串口的使用方法,敬請期待。
  • 回復

    使用道具 舉報

    發(fā)表回復

    您需要登錄后才可以回帖 登錄 | 立即注冊

    本版積分規(guī)則


    聯(lián)系客服 關注微信 下載APP 返回頂部 返回列表