最近學(xué)校電賽隊(duì)伍招新,出的招新題就是低頻示波器的。之前一直沒有弄懂FFT,借著這次機(jī)會(huì)實(shí)現(xiàn)了一下,做了一個(gè)小示波器
- FFT原理簡(jiǎn)述
FFT,就是快速傅里葉變換,這個(gè)操作能夠?qū)r(shí)域信號(hào)轉(zhuǎn)化成頻域信號(hào),然后對(duì)信號(hào)進(jìn)行分析
這樣說可能有點(diǎn)抽象。講細(xì)點(diǎn)就是指能夠直觀的看出來目標(biāo)信號(hào)的頻率是多少。x軸坐標(biāo)本來是表示時(shí)間,F(xiàn)FT之后變成了表示頻率,就是這個(gè)意思
對(duì)于信號(hào)處理,F(xiàn)FT之后的結(jié)果,波峰一般會(huì)出現(xiàn)在我們希望測(cè)得信號(hào)的頻率附近(十分相近)
- 官方文件解釋
stm32官方給了幾個(gè)用于處理FFT的文件,如圖所示:
其中有兩個(gè)匯編文件兩個(gè)頭文件:匯編文件是定義了FFT的計(jì)算函數(shù),我們直接調(diào)用即可
cr4_fft_1024_stm32.s是包含了計(jì)算1024個(gè)點(diǎn)的FFT的函數(shù)的匯編文件,另一個(gè)匯編文件同理
stm32_dsp.h里面有關(guān)于FFT處理函數(shù)的聲明,我們包含了這個(gè)頭文件之后直接調(diào)用函數(shù)即可
補(bǔ)充:stm32_dsp.h當(dāng)中有一個(gè)include的頭文件,需要根據(jù)情況進(jìn)行修改,比如說用其他型號(hào)板子或者其他庫開發(fā)的記得要修改,不然編譯時(shí)會(huì)報(bào)錯(cuò)
- 算法解釋
//進(jìn)行FFT運(yùn)算等操作
void FFT_Wave(void)
{
u16 i;
float mid_value;
while(!ADC_flag)
{
LED1 = !LED1;
delay_ms(100);
}
ADC_flag = 0;
//獲取最大值最小值
adc_value_max = adc_value_min = ADC_buff[1];
for(i = 0;i < NPT;i++)
{
//尋找最大值最小值
if(ADC_buff[i] >= adc_value_max)
{
adc_value_max = ADC_buff[i];
}
if(ADC_buff[i] <= adc_value_min)
{
adc_value_min = ADC_buff[i];
}
//先清空數(shù)組
fftin[i] = 0;
//移位,讓后面16位為虛部
fftin[i] = ((s16)ADC_buff[i] << 16);
}
cr4_fft_1024_stm32(fftout,fftin,1024);//FFT
GetPowerMag();
//計(jì)算電壓值
Vpp_true = (adc_value_max - adc_value_min) * 3.3 / 4096.0;//獲得Vpp值
mid_value = (adc_value_max + adc_value_min) / 2;
for(int i = 0;i < NPT;i++)
{
if(ADC_buff[i] > mid_value)
{
rect_duty++;
}
}
rect_duty = rect_duty / 1024 * 100;
}
這是FFT的主體函數(shù)
第一步我們先要等待ADC采集完成,將數(shù)據(jù)存入數(shù)組當(dāng)中準(zhǔn)備進(jìn)行處理
第二步是在采樣值當(dāng)中尋找最大值和最小值(遍歷數(shù)組即可)
第三步是對(duì)數(shù)組進(jìn)行移位處理(前面的是實(shí)部,后面的是虛部,由于我們采集到的電壓都是實(shí)數(shù),所以虛部都置0)
第四步是使用ST官方提供的函數(shù)進(jìn)行FFT運(yùn)算,得到運(yùn)算之后的數(shù)組
第五步是根據(jù)頻譜查找我們信號(hào)所對(duì)應(yīng)的頻率,也就是對(duì)頻譜圖當(dāng)中所有的頻率進(jìn)行幅值的比較,找出幅值最大時(shí)所對(duì)應(yīng)的頻率,即為我們所需要測(cè)量的頻率,其他的都可以看作噪聲
在我們找到該頻率之后,不能立刻輸出,要與ADC的采樣率相乘再除以1024,之后才能得到我們想要的信號(hào)頻率
GetPowerMag函數(shù)定義如下:
void GetPowerMag(void)
{
s16 lX,lY;
u32 i;
float maxmag;
for(i = 0;i < NPT / 2;i++)
{
lX = (fftout[i] << 16) >> 16;
lY = (fftout[i] >> 16);
float X = 1024 * ((float)lX) / 32768;
float Y = 1024 * ((float)lY) / 32768;
float mag = sqrt(X * X + Y * Y) / 1024;
FFT_Mag[i] = (u32)(mag * 65536);
}
FFT_Mag[0] >>= 1;//頻譜圖第一個(gè)是直流分量,無需乘2
for(int i = 0;i < NPT / 2;i++)
{
if((maxmag < FFT_Mag[i]) && (i != 0))
{
maxmag = FFT_Mag[i];
temp = i;
}
}
F_hz = temp * sampling_rate / 1024.0;
}
至此,我們就得到了我們所需信號(hào)的頻率
鑒于本小白能力有限,如果有紕漏或改進(jìn)之處,歡迎指正
特別提醒:ADC采樣率應(yīng)遵循奈奎斯特采樣定理!采樣率不是越高越好(因?yàn)椴蓸勇侍邥?huì)降低采樣的精度,采樣率太低會(huì)導(dǎo)致高頻信號(hào)發(fā)生混疊現(xiàn)象)!
這個(gè)是上面用到的匯編文件的百度盤分享鏈接,失效了可以私聊cue我更新文章來源:http://www.zghlxwxcb.cn/news/detail-632220.html
鏈接:https://pan.baidu.com/s/1n8Hl09SmLhp963-vYbA2iw?pwd=1234?
提取碼:1234?文章來源地址http://www.zghlxwxcb.cn/news/detail-632220.html
到了這里,關(guān)于stm32F103RCT6使用FFT運(yùn)算分析波形詳解(細(xì)致教學(xué))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!