加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 3.1 基于python生成數(shù)據(jù)源
    • 3.2 基于C驗(yàn)證算法
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

嵌入式算法16:傅里葉變換算法

2022/03/12
762
閱讀需 59 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

摘要:傅里葉變換的核心在于,“任何連續(xù)周期信號(hào)可以由一組適當(dāng)?shù)恼仪€組合而成”,在這個(gè)基礎(chǔ)上對(duì)信號(hào)的中特定頻率的正弦波進(jìn)行分解或者重組,基于頻率方面分析波形。

1、傅里葉變換的意義

近似周期性的方波(橙色),可采用6組正弦波(藍(lán)色)合成,這是傅里葉的基礎(chǔ)。

對(duì)數(shù)字信號(hào)處理或者工程數(shù)學(xué)有一定基礎(chǔ),就明白傅里葉變換的價(jià)值。一般情況下的信號(hào)或者波形隨時(shí)間變化,稱為時(shí)域信號(hào),時(shí)域(Time domain)是描述數(shù)學(xué)函數(shù)或物理信號(hào)對(duì)時(shí)間的關(guān)系。而以頻率和幅度表示信號(hào)稱為頻域,頻域(frequency domain)是描述信號(hào)在頻率方面特性時(shí)用到的一種坐標(biāo)系。其數(shù)學(xué)理論上暫且不理,針對(duì)嵌入式系統(tǒng)開(kāi)發(fā),只探討其物理意義或者應(yīng)用場(chǎng)景。

時(shí)域和頻域是信號(hào)的基本性質(zhì),時(shí)域的表示較為形象與直觀,比較符合一般認(rèn)知,而頻域分析則更為簡(jiǎn)練,剖析問(wèn)題更為深刻和方便。

例如下圖的左側(cè)時(shí)域信號(hào),其可以分解為2路正弦波的疊加效果,右側(cè)為頻域信號(hào),表示2路正弦波的頻率和幅度。傅里葉變化可簡(jiǎn)單理解為求解一段信號(hào)或波形,由哪些正弦波組成,也可以反向推導(dǎo)多路正弦波合并后的效果。

 

基于動(dòng)畫形式表現(xiàn)如下:

 

傅里葉變換是一種信號(hào)分析方法,讓我們對(duì)信號(hào)的構(gòu)成和特點(diǎn)進(jìn)行深入的、定量的研究。把信號(hào)通過(guò)頻譜的方式進(jìn)行準(zhǔn)確的、定量的描述。將原來(lái)難以處理的時(shí)域信號(hào)轉(zhuǎn)換成了易于分析的頻域信號(hào),即傅里葉變換的核心是從時(shí)域到頻域的變換。

2、變換方式

數(shù)字信號(hào)屬于離散值,對(duì)應(yīng)的稱為離散傅里葉變換(DFT),是傅里葉變換在時(shí)域和頻域上都呈現(xiàn)離散的形式,將時(shí)域信號(hào)的采樣變換為在離散時(shí)間傅里葉變換(DTFT)頻域的采樣。在形式上,變換兩端(時(shí)域和頻域上)的序列是有限長(zhǎng)的,而實(shí)際上這兩組序列都應(yīng)當(dāng)被認(rèn)為是離散周期信號(hào)的主值序列。即使對(duì)有限長(zhǎng)的離散信號(hào)作DFT,也應(yīng)當(dāng)將其看作經(jīng)過(guò)周期延拓成為周期信號(hào)再作變換。

在實(shí)際應(yīng)用中通常采用快速傅里葉變換以高效計(jì)算效率,快速傅里葉變換 FFT(Fast Fourier Transformation)是離散傅里葉變換 DFT(Discrete Fourier Transform)的快速算法。采用這種算法能使計(jì)算機(jī)計(jì)算離散傅里葉變換所需要的乘法次數(shù)大為減少,特別是被變換的抽樣點(diǎn)數(shù)N越多,F(xiàn)FT算法計(jì)算量的節(jié)省就越顯著。同理,從頻域到時(shí)域的變換,稱為逆變換,快速傅里葉逆變換 IFFT和離散傅里葉逆變換IDFT。

3、應(yīng)用

