【玩轉單片機系列002】 如何使用STM32提供的DSP庫進行FFT

  前些日子,由於須要在STM32F103系列處理器上,對採集的音頻信號進行FFT,因此花了一些時間來研究如何高效並精確的在STM32F103系列處理器上實現FFT。在網上找了不少這方面的資料作實驗並進行比較,最終選擇了使用STM32提供的DSP庫這種方法。數組

  本文將以一個實例來介紹如何使用STM32提供的DSP庫函數進行FFT框架

 

1.FFT運算效率ide

  使用STM32官方提供的DSP庫進行FFT,雖然在使用上有些不靈活(由於它是基4FFT,因此FFT的點數必須是4^n),但其執行效率確實很是高效,看圖1所示的FFT運算效率測試數據即可見一斑。該數據來自STM32 DSP庫使用文檔。函數

 

 圖1 FFT運算效率測試數據測試

  由圖1可見,在STM32F10x系列處理器上,若是使用72M的系統主頻,進行64點的FFT運算,僅僅須要0.078ms而已。若是是進行1024點的FFT運算,也才須要2.138msui

 

2.如何使用STM32提供的DSP庫函數spa

2.1下載STM32DSP指針

  你們能夠從網上搜索下載獲得STM32DSP庫,這裏提供一個下載的地址:code

      https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DispForm.aspx?ID=30831&RootFolder=%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex%5fmx%5fstm32%2fSTM32F10x%20DSP%20library%2c%20where%20is%20itorm

2.2添加DSP庫到本身的工程項目中

  下載獲得STM32DSP庫以後,就能夠將其添加到本身的工程項目中了。

  其中,inc文件夾下的stm32_dsp.htable_fft.h兩個文件是必須添加的。stm32_dsp.hSTM32DSP庫的頭文件。

  src文件夾下的文件能夠有選擇的添加(用到那個添加那個便可)。由於我只用到了256點的FFT,因此這裏我只添加了cr4_fft_256_stm32.s文件。添加完成後的項目框架如圖2所示。

圖2 項目框架

2.3模擬採樣數據

  根據採樣定理,採樣頻率必須是被採樣信號最高頻率的2倍。這裏,我要採集的是音頻信號,音頻信號的頻率範圍是20Hz20KHz,因此我使用的採用頻率是44800Hz。那麼在進行256FFT時,將獲得44800Hz / 256 = 175Hz的頻率分辨率。

  爲了驗證FFT運算結果的正確性,這裏我模擬了一組採樣數據,並將該採樣數據存放到了long類型的lBufInArray數組中,且該數組中每一個元素的高16位存儲採樣數據的實部,低16位存儲採樣數據的虛部(老是爲0)

  爲何要這樣作呢?是由於後面要調用STM32DSP庫函數,須要傳入的參數規定了必須是這樣的數據格式。

  下面是具體的實現代碼:

 1 /******************************************************************
 2 函數名稱:InitBufInArray()
 3 函數功能:模擬採樣數據,採樣數據中包含3種頻率正弦波(350Hz,8400Hz,18725Hz)
 4 參數說明:
 5 備    注:在lBufInArray數組中,每一個數據的高16位存儲採樣數據的實部,
 6           低16位存儲採樣數據的虛部(老是爲0)
 7 做  者:博客園 依舊淡然(http://www.cnblogs.com/menlsh/ 8 *******************************************************************/
 9 void InitBufInArray()
10 {
11     unsigned short i;
12     float fx;
13     for(i=0; i<NPT; i++)
14     {
15         fx = 1500 * sin(PI2 * i * 350.0 / Fs) +
16              2700 * sin(PI2 * i * 8400.0 / Fs) +
17              4000 * sin(PI2 * i * 18725.0 / Fs);
18         lBufInArray[i] = ((signed short)fx) << 16;
19     }
20 }

  其中,NPT是採樣點數256PI22π(即6.28318530717959),Fs是採樣頻率44800。能夠看到採樣數據中包含了3種頻率的正弦波,分別爲350Hz8400Hz18725Hz

