當(dāng)前位置:首頁 > 公眾號精選 > 嵌入式客棧
[導(dǎo)讀]?點上方嵌入式客棧,置頂/星標(biāo)干貨及時送達(dá) 【導(dǎo)讀】:在嵌入式系統(tǒng)中經(jīng)常需要采集模擬信號,采集模擬信號的信號鏈中難免引入干擾,那么如何濾除干擾呢?今天就來個一步一步描述如何設(shè)計部署一個IIR濾波器到你的系統(tǒng)。寫這篇文章考慮到很多粉絲是做單片機系統(tǒng)

 點上方嵌入式客棧,置頂/星標(biāo)干貨及時送達(dá)

【導(dǎo)讀】:在嵌入式系統(tǒng)中經(jīng)常需要采集模擬信號,采集模擬信號的信號鏈中難免引入干擾,那么如何濾除干擾呢?今天就來個一步一步描述如何設(shè)計部署一個IIR濾波器到你的系統(tǒng)。寫這篇文章考慮到很多粉絲是做單片機系統(tǒng)開發(fā)的,經(jīng)常會需要采集模擬信號,系統(tǒng)中往往存在各種各樣的干擾,干擾常常讓人一籌莫展,所以花了一周時間整理出IIR濾波器設(shè)計部署的干貨文章,照此一步一步做,你必會解決大部分干擾問題。

編外語: 文章寫作過程雖談不上嘔心瀝血,但也可算絞盡腦汁。 在此也呼吁粉絲朋友積極參與互動,或點在看,或分享,或留言評論,當(dāng)然如能買杯咖啡,那就更好啦!如果大家對此類話題感興趣,我會寫出系列信號處理文章以答謝各位的厚愛,如果大家對此類話題不感興趣,就不在花過多時間整理發(fā)布了。在此感謝各位關(guān)注厚愛!

何為IIR濾波器?

無限沖激響應(yīng)(IIRInfinite Impulse Response)是一種適用于許多線性時不變系統(tǒng)的屬性,這些系統(tǒng)的特征是具有一個沖激響應(yīng)h(t),該沖激響應(yīng)h(t)不會在特定點上完全變?yōu)榱悖菬o限期地持續(xù)。這與有限沖激響應(yīng)(FIRFinite Impulse Response)系統(tǒng)形成對比,在有限沖激響應(yīng)(FIR)系統(tǒng)中,對于某個有限T,在時間t> T時,沖激響應(yīng)確實恰好變?yōu)榱?。線性時不變系統(tǒng)的常見示例是大多數(shù)電子和數(shù)字濾波器。具有此屬性的系統(tǒng)稱為IIR系統(tǒng)或IIR濾波器。對于什么叫沖激響應(yīng),這里就不展開解釋了,有興趣的可以查閱相關(guān)書籍。

這是常見的教科書式數(shù)學(xué)嚴(yán)謹(jǐn)定義,很多人看到這一下就蒙了,能說人話嗎?

線性時不變系統(tǒng)理論俗稱LTI系統(tǒng)理論,源自應(yīng)用數(shù)學(xué),直接在核磁共振頻譜學(xué)、地震學(xué)、電路、信號處理和控制理論等技術(shù)領(lǐng)域運用。它研究的是線性、非時變系統(tǒng)對任意輸入信號的響應(yīng)。雖然這些系統(tǒng)的軌跡通常會隨時間變化(例如聲學(xué)波形)來測量和跟蹤,但是應(yīng)用到圖像處理和場論時,LTI系統(tǒng)在空間維度上也有軌跡。因此,這些系統(tǒng)也被稱為線性非時變平移,在最一般的范圍理論給出此理論。在離散(即采樣)系統(tǒng)中對應(yīng)的術(shù)語是線性非時變平移系統(tǒng)。由電阻、電容、電感組成的電路是LTI系統(tǒng)的一個很好的例子。比如一個運放系統(tǒng)在一定頻帶范圍內(nèi)滿足信號的時域疊加,輸入一個100Hz和200Hz正弦信號,輸出頻率是這兩種信號的線性疊加。