一般嵌入式系統(tǒng)使用快速傅里葉變換是分析某段信號(hào)中混合的雜波干擾,或者剔除某個(gè)頻段后再逆變換。有些高端示波器可以對(duì)信號(hào)快速傅里葉變換 FFT,直接顯示高頻雜波的頻率或者較大幅度干擾源的頻率,以便由針對(duì)性的檢查電路竄擾。本文主要是講解使用fft/ifft進(jìn)行干擾信號(hào)的過(guò)濾。

1、python生成正弦波,以及混合波形,提取數(shù)值作為c語(yǔ)言FFT/IFFT的數(shù)據(jù)源 

2、先進(jìn)行FFT,輸出幅頻數(shù)據(jù),導(dǎo)入Excel看看效果 

3、對(duì)數(shù)據(jù)進(jìn)行簡(jiǎn)單過(guò)濾

4、過(guò)濾后的數(shù)據(jù)進(jìn)行IFFT運(yùn)算,再導(dǎo)入Excel看還原的效果 

5、關(guān)注微信公眾號(hào)  嵌入式系統(tǒng)

3.1 基于python生成數(shù)據(jù)源

# This is a Python script.

import numpy as np
import matplotlib.pyplot as plt
def sin_wave(A, f, fs, phi, t):
    '''
    :params A:    振幅
    :params f:    信號(hào)頻率
    :params fs:   采樣頻率
    :params phi:  相位
    :params t:    時(shí)間長(zhǎng)度
    '''
    # 若時(shí)間序列長(zhǎng)度為 t=1s,
    # 采樣頻率 fs=1000 Hz, 則采樣時(shí)間間隔 Ts=1/fs=0.001s
    # 采樣點(diǎn)個(gè)數(shù)為 n=t/Ts=1/0.001=1000, 即有1000個(gè)點(diǎn),每個(gè)點(diǎn)間隔為 Ts
    Ts = 1/fs
    n = t / Ts
    n = np.arange(n)
    y = A*np.sin(2*np.pi*f*n*Ts + phi*(np.pi/180))
    return y

fs = 360*40
my_sin1 = sin_wave(100, 100, fs=fs, phi=0, t=0.08)
my_sin2 = sin_wave(20, 500, fs=fs, phi=0, t=0.08)
my_sin3 = sin_wave(10, 1100, fs=fs, phi=0, t=0.08)

x = np.arange(0, 0.08, 1/fs)
plt.xlabel('x-t (samRate=14400)')
plt.ylabel('y-A')
plt.grid()
plt.plot(x, my_sin1, 'k--',label="f=100")
plt.plot(x, my_sin2, 'b--',label="f=500")
plt.plot(x, my_sin3, 'g--',label="f=1100")
plt.plot(x, my_sin1+my_sin2+my_sin3, 'r',label="mix")
plt.legend()
plt.show()

np.savetxt("sin.txt",my_sin1+my_sin2+my_sin3, fmt='%.06f')

def print_name(name):
    print(f'Hi, {name}')


if __name__ == '__main__':
    print_name('fft test')

 

生成的波形圖如下:

三種頻率的sin以及合成后的紅色曲線,變形的正弦波;同時(shí)也將數(shù)據(jù)存入文件sin.txt備用。

3.2 基于C驗(yàn)證算法

將前面生成的數(shù)據(jù)使用c語(yǔ)言的FFT/IFFT進(jìn)行處理,輸出結(jié)果,并導(dǎo)入Excels生成圖表展示效果。

#include <math.h>
#include <stdio.h>
#include "string.h"

typedef struct
{
    float real;
    float imag;
} complex_t;

#ifndef PI
#define PI             (3.14159265)
#endif

#define TYPE_FFT_E     float    /* Type is the same with complex_t member */

typedef complex_t TYPE_FFT;  /* Define complex_t in Config.h */
typedef unsigned int                      uint32_t;

#define     SAMPLE_NODES    (1024)
complex_t   fft_buff[SAMPLE_NODES];