2.4調用DSP庫函數進行FFT

  進行256點的FFT,只須要調用STM32 DSP庫函數中的cr4_fft_256_stm32()函數便可。該函數的原型爲:

  void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);

  其中,參數pssOUT表示FFT輸出數組指針,參數pssIN表示要進行FFT運算的輸入數組指針,參數Nbin表示了點數。至於該函數的具體實現,由於是用匯編語言編寫的,我也不懂,這裏就不妄談了。

  下面是具體的調用實例:

  cr4_fft_256_stm32(lBufOutArray, lBufInArray, NPT);

  其中,參數lBufOutArray一樣是一個long類型的數組,參數lBufInArray就是存放模擬採樣數據的採樣數組,NPT爲採樣點數256

  調用該函數以後,在lBufOutArray數組中就存放了進行FFT運算以後的結果數據。該數組中每一個元素的數據格式爲;高16位存儲虛部,低16位存儲實部。

2.5計算各次諧波幅值

  獲得FFT運算以後的結果數據以後,就能夠計算各次諧波的幅值了。

  下面是具體的實現代碼:

 1 /******************************************************************
 2 函數名稱:GetPowerMag()
 3 函數功能:計算各次諧波幅值
 4 參數說明:
 5 備  注:先將lBufOutArray分解成實部(X)和虛部(Y),而後計算幅值(sqrt(X*X+Y*Y)
 6 做  者:博客園 依舊淡然(http://www.cnblogs.com/menlsh/ 7 *******************************************************************/
 8 void GetPowerMag()
 9 {
10     signed short lX,lY;
11     float X,Y,Mag;
12     unsigned short i;
13     for(i=0; i<NPT/2; i++)
14     {
15         lX  = (lBufOutArray[i] << 16) >> 16;
16         lY  = (lBufOutArray[i] >> 16);
17         X = NPT * ((float)lX) / 32768;
18         Y = NPT * ((float)lY) / 32768;
19         Mag = sqrt(X * X + Y * Y) / NPT;
20         if(i == 0)
21             lBufMagArray[i] = (unsigned long)(Mag * 32768);
22         else
23             lBufMagArray[i] = (unsigned long)(Mag * 65536);
24     }
25 }

  其中,數組lBufMagArray存儲了各次諧波的幅值。