用數(shù)學(xué)對LTI系統(tǒng)描述:

線性:輸入x1(t),產(chǎn)生響應(yīng) y1(t),而輸入x2(t),產(chǎn)生相應(yīng)y2(t) , 那么放縮和加和輸入 ax1(t)+bx1(t), 產(chǎn)生放縮、加和的響應(yīng)ay1(t)+by1(t),其中a和b是標(biāo)量,對于任意的有:

輸入  

產(chǎn)生響應(yīng)為:

時不變性:指如果將系統(tǒng)的輸入信號延遲δ秒,那么得到的輸出響應(yīng)也相應(yīng)延時δ秒。用數(shù)學(xué)描述,也即如果輸入x1(t),產(chǎn)生響應(yīng)y1(t) ,而輸入x1(t+δ) ,產(chǎn)生響應(yīng) y1(t+δ)。

這么描述還是不易懂,來個圖,有圖有真相:

假定一個信號放大電路對100Hz正弦信號放大2倍,則輸出為:

而對200Hz的正弦信號,假定其放大倍數(shù)為1.7倍。(做過運放電路設(shè)計的朋友應(yīng)該有經(jīng)驗,在其同頻帶其放大倍數(shù)往往并不平坦,也即幅頻響應(yīng)在頻帶內(nèi)不平坦,這是比較常見的)。也即輸入為:

則響應(yīng)為:


那么如果輸入100Hz和200Hz的時域疊加信號,則其輸入為:

則其響應(yīng)為:

由這些圖可看出,輸入信號的形狀保持不變,輸出為對應(yīng)輸入的線性時域疊加。對于時不變,就不用圖描述了,在一個真實電路中,如果輸入延遲一定時間,則響應(yīng)對應(yīng)延遲相同時間輸出。

上面這么多文字只是為了描述在什么場合可以使用IIR濾波器對信號進(jìn)行數(shù)字濾波??偨Y(jié)而言,就是在線性時不變系統(tǒng)中適用。換言之,在大多數(shù)電路系統(tǒng)中我們都可以嘗試采用IIR濾波器進(jìn)行數(shù)字濾波。

那么究竟什么是IIR濾波器呢?從數(shù)字信號處理的書籍中我們能看到這樣的Z變換信號流圖:

Z的-1次方表示延遲一拍,在數(shù)字系統(tǒng)中表示對于輸入信號而言,即為上一次采樣值,對于輸出而言,即為上一次的輸出值。


在時域中對于上述流圖,用時域描述即為:

如果熟悉Z變換,則Z變換傳遞函數(shù)為:

上述數(shù)字濾波器,如果從編程的角度來看,x(n-1),表示上一次的信號,可能是來自ADC的上次采樣,而y(n-1)則為上一次濾波器的輸出值,對應(yīng)就比較好理解x(n-N)就表示前第n次輸入樣本信號,而y(n-M)則為前第M次濾波器的輸出。

說了這么多,只是為了更好的理解概念,只有概念理解正確,才能使用正確。概念理解這對工程師而言,非常之重要。

如何設(shè)計呢?

MATLAB提供了非常容易使用的FDATool幫助我們設(shè)計數(shù)字濾波器,真正精彩的地方開始了,讓我們拭目以待究竟如何一步一步設(shè)計并實施一個IIR濾波器。首先打開MATLAB,在命令行中敲fdatool,然后敲回車

彈出窗體就是fdatool了,如下:

在設(shè)計具體,有幾個相關(guān)概念需要澄清:
Fs :采 樣率,單位為Hz,真實部署在系統(tǒng)中,請務(wù)必確保樣本是按照恒定采樣率進(jìn)行采樣,否則將得不到想要的效果。
Fpass : 通頻帶,單位為Hz,即系統(tǒng)中期望通過的最高頻率。
Fstop : 截至頻率,即幅頻響應(yīng)的-3dB處的頻率,這個如不理解,請自行查閱相關(guān)書籍。
分貝dB : 這是一個無單位反應(yīng)輸出與輸入倍數(shù)的一個術(shù)語。電學(xué)中分貝與放大倍數(shù)的轉(zhuǎn)換關(guān)系為:
  • A(V)(dB)=20lg(Vo/Vi);電壓增益,Vo 為輸出電壓,Vi為輸入電壓

  • A(I)(dB)=20lg(Io/Ii);電流增益,Io 為輸出電流,Ii為輸入電流

  • A(p)(dB)=10lg(Po/Pi);功率增益,Po 為輸出功率,Pi為輸入功率