//python生成的3個(gè)sin混合的波形數(shù)組
float my_sin_wave_table[] =
{
    0.000000,13.308217,25.359460,35.142296,42.082633,46.140080,47.788611,47.887148,47.470293,47.507139,48.682920,51.252751,
    55.000000,59.307883,63.326941,66.199152,67.286436,66.350198,63.639610,59.866963,56.074110,53.418823,52.928233,55.274323,
    60.621778,68.582540,78.287693,88.561119,98.156743,106.007043,111.428222,114.237346,114.756729,113.706291,112.009861,
    110.560634,110.000000,110.560634,112.009861,113.706291,114.756729,114.237346,111.428222,106.007043,98.156743,88.561119,
    78.287693,68.582540,60.621778,55.274323,52.928233,53.418823,56.074110,59.866963,63.639610,66.350198,67.286436,66.199152,
    63.326941,59.307883,55.000000,51.252751,48.682920,47.507139,47.470293,47.887148,47.788611,46.140080,42.082633,35.142296,
    25.359460,13.308217,0.000000,-13.308217,-25.359460,-35.142296,-42.082633,-46.140080,-47.788611,-47.887148,-47.470293,
    -47.507139,-48.682920,-51.252751,-55.000000,-59.307883,-63.326941,-66.199152,-67.286436,-66.350198,-63.639610,-59.866963,
    -56.074110,-53.418823,-52.928233,-55.274323,-60.621778,-68.582540,-78.287693,-88.561119,-98.156743,-106.007043,-111.428222,
    -114.237346,-114.756729,-113.706291,-112.009861,-110.560634,-110.000000,-110.560634,-112.009861,-113.706291,-114.756729,
    -114.237346,-111.428222,-106.007043,-98.156743,-88.561119,-78.287693,-68.582540,-60.621778,-55.274323,-52.928233,
    -53.418823,-56.074110,-59.866963,-63.639610,-66.350198,-67.286436,-66.199152,-63.326941,-59.307883,-55.000000,
    -51.252751,-48.682920,-47.507139,-47.470293,-47.887148,-47.788611,-46.140080,-42.082633,-35.142296,-25.359460,
    -13.308217,-0.000000,13.308217,25.359460,35.142296,42.082633,46.140080,47.788611,47.887148,47.470293,47.507139,
    48.682920,51.252751,55.000000,59.307883,63.326941,66.199152,67.286436,66.350198,63.639610,59.866963,56.074110,
    53.418823,52.928233,55.274323,60.621778,68.582540,78.287693,88.561119,98.156743,106.007043,111.428222,114.237346,
    114.756729,113.706291,112.009861,110.560634,110.000000,110.560634,112.009861,113.706291,114.756729,114.237346,
    111.428222,106.007043,98.156743,88.561119,78.287693,68.582540,60.621778,55.274323,52.928233,53.418823,56.074110,
    59.866963,63.639610,66.350198,67.286436,66.199152,63.326941,59.307883,55.000000,51.252751,48.682920,47.507139,
    47.470293,47.887148,47.788611,46.140080,42.082633,35.142296,25.359460,13.308217,0.000000,-13.308217,-25.359460,
    -35.142296,-42.082633,-46.140080,-47.788611,-47.887148,-47.470293,-47.507139,-48.682920,-51.252751,-55.000000,
    -59.307883,-63.326941,-66.199152,-67.286436,-66.350198,-63.639610,-59.866963,-56.074110,-53.418823,-52.928233,
    -55.274323,-60.621778,-68.582540,-78.287693,-88.561119,-98.156743,-106.007043,-111.428222,-114.237346,-114.756729,
    -113.706291,-112.009861,-110.560634,-110.000000,-110.560634,-112.009861,-113.706291,-114.756729,-114.237346,-111.428222,
    -106.007043,-98.156743,-88.561119,-78.287693,-68.582540,-60.621778,-55.274323,-52.928233,-53.418823,-56.074110,-59.866963,
    -63.639610,-66.350198,-67.286436,-66.199152,-63.326941,-59.307883,-55.000000,-51.252751,-48.682920,-47.507139,-47.470293,
    -47.887148,-47.788611,-46.140080,-42.082633,-35.142296,-25.359460,-13.308217,-0.000000,13.308217,25.359460,35.142296,
    42.082633,46.140080,47.788611,47.887148,47.470293,47.507139,48.682920,51.252751,55.000000,59.307883,63.326941,66.199152,
    67.286436,66.350198,63.639610,59.866963,56.074110,53.418823,52.928233,55.274323,60.621778,68.582540,78.287693,88.561119,
    98.156743,106.007043,111.428222,114.237346,114.756729,113.706291,112.009861,110.560634,110.000000,110.560634,112.009861,
    113.706291,114.756729,114.237346,111.428222,106.007043,98.156743,88.561119,78.287693,68.582540,60.621778,55.274323,
    52.928233,53.418823,56.074110,59.866963,63.639610,66.350198,67.286436,66.199152,63.326941,59.307883,55.000000,51.252751,
    48.682920,47.507139,47.470293,47.887148,47.788611,46.140080,42.082633,35.142296,25.359460,13.308217,0.000000,-13.308217,
    -25.359460,-35.142296,-42.082633,-46.140080,-47.788611,-47.887148,-47.470293,-47.507139,-48.682920,-51.252751,-55.000000,
    -59.307883,-63.326941,-66.199152,-67.286436,-66.350198,-63.639610,-59.866963,-56.074110,-53.418823,-52.928233,-55.274323,
    -60.621778,-68.582540,-78.287693,-88.561119,-98.156743,-106.007043,-111.428222,-114.237346,-114.756729,-113.706291,
    -112.009861,-110.560634,-110.000000,-110.560634,-112.009861,-113.706291,-114.756729,-114.237346,-111.428222,-106.007043,
    -98.156743,-88.561119,-78.287693,-68.582540,-60.621778,-55.274323,-52.928233,-53.418823,-56.074110,-59.866963,-63.639610,
    -66.350198,-67.286436,-66.199152,-63.326941,-59.307883,-55.000000,-51.252751,-48.682920,-47.507139,-47.470293,-47.887148,
    -47.788611,-46.140080,-42.082633,-35.142296,-25.359460,-13.308217,-0.000000,13.308217,25.359460,35.142296,42.082633,
    46.140080,47.788611,47.887148,47.470293,47.507139,48.682920,51.252751,55.000000,59.307883,63.326941,66.199152,67.286436,
    66.350198,63.639610,59.866963,56.074110,53.418823,52.928233,55.274323,60.621778,68.582540,78.287693,88.561119,98.156743,
    106.007043,111.428222,114.237346,114.756729,113.706291,112.009861,110.560634,110.000000,110.560634,112.009861,113.706291,
    114.756729,114.237346,111.428222,106.007043,98.156743,88.561119,78.287693,68.582540,60.621778,55.274323,52.928233,53.418823,
    56.074110,59.866963,63.639610,66.350198,67.286436,66.199152,63.326941,59.307883,55.000000,51.252751,48.682920,47.507139,
    47.470293,47.887148,47.788611,46.140080,42.082633,35.142296,25.359460,13.308217,0.000000,-13.308217,-25.359460,-35.142296,
    -42.082633,-46.140080,-47.788611,-47.887148,-47.470293,-47.507139,-48.682920,-51.252751,-55.000000,-59.307883,-63.326941,
    -66.199152,-67.286436,-66.350198,-63.639610,-59.866963,-56.074110,-53.418823,-52.928233,-55.274323,-60.621778,-68.582540,
    -78.287693,-88.561119,-98.156743,-106.007043,-111.428222,-114.237346,-114.756729,-113.706291,-112.009861,-110.560634,
    -110.000000,-110.560634,-112.009861,-113.706291,-114.756729,-114.237346,-111.428222,-106.007043,-98.156743,-88.561119,
    -78.287693,-68.582540,-60.621778,-55.274323,-52.928233,-53.418823,-56.074110,-59.866963,-63.639610,-66.350198,-67.286436,
    -66.199152,-63.326941,-59.307883,-55.000000,-51.252751,-48.682920,-47.507139,-47.470293,-47.887148,-47.788611,-46.140080,
    -42.082633,-35.142296,-25.359460,-13.308217,-0.000000,13.308217,25.359460,35.142296,42.082633,46.140080,47.788611,47.887148,
    47.470293,47.507139,48.682920,51.252751,55.000000,59.307883,63.326941,66.199152,67.286436,66.350198,63.639610,59.866963,
    56.074110,53.418823,52.928233,55.274323,60.621778,68.582540,78.287693,88.561119,98.156743,106.007043,111.428222,114.237346,
    114.756729,113.706291,112.009861,110.560634,110.000000,110.560634,112.009861,113.706291,114.756729,114.237346,111.428222,
    106.007043,98.156743,88.561119,78.287693,68.582540,60.621778,55.274323,52.928233,53.418823,56.074110,59.866963,63.639610,
    66.350198,67.286436,66.199152,63.326941,59.307883,55.000000,51.252751,48.682920,47.507139,47.470293,47.887148,47.788611,
    46.140080,42.082633,35.142296,25.359460,13.308217,0.000000,-13.308217,-25.359460,-35.142296,-42.082633,-46.140080,-47.788611,
    -47.887148,-47.470293,-47.507139,-48.682920,-51.252751,-55.000000,-59.307883,-63.326941,-66.199152,-67.286436,-66.350198,
    -63.639610,-59.866963,-56.074110,-53.418823,-52.928233,-55.274323,-60.621778,-68.582540,-78.287693,-88.561119,-98.156743,
    -106.007043,-111.428222,-114.237346,-114.756729,-113.706291,-112.009861,-110.560634,-110.000000,-110.560634,-112.009861,
    -113.706291,-114.756729,-114.237346,-111.428222,-106.007043,-98.156743,-88.561119,-78.287693,-68.582540,-60.621778,-55.274323,
    -52.928233,-53.418823,-56.074110,-59.866963,-63.639610,-66.350198,-67.286436,-66.199152,-63.326941,-59.307883,-55.000000,
    -51.252751,-48.682920,-47.507139,-47.470293,-47.887148,-47.788611,-46.140080,-42.082633,-35.142296,-25.359460,-13.308217,
    -0.000000,13.308217,25.359460,35.142296,42.082633,46.140080,47.788611,47.887148,47.470293,47.507139,48.682920,51.252751,
    55.000000,59.307883,63.326941,66.199152,67.286436,66.350198,63.639610,59.866963,56.074110,53.418823,52.928233,55.274323,
    60.621778,68.582540,78.287693,88.561119,98.156743,106.007043,111.428222,114.237346,114.756729,113.706291,112.009861,
    110.560634,110.000000,110.560634,112.009861,113.706291,114.756729,114.237346,111.428222,106.007043,98.156743,88.561119,
    78.287693,68.582540,60.621778,55.274323,52.928233,53.418823,56.074110,59.866963,63.639610,66.350198,67.286436,66.199152,
    63.326941,59.307883,55.000000,51.252751,48.682920,47.507139,47.470293,47.887148,47.788611,46.140080,42.082633,35.142296,
    25.359460,13.308217,0.000000,-13.308217,-25.359460,-35.142296,-42.082633,-46.140080,-47.788611,-47.887148,-47.470293,
    -47.507139,-48.682920,-51.252751,-55.000000,-59.307883,-63.326941,-66.199152,-67.286436,-66.350198,-63.639610,-59.866963,
    -56.074110,-53.418823,-52.928233,-55.274323,-60.621778,-68.582540,-78.287693,-88.561119,-98.156743,-106.007043,-111.428222,
    -114.237346,-114.756729,-113.706291,-112.009861,-110.560634,-110.000000,-110.560634,-112.009861,-113.706291,-114.756729,
    -114.237346,-111.428222,-106.007043,-98.156743,-88.561119,-78.287693,-68.582540,-60.621778,-55.274323,-52.928233,-53.418823,
    -56.074110,-59.866963,-63.639610,-66.350198,-67.286436,-66.199152,-63.326941,-59.307883,-55.000000,-51.252751,-48.682920,
    -47.507139,-47.470293,-47.887148,-47.788611,-46.140080,-42.082633,-35.142296,-25.359460,-13.308217,-0.000000,13.308217,
    25.359460,35.142296,42.082633,46.140080,47.788611,47.887148,47.470293,47.507139,48.682920,51.252751,55.000000,59.307883,
    63.326941,66.199152,67.286436,66.350198,63.639610,59.866963,56.074110,53.418823,52.928233,55.274323,60.621778,68.582540,
    78.287693,88.561119,98.156743,106.007043,111.428222,114.237346,114.756729,113.706291,112.009861,110.560634,110.000000,
    110.560634,112.009861,113.706291,114.756729,114.237346,111.428222,106.007043,98.156743,88.561119,78.287693,68.582540,
    60.621778,55.274323,52.928233,53.418823,56.074110,59.866963,63.639610,66.350198,67.286436,66.199152,63.326941,59.307883,
    55.000000,51.252751,48.682920,47.507139,47.470293,47.887148,47.788611,46.140080,42.082633,35.142296,25.359460,13.308217,
    0.000000,-13.308217,-25.359460,-35.142296,-42.082633,-46.140080,-47.788611,-47.887148,-47.470293,-47.507139,-48.682920,
    -51.252751,-55.000000,-59.307883,-63.326941,-66.199152,-67.286436,-66.350198,-63.639610,-59.866963,-56.074110,-53.418823,
    -52.928233,-55.274323,-60.621778,-68.582540,-78.287693,-88.561119,-98.156743,-106.007043,-111.428222,-114.237346,-114.756729,
    -113.706291,-112.009861,-110.560634,-110.000000,-110.560634,-112.009861,-113.706291,-114.756729,-114.237346,-111.428222,
    -106.007043,-98.156743,-88.561119,-78.287693,-68.582540,-60.621778,-55.274323,-52.928233,-53.418823,-56.074110,-59.866963,
    -63.639610,-66.350198,-67.286436,-66.199152,-63.326941,-59.307883,-55.000000,-51.252751,-48.682920,-47.507139,-47.470293,
    -47.887148,-47.788611,-46.140080,-42.082633,-35.142296,-25.359460,-13.308217,-0.000000,13.308217,25.359460,35.142296,
    42.082633,46.140080,47.788611,47.887148,47.470293,47.507139,48.682920,51.252751,55.000000,59.307883,63.326941,66.199152,
    67.286436,66.350198,63.639610,59.866963,56.074110,53.418823,52.928233,55.274323,60.621778,68.582540,78.287693,88.561119,
    98.156743,106.007043,111.428222,114.237346,114.756729,113.706291,112.009861,110.560634,110.000000,110.560634,112.009861,
    113.706291,114.756729,114.237346,111.428222,106.007043,98.156743,88.561119,78.287693,68.582540,60.621778,55.274323,52.928233,
    53.418823,56.074110,59.866963,63.639610,66.350198,67.286436,66.199152,63.326941,59.307883,55.000000,51.252751,48.682920,
    47.507139,47.470293,47.887148,47.788611,46.140080,42.082633,35.142296,25.359460,13.308217,0.000000,-13.308217,-25.359460,
    -35.142296,-42.082633,-46.140080,-47.788611,-47.887148,-47.470293,-47.507139,-48.682920,-51.252751,-55.000000,-59.307883,
    -63.326941,-66.199152,-67.286436,-66.350198,-63.639610,-59.866963,-56.074110,-53.418823,-52.928233,-55.274323,-60.621778,
    -68.582540,-78.287693,-88.561119,-98.156743,-106.007043,-111.428222,-114.237346,-114.756729,-113.706291,-112.009861,
    -110.560634,-110.000000,-110.560634,-112.009861,-113.706291,-114.756729,-114.237346,-111.428222,-106.007043,-98.156743,
    -88.561119,-78.287693,-68.582540,-60.621778,-55.274323,-52.928233,-53.418823,-56.074110,-59.866963,-63.639610,-66.350198,
    -67.286436,-66.199152,-63.326941,-59.307883,-55.000000,-51.252751,-48.682920,-47.507139,-47.470293,-47.887148,-47.788611,
    -46.140080,-42.082633,-35.142296,-25.359460,-13.308217,
};