2.6實驗結果

  經過串口,咱們能夠將lBufMagArray數組中各次諧波的幅值(即各個頻率份量的幅值)輸出打印出來,具體實驗數據以下所示:

   i,         P,       Mag,         X,         Y
   0,         0,         4,         0,        -4
   1,       175,        14,        -6,        -4
   2,       350,      1492,       746,        -3
   3,       525,        11,        -5,        -3
   4,       700,         8,        -3,        -3
   5,       875,         8,        -4,        -2
   6,      1050,         6,        -3,         0
   7,      1225,         6,        -3,         0
   8,      1400,         8,        -4,        -2
   9,      1575,         8,        -4,         0
  10,      1750,         4,        -2,         0
  11,      1925,         8,        -4,        -1
  12,      2100,         6,        -3,         0
  13,      2275,         5,        -2,        -2
  14,      2450,         6,        -3,        -1
  15,      2625,         8,        -3,        -3
  16,      2800,         4,        -2,         0
  17,      2975,         6,        -3,        -1
  18,      3150,         6,        -3,         0
  19,      3325,         6,        -3,         0
  20,      3500,         2,        -1,         0
  21,      3675,         4,        -2,         0
  22,      3850,         4,        -2,         0
  23,      4025,         4,        -2,         0
  24,      4200,         6,        -3,         0
  25,      4375,         6,        -3,         0
  26,      4550,         4,        -2,         0
  27,      4725,         6,        -3,         0
  28,      4900,         2,        -1,         0
  29,      5075,         4,        -2,        -1
  30,      5250,         4,        -2,         0
  31,      5425,         2,        -1,         0
  32,      5600,         4,        -2,        -1
  33,      5775,         6,        -3,        -1
  34,      5950,         2,        -1,        -1
  35,      6125,         6,        -3,        -1
  36,      6300,         2,        -1,         0
  37,      6475,         6,        -3,         0
  38,      6650,         4,        -2,         0
  39,      6825,         4,        -2,        -1
  40,      7000,         2,        -1,         0
  41,      7175,         6,        -3,         0
  42,      7350,         2,        -1,         0
  43,      7525,         2,        -1,         0
  44,      7700,         2,        -1,         0
  45,      7875,         2,        -1,         0
  46,      8050,         4,        -2,         0
  47,      8225,         2,        -1,         0
  48,      8400,      2696,      1348,         0
  49,      8575,         2,        -1,        -1
  50,      8750,         0,         0,         0
  51,      8925,         4,        -2,        -1
  52,      9100,         2,         0,        -1
  53,      9275,         0,         0,         0
  54,      9450,         2,        -1,        -1
  55,      9625,         2,        -1,         0
  56,      9800,         2,        -1,         0
  57,      9975,         2,        -1,        -1
  58,     10150,         2,        -1,        -1
  59,     10325,         2,        -1,         0
  60,     10500,         0,         0,         0
  61,     10675,         2,        -1,         0
  62,     10850,         4,        -2,        -1
  63,     11025,         2,        -1,        -1
  64,     11200,         0,         0,         0
  65,     11375,         2,        -1,         0
  66,     11550,         0,         0,         0
  67,     11725,         2,        -1,        -1
  68,     11900,         2,        -1,        -1
  69,     12075,         2,        -1,         1
  70,     12250,         2,        -1,         1
  71,     12425,         4,        -2,         1
  72,     12600,         4,        -2,        -1
  73,     12775,         2,        -1,         1
  74,     12950,         0,         0,         0
  75,     13125,         4,        -2,         0
  76,     13300,         4,        -2,         0
  77,     13475,         2,        -1,         0
  78,     13650,         2,        -1,         0
  79,     13825,         4,        -2,        -1
  80,     14000,         2,        -1,         0
  81,     14175,         4,        -2,         0
  82,     14350,         2,        -1,         1
  83,     14525,         4,        -2,         1
  84,     14700,         4,        -2,         1
  85,     14875,         2,        -1,         1
  86,     15050,         4,        -2,         0
  87,     15225,         2,        -1,         0
  88,     15400,         4,        -2,         1
  89,     15575,         4,        -2,         1
  90,     15750,         2,        -1,         0
  91,     15925,         2,        -1,         1
  92,     16100,         2,        -1,         1
  93,     16275,         2,        -1,         1
  94,     16450,         4,        -2,         1
  95,     16625,         2,        -1,         1
  96,     16800,         2,        -1,        -1
  97,     16975,         4,        -2,         0
  98,     17150,         2,        -1,         0
  99,     17325,         4,        -2,         0
 100,     17500,         4,        -2,         1
 101,     17675,         4,        -2,         0
 102,     17850,         4,        -2,         1
 103,     18025,         4,        -2,        -1
 104,     18200,         2,        -1,         1
 105,     18375,         4,        -2,         0
 106,     18550,         2,        -1,         1
 107,     18725,      3996,      1998,         1
 108,     18900,         2,        -1,         0
 109,     19075,         2,        -1,         1
 110,     19250,         4,        -2,         1
 111,     19425,         4,        -2,         1
 112,     19600,         2,         0,         1
 113,     19775,         2,        -1,         0
 114,     19950,         0,         0,         0
 115,     20125,         4,        -2,         1
 116,     20300,         2,         0,         1
 117,     20475,         2,         0,         1
 118,     20650,         2,        -1,         1
 119,     20825,         2,        -1,         1
 120,     21000,         2,        -1,         1
 121,     21175,         2,        -1,         0
 122,     21350,         2,         0,         1
 123,     21525,         2,        -1,         0
 124,     21700,         0,         0,         0
 125,     21875,         2,        -1,         1
 126,     22050,         2,        -1,         1
 127,     22225,         2,         0,         1
View Code

  在以上的實驗數據中,咱們分別打印出來了點數、頻率、幅值、實部、虛部信息。

  由以上的實驗數據,咱們能夠看出,在頻率爲350Hz8400Hz18725Hz時,幅值出現峯值,分別爲149226963996,這與咱們所預期的結果正好相符,從而驗證了實驗結果的正確性。

相關文章
相關標籤/搜索