濾波器類型:這里有Butterworth(巴特沃斯)、Chebyshev Type I,Chebyshev Type II、(切比雪夫)、Elipic 等可選。

  • 巴特沃斯 Butterworth,也被稱作最大平坦濾波器。巴特沃斯濾波器的特點是通頻帶內(nèi)的頻率響應(yīng)曲線最大限度平坦,沒有紋波。

  • 切比雪夫 Chebyshev,是在通帶或阻帶上頻率響應(yīng)幅度等波紋波動的濾波器。切比雪夫濾波器在過渡帶比巴特沃斯濾波器的衰減快,但頻率響應(yīng)的幅頻特性不如后者平坦。

  • 橢圓 Elliptic,橢圓濾波器是在通帶和阻帶等波紋的一種濾波器。

  • …這里就不一一介紹了,有興趣可以去查信號處理書籍。

就其特點,這里對其中幾種略作介紹:

  • 巴特沃斯具有最平坦的通帶。

  • 橢圓濾波器衰減最快,但是通帶、阻帶都有波紋。

  • 切比雪夫濾波器衰減比巴特沃斯快,但比橢圓濾波器慢,波紋區(qū)域可選擇。

假設(shè)我們需要設(shè)計一個IIR濾波器,采樣率為32000Hz, 有用信號頻率在10000Hz內(nèi),設(shè)計IIR濾波器對信號進(jìn)行數(shù)字濾波。這里為節(jié)省算力,我們指定濾波器的階數(shù),也即傳遞函數(shù)中N/M中的最大值,一般而言N大于M。

這里指定階數(shù)為8階,類型指定為巴特沃斯型IIR濾波器,輸入階數(shù)8階,采樣率32000Hz,然后點擊Design Filter如下圖所示:

其相頻響應(yīng)曲線如下:


除此之外,我們還可以將幅頻與相頻曲線放在一個頻率坐標(biāo)上去看設(shè)計結(jié)果:

導(dǎo)出濾波器參數(shù),這里我們選擇,

然后就得到了一個文件,保存2KHz_LPF.fcf,文件名隨你喜歡。

文件內(nèi)容如下:

Generated by MATLAB(R) 8.4 and the Signal Processing Toolbox 6.22.
Generated on: 27-Mar-2020 21:27:06

Coefficient FormatDecimal

Discrete-Time IIR Filter (real)                            
-------------------------------                            
Filter Structure    : Direct-Form IISecond-Order Sections
Number of Sections  : 4                                    
Stable              : Yes                                  
Linear Phase        : No                                   


SOS Matrix:                                                  
1  2  1  1  -1.7193929141691948  0.8610574795347461          
1  2  1  1  -1.5237898734101736  0.64933827386370635         
1  2  1  1  -1.4017399331200424  0.51723237044751591         
1  2  1  1  -1.3435020629061745  0.45419615396638446         

Scale Values:                                                
0.035416141341387819                                         
0.031387100113383172                                         
0.028873109331868367                                         
0.027673522765052503                                          

至此設(shè)計工作就結(jié)束了,馬上進(jìn)入濾波器的部署測試階段。

這里有個概念需要略作解釋:什么叫直接II型 SOS

所謂直接II型,SOS(second order section)理解很簡單,本質(zhì)是將IIR Z傳遞函數(shù)分解為上述二階塊的級聯(lián)形式。

部署測試濾波器

到這里,沒有經(jīng)驗的朋友可能會說,這么一堆參數(shù)我該咋用呢?