//fft算法來(lái)自開(kāi)源 https://github.com/xiahouzuoxin/fft

const float sin_tb[] =    // 精度(PI PI/2 PI/4 PI/8 PI/16 ... PI/(2^k))
{
        0.000000, 1.000000, 0.707107, 0.382683, 0.195090, 0.098017,
        0.049068, 0.024541, 0.012272, 0.006136, 0.003068, 0.001534,
        0.000767, 0.000383, 0.000192, 0.000096, 0.000048, 0.000024,
        0.000012, 0.000006, 0.000003
        };

const float cos_tb[] =    // 精度(PI PI/2 PI/4 PI/8 PI/16 ... PI/(2^k))
{
        -1.000000, 0.000000, 0.707107, 0.923880, 0.980785, 0.995185,
        0.998795, 0.999699, 0.999925, 0.999981, 0.999995, 0.999999,
        1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
        1.000000, 1.000000, 1.000000
        };


int ones_32(uint32_t n)
{
    unsigned int c = 0 ;
    for(c = 0; n; ++c)
    {
        n &= (n - 1) ;
    }

    return c ;
}


uint32_t floor_log2_32(uint32_t fft_buff)
{
    fft_buff |= (fft_buff >> 1);
    fft_buff |= (fft_buff >> 2);
    fft_buff |= (fft_buff >> 4);
    fft_buff |= (fft_buff >> 8);
    fft_buff |= (fft_buff >> 16);

    return (ones_32(fft_buff >> 1));
}


