|
上一章介紹了利用STM32的TIM的捕獲功能實現(xiàn)頻率測量的方法,但測量誤差受被測信號頻率的影響,不適合測量頻率變化較大的 。本章將介紹等精度測頻的方法以及STM32的實現(xiàn)。
STM32硬件電路板及仿真器(以STM32F072C8單片機為例) Keil v5以上版本(MDK-ARM)
基本原理
首先看一張圖:
50j043olh5c64048945230.png (20.29 KB, 下載次數(shù): 0)
下載附件
保存到相冊
50j043olh5c64048945230.png
2024-10-5 23:00 上傳
傳統(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配置如下:
gfkcpzrrpdu64048945330.jpg (284.48 KB, 下載次數(shù): 1)
下載附件
保存到相冊
gfkcpzrrpdu64048945330.jpg
2024-10-5 23:00 上傳
TIM1作為產生閘門時間的定時器,其計數(shù)周期設置為47999,時鐘為系統(tǒng)時鐘,1000分頻。則溢出周期即閘門時間為1秒,打開溢出中斷:
sbcb1is1eyj64048945430.png (20.6 KB, 下載次數(shù): 1)
下載附件
保存到相冊
sbcb1is1eyj64048945430.png
2024-10-5 23:00 上傳
TIM3作為捕獲被測信號的定時器,其配置如下,通道1設置為捕獲模式,捕獲上升沿,定時周期設置為最大65535,時鐘為系統(tǒng)時鐘,不分頻。打開中斷(TIM3捕獲和溢出為同一個中斷)。
iasacpombgt64048945530.png (20.98 KB, 下載次數(shù): 0)
下載附件
保存到相冊
iasacpombgt64048945530.png
2024-10-5 23:00 上傳
hguccb04syy64048945630.jpg (246.09 KB, 下載次數(shù): 0)
下載附件
保存到相冊
hguccb04syy64048945630.jpg
2024-10-5 23:00 上傳
程序實現(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串口的使用方法,敬請期待。 |
|