需要自己去寫前面描述的計算公式嗎?當(dāng)然你也可以這么做,這里就不寫了,ARM的CMSIS庫已經(jīng)幫大家設(shè)計好了種類繁多的數(shù)字信號處理函數(shù)實現(xiàn)了,而且經(jīng)過了測試,這里直接拿來用即可。有興趣自己寫也不難,只要理解Z傳遞函數(shù)概念內(nèi)涵,非常容易實現(xiàn)。這里我們采用32位浮點實現(xiàn)函數(shù):

arm_biquad_cascade_df1_f32。該函數(shù)位于:

CMSIS\DSP\Source\FilteringFunctions\arm_biquad_cascade_df1_init_f32.c

CMSIS\DSP\Source\FilteringFunctions\arm_biquad_cascade_df1_f32.c

我們來看一看這個函數(shù):

arm_biquad_cascade_df1_init_f32.c:

/*
*作用      :初始化濾波器
*S        :指向浮點SOS級聯(lián)結(jié)構(gòu)的實例。
*numStages:濾波器中二階SOS的數(shù)量
*pCoeffs  :濾波器參數(shù)指針,參數(shù)按下列順序存儲
*          {b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
*pState   :歷史狀態(tài)緩沖區(qū)指針
*/

void arm_biquad_cascade_df1_init_f32(
        arm_biquad_casd_df1_inst_f32 * S,
        uint8_t numStages,
  const float32_t * pCoeffs,
        float32_t * pState)

{
  /* Assign filter stages */
  S->numStages = numStages;

  /* Assign coefficient pointer */
  S->pCoeffs = pCoeffs;

  /* Clear state buffer and size is always 4 * numStages */
  memset(pState, 0, (4U * (uint32_t) numStages) * sizeof(float32_t));

  /* Assign state pointer */
  S->pState = pState;
}

arm_math.h 定義了須用到的結(jié)構(gòu)體,對于本例相關(guān)的結(jié)構(gòu)體為arm_biquad_casd_df1_inst_f32

typedef struct
{

  unsigned int numStages; /*2階節(jié)的個數(shù),應(yīng)為2*numStages.        */
  float *pState;          /*狀態(tài)系數(shù)數(shù)組指針,數(shù)組長度為4*numStages*/
  float *pCoeffs;         /*系數(shù)數(shù)組指針, 數(shù)組的長度為5*numStages.*/
} arm_biquad_casd_df1_inst_f32;

濾波器具體濾波函數(shù)為:

arm_biquad_cascade_df1_f32

/**
 *  *S       :指向浮點Biquad級聯(lián)結(jié)構(gòu)的實例.
 *  *pSrc    :指向輸入數(shù)據(jù)塊。
 *  *pDst    :指向輸出數(shù)據(jù)塊。
 *  blockSize:每次調(diào)用要處理的樣本數(shù)。
 *  返回值    :無.
 */

void arm_biquad_cascade_df1_f32(
  const arm_biquad_casd_df1_inst_f32 * S,
  float * pSrc,
  float * pDst,
  unsigned int blockSize)