/*
 * FFT Algorithm
 * === Inputs ===
 * fft_buff : complex numbers
 * N : nodes of FFT. @N should be power of 2, that is 2^(*)
 * === Output ===
 * the @fft_buff contains the result of FFT algorithm, so the original data
 * in @fft_buff is destroyed, please store them before using FFT.
 */
int fft(TYPE_FFT *fft_buff, uint32_t N)
{
    int i, j, l, k, ip;
    static uint32_t M = 0;
    static int le, le2;
    static TYPE_FFT_E sR, sI, tR, tI, uR, uI;

    M = floor_log2_32(N);

    /*
     * bit reversal sorting
     */

    l = N >> 1;
    j = l;
    ip = N - 2;
    for(i = 1; i <= ip; i++)
    {
        if(i < j)
        {
            tR = fft_buff[j].real;
            tI = fft_buff[j].imag;
            fft_buff[j].real = fft_buff[i].real;
            fft_buff[j].imag = fft_buff[i].imag;
            fft_buff[i].real = tR;
            fft_buff[i].imag = tI;
        }

        k = l;

        while(k <= j)
        {
            j = j - k;
            k = k >> 1;
        }

        j = j + k;
    }

    /*
     * For Loops
     */

    for(l = 1; l <= M; l++)  /* loop for ceil{log2(N)} */
    {
        le  = (int)(1 << l);
        le2 = (int)(le >> 1);
        uR = 1;
        uI = 0;

        k = floor_log2_32(le2);
        sR = cos_tb[k];
        sI = -sin_tb[k];

        for(j = 1; j <= le2; j++)  /* loop for each sub DFT */
        {
            for(i = j - 1; i < N; i += le) /* loop for each butterfly */
            {
                ip = i + le2;
                tR = fft_buff[ip].real * uR - fft_buff[ip].imag * uI;
                tI = fft_buff[ip].real * uI + fft_buff[ip].imag * uR;
                fft_buff[ip].real = fft_buff[i].real - tR;
                fft_buff[ip].imag = fft_buff[i].imag - tI;
                fft_buff[i].real += tR;
                fft_buff[i].imag += tI;
            }  /* Next i */

            tR = uR;
            uR = tR * sR - uI * sI;
            uI = tR * sI + uI * sR;

        } /* Next j */

    } /* Next l */

    return 0;
}


