|
上一章介紹了利用STM32的TIM的捕獲功能實(shí)現(xiàn)頻率測(cè)量的方法,但測(cè)量誤差受被測(cè)信號(hào)頻率的影響,不適合測(cè)量頻率變化較大的 。本章將介紹等精度測(cè)頻的方法以及STM32的實(shí)現(xiàn)。
STM32硬件電路板及仿真器(以STM32F072C8單片機(jī)為例) Keil v5以上版本(MDK-ARM)
基本原理
首先看一張圖:
50j043olh5c64048945230.png (20.29 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
50j043olh5c64048945230.png
2024-10-5 23:00 上傳
傳統(tǒng)的測(cè)頻方式,閘門放時(shí)間是固定的,閘門時(shí)間內(nèi)被測(cè)信號(hào)的計(jì)數(shù)個(gè)數(shù)Nx不一定是整數(shù)個(gè),因此會(huì)有一定的誤差,且誤差與被測(cè)信號(hào)頻率有關(guān)。而等精度測(cè)頻的方法,閘門時(shí)間不是固定的,而是被測(cè)信號(hào)的整數(shù)倍。 因此消除了對(duì)被測(cè)信號(hào)計(jì)數(shù)的±1誤差,其誤差只與標(biāo)準(zhǔn)信號(hào)的計(jì)數(shù)個(gè)數(shù)Ns的±1誤差有關(guān)。可以看出,閘門時(shí)間越長(zhǎng),標(biāo)準(zhǔn)頻率Fs越大,Ns的計(jì)數(shù)值越大,±1誤差的影響就小。在相同的閘門時(shí)間內(nèi),被測(cè)信號(hào)的頻率Fx=Nx*Fs/Ns。
STM32的實(shí)現(xiàn)
實(shí)現(xiàn)等精度測(cè)頻用到兩個(gè)定時(shí)器,其中一個(gè)定時(shí)器用于產(chǎn)生閘門時(shí)間,另外一個(gè)用于捕獲被測(cè)信號(hào)和標(biāo)準(zhǔn)信號(hào)計(jì)數(shù)。
實(shí)現(xiàn)步驟:
TIM1設(shè)置約1秒的閘門時(shí)間。TIM3捕獲到被測(cè)信號(hào)上升沿后,將TIM1計(jì)數(shù)器清零。閘門時(shí)間開始,TIM3開始捕獲計(jì)數(shù)同時(shí)本身計(jì)數(shù)器也開始計(jì)數(shù)。閘門時(shí)間到后,標(biāo)志置位。TIM3檢測(cè)到標(biāo)志置位且捕獲到上升沿后,記錄當(dāng)前捕獲計(jì)數(shù)的值Nx和本身計(jì)數(shù)器的計(jì)數(shù)值Ns。計(jì)算被測(cè)信號(hào)頻率Fx=Nx*Fs/Ns,其中Fs為定時(shí)器時(shí)鐘頻率48MHz。[/ol]
STM32CubeMX的TIM配置如下:
gfkcpzrrpdu64048945330.jpg (284.48 KB, 下載次數(shù): 1)
下載附件
保存到相冊(cè)
gfkcpzrrpdu64048945330.jpg
2024-10-5 23:00 上傳
TIM1作為產(chǎn)生閘門時(shí)間的定時(shí)器,其計(jì)數(shù)周期設(shè)置為47999,時(shí)鐘為系統(tǒng)時(shí)鐘,1000分頻。則溢出周期即閘門時(shí)間為1秒,打開溢出中斷:
sbcb1is1eyj64048945430.png (20.6 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
sbcb1is1eyj64048945430.png
2024-10-5 23:00 上傳
TIM3作為捕獲被測(cè)信號(hào)的定時(shí)器,其配置如下,通道1設(shè)置為捕獲模式,捕獲上升沿,定時(shí)周期設(shè)置為最大65535,時(shí)鐘為系統(tǒng)時(shí)鐘,不分頻。打開中斷(TIM3捕獲和溢出為同一個(gè)中斷)。
iasacpombgt64048945530.png (20.98 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
iasacpombgt64048945530.png
2024-10-5 23:00 上傳
hguccb04syy64048945630.jpg (246.09 KB, 下載次數(shù): 0)
下載附件
保存到相冊(cè)
hguccb04syy64048945630.jpg
2024-10-5 23:00 上傳
程序?qū)崿F(xiàn):
按照之前介紹的步驟設(shè)置其它外設(shè),并生成代碼。初始化后,啟動(dòng)TIM1和TIM3中斷。
HAL_TIM_Base_Start_IT(&htim1); HAL_TIM_Base_Start_IT(&htim3); HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);編寫中斷回調(diào)函數(shù)。
#define Fs 48000000L //定時(shí)器時(shí)鐘頻率uint32_t TIM3_Cnt_Value[2];//定時(shí)器3捕獲值uint32_t TIM3_Over_Cnt=0;//定時(shí)器3溢出次數(shù)uint32_t TIM1_Over_Flag=0;//定時(shí)器1溢出標(biāo)志uint32_t Ns,Nx;//標(biāo)志信號(hào)計(jì)數(shù)值 被測(cè)信號(hào)計(jì)數(shù)值double Fx;//被測(cè)頻率
//定時(shí)器溢出中斷 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; }
}
//定時(shí)器捕獲中斷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清零 開始閘門時(shí)間 TIM3_Cnt_Value[0] = __HAL_TIM_GET_COUNTER(&htim3); Nx++; } else if(TIM1_Over_Flag == 1)//閘門時(shí)間到 { Nx++; TIM3_Cnt_Value[1] = __HAL_TIM_GET_COUNTER(&htim3); Ns = (TIM3_Over_Cnt16) + TIM3_Cnt_Value[1] - TIM3_Cnt_Value[0];//計(jì)算標(biāo)準(zhǔn)信號(hào)的計(jì)數(shù)值 TIM1_Over_Flag = 2;//一次測(cè)量完成 標(biāo)志置位 } }}//計(jì)算被測(cè)頻率void CalcFx(void){ if(TIM1_Over_Flag == 2) { Fx = (double)Nx * Fs / Ns;//計(jì)算頻率 Nx=0; //計(jì)數(shù)清零 TIM1_Over_Flag = 0;//標(biāo)志清零,可以開始下一次測(cè)量 }}
在主函數(shù)中調(diào)用CalcFx()函數(shù)即可獲取被測(cè)信號(hào)的頻率。
以上即為利用STM32定時(shí)器實(shí)現(xiàn)等精度測(cè)頻的全部?jī)?nèi)容,STM32定時(shí)器的功能還有很多,如觸發(fā)ADC采樣、編碼器模式等。不再一一做介紹,下一章開始介紹STM32串口的使用方法,敬請(qǐng)期待。 |
|