{
  float *pIn = pSrc;                         /*源指針     */
  float *pOut = pDst;                        /*目的指針    */
  float *pState = S->pState;                 /*狀態(tài)指針    */
  float *pCoeffs = S->pCoeffs;               /*參數(shù)指針    */
  float acc;                                 /*累加器      */
  float b0, b1, b2, a1, a2;                  /*濾波器參數(shù)   */
  float Xn1, Xn2, Yn1, Yn2;                  /*濾波器狀態(tài)變量*/
  float Xn;                                  /*臨時輸入     */
  unsigned int sample, stage = S->numStages; /*循環(huán)計數(shù)     */

  do
  {
    /* Reading the coefficients */
    b0 = *pCoeffs++;
    b1 = *pCoeffs++;
    b2 = *pCoeffs++;
    a1 = *pCoeffs++;
    a2 = *pCoeffs++;

    Xn1 = pState[0];
    Xn2 = pState[1];
    Yn1 = pState[2];
    Yn2 = pState[3];

    sample = blockSize >> 2u;

    while(sample > 0u)
    {
      /* 讀第一個輸入 */
      Xn = *pIn++;

      /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
      Yn2 = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);

      /* Store the result in the accumulator in the destination buffer. */
      *pOut++ = Yn2;

      /* 每次計算輸出后,狀態(tài)都應(yīng)更新. */
      /* 狀態(tài)應(yīng)更新為:  */
      /* Xn2 = Xn1    */
      /* Xn1 = Xn     */
      /* Yn2 = Yn1    */
      /* Yn1 = acc   */

      /* Read the second input */
      Xn2 = *pIn++;

      /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
      Yn1 = (b0 * Xn2) + (b1 * Xn) + (b2 * Xn1) + (a1 * Yn2) + (a2 * Yn1);

      /* 將結(jié)果存儲在目標(biāo)緩沖區(qū)的累加器中. */
      *pOut++ = Yn1;

      /* 每次計算輸出后,狀態(tài)都應(yīng)更新. */
      /* 狀態(tài)應(yīng)更新為:  */
      /* Xn2 = Xn1    */
      /* Xn1 = Xn     */
      /* Yn2 = Yn1    */
      /* Yn1 = acc   */

      /*讀第三個輸入 */
      Xn1 = *pIn++;

      /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
      Yn2 = (b0 * Xn1) + (b1 * Xn2) + (b2 * Xn) + (a1 * Yn1) + (a2 * Yn2);

      /* 將結(jié)果存儲在目標(biāo)緩沖區(qū)的累加器中. */
      *pOut++ = Yn2;

      /* 每次計算輸出后,狀態(tài)都應(yīng)更新. */
      /* 狀態(tài)應(yīng)更新為: */
      /* Xn2 = Xn1    */
      /* Xn1 = Xn     */
      /* Yn2 = Yn1    */
      /* Yn1 = acc   */
      /* 讀第四個輸入 */
      Xn = *pIn++;

      /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
      Yn1 = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn2) + (a2 * Yn1);

      /* 將結(jié)果存儲在目標(biāo)緩沖區(qū)的累加器中. */
      *pOut++ = Yn1;

      /* 每次計算輸出后,狀態(tài)都應(yīng)更新. */
      /* 狀態(tài)應(yīng)更新為:  */
      /* Xn2 = Xn1    */
      /* Xn1 = Xn     */
      /* Yn2 = Yn1    */
      /* Yn1 = acc   */
      Xn2 = Xn1;
      Xn1 = Xn;

      /* 遞減循環(huán)計數(shù)器 */
      sample--;
    }

    /* 如果blockSize不是4的倍數(shù),
    *請在此處計算任何剩余的輸出樣本。
    *不使用循環(huán)展開. */

    sample = blockSize & 0x3u;

    while(sample > 0u)
    {
      /* 讀取輸入 */
      Xn = *pIn++;

      /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
      acc = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);

      /* 將結(jié)果存儲在目標(biāo)緩沖區(qū)的累加器中. */
      *pOut++ = acc;

      /* 每次計算輸出后,狀態(tài)都應(yīng)更新。 */
      /* 狀態(tài)應(yīng)更新為:    */
      /* Xn2 = Xn1    */
      /* Xn1 = Xn     */
      /* Yn2 = Yn1    */
      /* Yn1 = acc   */
      Xn2 = Xn1;
      Xn1 = Xn;
      Yn2 = Yn1;
      Yn1 = acc;

      /* d遞減循環(huán)計數(shù)器 */
      sample--;
    }

    /*  將更新后的狀態(tài)變量存儲回pState數(shù)組中 */
    *pState++ = Xn1;
    *pState++ = Xn2;
    *pState++ = Yn1;
    *pState++ = Yn2;

    /*第一階段從輸入緩沖區(qū)到輸出緩沖區(qū).     */
    /*隨后的numStages在輸出緩沖區(qū)中就地發(fā)生*/
    pIn = pDst;

    /* 重置輸出指針 */
    pOut = pDst;

    /* 遞減循環(huán)計數(shù)器 */
    stage--;

  } while(stage > 0u);
}