/*
 * Inverse FFT Algorithm
 * === Inputs ===
 * fft_buff : complex numbers
 * N : nodes of FFT. @N should be power of 2, that is 2^(*)
 * === Output ===
 * the @fft_buff contains the result of FFT algorithm, so the original data
 * in @fft_buff is destroyed, please store them before using FFT.
 */

int ifft(TYPE_FFT *fft_buff, uint32_t N)
{
    int k = 0;

    for(k = 0; k <= N - 1; k++)
    {
        fft_buff[k].imag = -fft_buff[k].imag;
    }

    fft(fft_buff, N);    /* using FFT */

    for(k = 0; k <= N - 1; k++)
    {
        fft_buff[k].real = fft_buff[k].real / N;
        fft_buff[k].imag = -fft_buff[k].imag / N;
    }

    return 0;
}

static void import_data(void)
{
    int i;

    for(i = 0; i < SAMPLE_NODES; i++)
    {
        fft_buff[i].real = my_sin_wave_table[i];//取前1024個(gè)數(shù)進(jìn)行fft變換
        fft_buff[i].imag  = 0.0f;
    }
}


int main(int argc, char *argv[])
{
    int i;
    int f;//頻率
    float a;//幅度
    int fd;
    float t;

    printf("FFTrn");

    import_data();

    fft(fft_buff, SAMPLE_NODES);

    //fft后的結(jié)果在fft_buff
    //將其實(shí)部與虛部處理,輸出頻點(diǎn)與幅度值,導(dǎo)入Excel看效果
    //因?yàn)槭侵芷谛再|(zhì),取前半部分即可

    //數(shù)據(jù)采樣頻率是360*40,均分到SAMPLE_NODES,則對(duì)應(yīng)頻點(diǎn)間隔是 360*40/SAMPLE_NODES
    fd=360*40/SAMPLE_NODES;

    for(i = 0; i < SAMPLE_NODES / 2; i++)
    {
        f = i *fd;
        a = (double)sqrt(fft_buff[i].real * fft_buff[i].real + fft_buff[i].imag * fft_buff[i].imag)/ (SAMPLE_NODES / 2);//轉(zhuǎn)換幅度
        //printf("%d,%fn", f, a);//>>導(dǎo)入excel查看幅頻圖效果
    }

    //過(guò)濾高頻部分
    //將幅度小于某個(gè)值的,以30為例過(guò)濾
    for(i = 0; i < SAMPLE_NODES; i++)
    {
        a = (double)sqrt(fft_buff[i].real * fft_buff[i].real + fft_buff[i].imag * fft_buff[i].imag)/ (SAMPLE_NODES / 2);
        if(a<30)
        {
            fft_buff[i].real = 0;
            fft_buff[i].imag = 0;
        }
    }

    //再進(jìn)行逆運(yùn)算還原
    ifft(fft_buff, SAMPLE_NODES);
    for(i = 0; i < SAMPLE_NODES; i++)
    {
        t=1.0/(360*40)*i;//結(jié)合采樣頻率步進(jìn),方便查看波形效果
        //printf("%f,%fn", t,fft_buff[i].real);//>>導(dǎo)入excel查看還原后的sin效果
    }

    return 0;
}

3.3 幅頻圖

混合波形使用FFT后的幅頻圖:

看圖可知對(duì)應(yīng)的頻點(diǎn)和幅度,與原始混合波形的3種正弦波吻合。

柵欄效應(yīng):其中頻點(diǎn)與采樣頻率和FFT轉(zhuǎn)換的采樣數(shù)有關(guān),需要結(jié)合實(shí)際定義,因?yàn)閿?shù)字離散信號(hào),頻點(diǎn)并不是連續(xù)的,如上大概相差14,因?yàn)閿?shù)據(jù)點(diǎn)數(shù)N為1024點(diǎn),原始信號(hào)的采樣頻率為fs=14400Hz,則頻率間隔fs/N約等于14Hz。這樣看頻譜圖只有fs/N倍數(shù)的,例如沒(méi)有410Hz,只能看到相鄰頻率406Hz和420Hz處頻譜泄漏的數(shù)據(jù),相當(dāng)于透過(guò)柵欄觀賞風(fēng)景,只能看到頻譜的一部分,而其它頻率點(diǎn)看不見(jiàn),因此很可能部分有用的頻率成分被漏掉,這種現(xiàn)象被稱為柵欄效應(yīng)。

3.4 逆變換還原

FFT后的幅頻數(shù)據(jù)過(guò)濾其中2個(gè)頻點(diǎn)的小幅度波形,還原后的效果如下圖:

過(guò)濾還原后的波形,與原始圖,前面python生成的黑色虛線吻合。

4、應(yīng)用

傅里葉變換在數(shù)字信號(hào)領(lǐng)域中應(yīng)用廣泛,在嵌入式系統(tǒng)中,一般用來(lái)分析ADC高速采集的數(shù)據(jù)、濾波處理,或者對(duì)音頻進(jìn)行簡(jiǎn)單分析。但傅里葉變換算法內(nèi)存消耗有點(diǎn)大,低端設(shè)備可能無(wú)法運(yùn)行。

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

嵌入式系統(tǒng)開(kāi)發(fā)技術(shù)交流,軟件開(kāi)發(fā)的思路與方案共享,行業(yè)資訊的分享。