開始測試:

#include <stdio.h>
#include <math.h>
/*
SOS Matrix:                                                  
1  2  1  1  -1.7193929141691948  0.8610574795347461          
1  2  1  1  -1.5237898734101736  0.64933827386370635         
1  2  1  1  -1.4017399331200424  0.51723237044751591         
1  2  1  1  -1.3435020629061745  0.45419615396638446         

Scale Values:                                                
0.035416141341387819                                         
0.031387100113383172                                         
0.028873109331868367                                         
0.027673522765052503  
做如下轉(zhuǎn)換:
1.縮放
[1  2  1] * 0.035416141341387819
[1  2  1] * 0.031387100113383172
[1  2  1] * 0.028873109331868367
[1  2  1] * 0.027673522765052503
得到:
[0.035416141341387819  2*0.035416141341387819  0.035416141341387819]
[0.031387100113383172  2*0.031387100113383172  0.031387100113383172] 
[0.028873109331868367  2*0.028873109331868367  0.028873109331868367] 
[0.027673522765052503  2*0.027673522765052503  0.027673522765052503]
2.舍掉第四列參數(shù)
3.將后兩列分別乘以-1,即:
0.035416141341387819  2*0.035416141341387819  0.035416141341387819  -1.7193929141691948  0.8610574795347461          
0.031387100113383172  2*0.031387100113383172  0.031387100113383172  -1.5237898734101736  0.64933827386370635         
0.028873109331868367  2*0.028873109331868367  0.028873109331868367  -1.4017399331200424  0.51723237044751591         
0.027673522765052503  2*0.027673522765052503  0.027673522765052503  -1.3435020629061745  0.45419615396638446 
這樣就得到了濾波器系數(shù)組了
*/

#define IIR_SECTION 4                /*見前面設(shè)計輸出為4個SOS塊*/
static float iir_state[4*IIR_SECTION];/*歷史狀態(tài)緩沖區(qū)         */
const float iir_coeffs[5*IIR_SECTION]={
    
0.035416141341387819,2*0.035416141341387819,0.035416141341387819,1.7193929141691948,-0.8610574795347461,    0.031387100113383172,2*0.031387100113383172,0.031387100113383172,1.5237898734101736,-0.64933827386370635,    0.028873109331868367,2*0.028873109331868367,0.028873109331868367,1.4017399331200424,-0.51723237044751591,    0.027673522765052503,2*0.027673522765052503,0.027673522765052503,1.3435020629061745,-0.45419615396638446
};
static arm_biquad_casd_df1_inst_f32 S;
/*假定采樣512個點*/
#define BUF_SIZE 512
#define PI 3.1415926
#define SAMPLE_RATE  32000 /*32000Hz*/
int main()
{
    
float raw[BUF_SIZE];
    
float raw_4k[BUF_SIZE];
    
float raw_out[BUF_SIZE];

    
float raw_noise[BUF_SIZE];
    
float raw_noise_out[BUF_SIZE];

    arm_biquad_casd_df1_inst_f32 S;
    FILE *pFile=fopen(
"./simulation.csv","wt+");
    
if(pFile==NULL)
    {
        
printf("file opened failed");
        
return -1;
    }

    
for(int i=0;i<BUF_SIZE;i++)
    {
/*模擬800Hz正弦幅度171,疊加幅度50隨機噪聲 */
raw[i] = 
0.5*1024.0/3*sin(2*PI*800*i/32000.0f)+rand()%50;
       raw_4k[i] = 
0.5*1024.0/3*sin(2*PI*4000*i/32000.0f);
       
/*模擬800Hz +4000Hz+隨機噪聲疊加輸入 */
       raw_noise[i] = raw[i] + raw_4k[i];
    }
/*初始化濾波器,以及濾波*/
    arm_biquad_cascade_df1_init_f32(&S, IIR_SECTION, (
float *)&iir_coeffs[0], (float *)&iir_state[0]);
    arm_biquad_cascade_df1_f32(&S, raw, raw_out, BUF_SIZE);

    
for(int i=0;i<BUF_SIZE;i++)
    {
       
fprintf(pFile,"%f,",raw[i]);
    }

    
fprintf(pFile,"\n");
    
for(int i=0;i<BUF_SIZE;i++)
    {
        
fprintf(pFile,"%f,",raw_4k[i]);
    }
    
fprintf(pFile,"\n");
    
for(int i=0;i<BUF_SIZE;i++)
    {
        
fprintf(pFile,"%f,",raw_out[i]);
    }

    
/*初始化濾波器,以及濾波*/
    arm_biquad_cascade_df1_init_f32(&S, IIR_SECTION, (
float *)&iir_coeffs[0], (float *)&iir_state[0]);
    arm_biquad_cascade_df1_f32(&S, raw_noise, raw_noise_out, BUF_SIZE);

    
fprintf(pFile,"\n");
    
for(int i=0;i<BUF_SIZE;i++)
    {
        
fprintf(pFile,"%f,",raw_noise[i]);
    }

    
fprintf(pFile,"\n");
    
for(int i=0;i<BUF_SIZE;i++)
    {
        
fprintf(pFile,"%f,",raw_noise_out[i]);
    }

    fclose(pFile);

    
return 0;
}

利用csv文件,將模擬數(shù)據(jù)存儲,直接用excel打開,將行數(shù)據(jù)生成曲線圖如下:

有興趣也可以寫個界面直接顯示,甚至繪制出譜線圖,做進(jìn)一步分析。

  • 第一幅圖,為800Hz信號混入隨機噪聲的波形

  • 第二幅圖,為4000Hz信號,對假定系統(tǒng)為無用干擾信號

  • 第三幅圖, 為800Hz 混入隨機噪聲過濾后,已經(jīng)很好的還原有用信號頻率

  • 第四幅圖, 為800Hz信號混入隨機噪聲,同時疊加4000Hz干擾的波形,對系統(tǒng)而言,從時域中,明顯可見,有用信號已經(jīng)完全扭曲

  • 第五幅圖,為800Hz信號混入隨機噪聲,同時疊加4000Hz干擾的輸入,經(jīng)過該低通濾波器后的波形,與第三幅圖基本一樣,已經(jīng)非常好的濾除了干擾信號。

總結(jié)

  • IIR濾波器在線性時不變系統(tǒng)中可以很好的解決工程中一般噪聲問題

  • 如果需要設(shè)計帶通、高通濾波器其步驟基本類似,只是濾波器的參數(shù)以及SOS塊個數(shù)可能不一樣而已

  • 需要提醒的時,IIR的相頻響應(yīng)不線性,如果系統(tǒng)對相頻響應(yīng)有嚴(yán)格要求,就需要采用其他的數(shù)字濾波器拓?fù)湫问搅?/span>

  • 實際應(yīng)用中,如果階數(shù)不高時,現(xiàn)在算力強勁的單片機或者DSP以及可以直接使用浮點處理。

  • 如果對處理速度有嚴(yán)格的實時要求,需要在極短時間進(jìn)行濾波處理,可以考慮降低階數(shù),或采用定點IIR濾波算法實現(xiàn)。也或者將文中函數(shù)進(jìn)行匯編級優(yōu)化。

最近開的號,沒有留言功能,設(shè)置了小程序留言功能,歡迎點下面進(jìn)行留言討論。

點擊留言/查看留言

END

如果喜歡右下點個在看,也會讓我倍感鼓舞

往期精彩推薦




▲深度解析U-Boot網(wǎng)絡(luò)實現(xiàn)(長篇好文)
讀U-Boot源碼-C語言編程大法總結(jié)篇一
讀U-Boot源碼-C語言編程技巧總結(jié)篇二
基于Buildroot的Linux系統(tǒng)構(gòu)建之根文件系統(tǒng)
U-Boot架構(gòu)淺析

關(guān)注置頂: 掃描右下二維碼關(guān)注公眾號加星
討論加群:掃描左下二維碼添加,發(fā)送“加群”

關(guān)注

加群

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