你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【原创】【安富莱——DSP教程】第40章 IIR滤波器的实现

[复制链接]
baiyongbin2009 发布时间:2015-4-28 10:04
特别说明:完整45期数字信号处理教程,原创高性能示波器代码全开源地址:链接
* ^; g; L' j9 U8 `5 f& ^- P2 ~

- s4 K- s  T. J. |
第40章 IIR滤波器的实现

- y  U1 l# W( r* w) G3 }
    本章节讲解IIR滤波器直接I型的低通,高通,带通和带阻滤波器的实现。
    40.1 IIR滤波器介绍
    40.2 Matlab工具箱fdatool生成IIR滤波器系数
    40.3 IIR低通滤波器设计
    40.4 IIR高通滤波器设计
    40.5 IIR带通滤波器设计
    40.6 IIR带阻滤波器设计
    40.7 总结
4 E$ o8 ^: q8 G. P$ W5 D
40.1 IIR滤波器介绍
    ARM官方提供的直接I型IIR库支持Q7,Q15,Q31和浮点四种数据类型。其中Q15和Q31提供了基于Cortex-M3和Cortex-M4的快速版本。
    直接I型IIR滤波器是基于二阶Biquad级联的方式来实现的。每个Biquad由一个二阶的滤波器组成:
y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
    直接I型算法每个阶段需要5个系数和4个状态变量。
40.1.png
    这里有一点要特别的注意,有些滤波器系数生成工具是采用的下面公式实现:
y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
    比如matlab就是使用上面的公式实现的,所以在使用fdatool工具箱生成的a系数需要取反才能用于直接I型IIR滤波器的函数中。
    高阶IIR滤波器的实现是采用二阶Biquad级联的方式来实现的。其中参数numStages就是用来做指定二阶Biquad的个数。比如8阶IIR滤波器就可以采用numStages=4个二阶Biquad来实现。
40.2.png
如果要实现9阶IIR滤波器就需要将numStages=5,这时就需要其中一个Biquad配置成一阶滤波器(也就是b2=0,a2=0)。

  Z2 H( ?% k- V' W. A$ x* }, y- {3 U3 t3 m9 o- @& b
赞 收藏 2 评论10 发布时间:2015-4-28 10:04

举报

10个回答
baiyongbin2009 回答时间:2015-4-28 10:13:21
40.2 Matlab工具箱fdatool生成IIR滤波器系数
    前面介绍FIR滤波器的时候,我们讲解了如何使用fdatool生成C头文件,从而获得滤波器系数。这里不能再使用这种方法了,主要是因为通过C头文件获取的滤波器系数需要通过ARM官方的IIR函数调用多次才能获得滤波结果,所以我们这里换另外一种方法。
    下面我们讲解如何通过fdatool工具箱生成滤波器系数。首先在matlab的命令窗口输入fdatool就能打开这个工具箱:
40.3.png
fdatool界面打开效果如下:
40.4.png
IIR滤波器的低通,高通,带通,带阻滤波的设置会在下面一一讲解,这里说一下设置后相应参数后如何生成滤波器系数。参数设置好以后点击如下按钮:
40.5.png
点击Design Filter之后,注意左上角生成的滤波器结构:
40.6.png
默认生成的IIR滤波器类型是Direct-Form II, Second-Order Sections(直接II型,每个Section是一个二阶滤波器)。这里我们需要将其转换成Direct-Form I, Second-Order Sections,因为本章使用的IIR滤波器函数是Direct-Form I的结构。
    转换方法,点击Edit->Convert Structure,界面如下,这里我们选择第一项,并点击OK:
40.7.png
转换好以后再点击File-Export,第一项选择Coefficient File(ASCII):
40.8.png
第一项选择好以后,第二项选择Decimal:
40.9.png
两个选项都选择好以后,点击Export进行导出,导出后保存即可:
40.10.png
保存后Matlab会自动打开untitled.fcf文件,可以看到生成的系数:
  1. %
    2 n/ M! p8 ]5 o( R* Z( T
  2. % Generated by MATLAB(R) 7.14 and the Signal Processing Toolbox 6.17.$ c1 `% G" {  K
  3. %4 V. F: e; |# k6 J9 b% A! G) d0 g* _
  4. % Generated on: 30-Dec-2014 21:08:505 M1 J& X( S( X
  5. %7 d6 v  g& d7 h3 O# {

  6.   C9 G/ p& M4 {! J! F' s3 w  e# s
  7. % Coefficient Format: Decimal
    + b$ |! D  `* X' Y& f
  8. % W9 v! I" D0 M1 R/ A, y. W
  9. % Discrete-Time IIR Filter (real)                            ' E3 L  j' S# k4 ^, ?8 Z
  10. % -------------------------------                           
    . M* u* c# H( x- f* t6 k3 X
  11. % Filter Structure    : Direct-Form II, Second-Order Sections# [" T+ O" B( h
  12. % Number of Sections  : 2                                    
    : F( V8 K) n& R- Y4 |& C6 T
  13. % Stable              : Yes                                  0 ^5 |* e5 h7 l$ C1 `; A8 u: \
  14. % Linear Phase        : No                                   # [5 P" ]4 \; X5 [5 I, a

  15. 9 B) }( J% b5 M" L
  16.                                                             ! I% w* z) _. z% k# @) b# d) o
  17. SOS Matrix:                                                  
    / M  }4 {9 v6 ~: C$ z+ X
  18. 1  2  1  1  -1.1130298541633479   0.57406191508395477        ; E2 o- W: E$ N1 m
  19. 1  2  1  1  -0.85539793277517018  0.20971535775655475        ; k1 q, ?, O* |: R1 |! b  G
  20.                                                              % }/ W9 I, L* x6 t' J3 ]. P
  21. Scale Values:                                                
    9 ]$ C; L* H$ }- D$ z) f
  22. 0.11525801523015171                                          
    ' B/ S+ ~. o: X# ~6 o
  23. 0.08857935624534613
复制代码
由于咱们前面选择的是4阶IIR滤波,生成的结果就是由两组二阶IIR滤波系数组成,系数的对应顺序如下:
  1. SOS Matrix:                                                  5 A. V8 ^) J, j
  2. 1   2   1   1   -1.1130298541633479   0.57406191508395477        ) k0 ~" I" f/ R
  3. b0  b1  b2  a0        a1                      a2
    , K% c* S/ a- ?% F5 T# @
  4. 1 2   1   1   -0.85539793277517018  0.20971535775655475        
    1 K1 U. w7 e1 a4 M7 P* q  q4 V2 B
  5. b0  b1  b2  a0        a1                      a2
复制代码
注意,实际使用ARM官方的IIR函数调用的时候要将a1和a2取反。另外下面两组是每个二阶滤波器的增益,滤波后的结果要乘以这两个增益数值才是实际结果:
  1. 0.11525801523015171                                          2 G3 r6 K7 R/ }9 F
  2. 0.08857935624534613
复制代码
实际的滤波系数调用方法,看下面的例子即可。
  q  C) {' L, W7 [& }# `% N
stary666 回答时间:2015-4-28 10:20:58
沙发,支持原创
baiyongbin2009 回答时间:2015-4-28 10:21:58
40.3 IIR低通滤波器设计
    本章使用的IIR滤波器函数是arm_biquad_cascade_df1_f32。下面使用此函数设计IIR低通,高通,带通和带阻滤波器。
40.3.1 函数arm_biquad_cascade_df1_f32说明
函数定义如下:
    void arm_biquad_cascade_df1_f32(
            const arm_biquad_casd_df1_inst_f32 * S,
            float32_t * pSrc,
            float32_t * pDst,
           uint32_t blockSize)
参数定义:
       [in]  *S         points to an instance of the floating-point Biquad cascade structure.   
       [in]  *pSrc      points to the block of input data.   
      [out] *pDst      points to the block of output data.   
      [in]  blockSize  number of samples to process per call.   
      return     none.   
注意事项:
结构arm_fir_instance_f32的定义如下(在文件arm_math.h文件):
      typedef struct
      {
      /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
      uint32_t numStages;   
       /**< Points to the array of state coefficients. The array is of length 4*numStages. */
      float32_t *pState;
      /**< Points to the array of coefficients.  The array is of length 5*numStages. */
          float32_t *pCoeffs;
      } arm_biquad_casd_df1_inst_f32;
特别注意,参数pState指向的数组大小要是4倍的numStages,pCoeffs指向的数组大小要是5倍的numStages。
1. 参数pCoeffs指向滤波因数,滤波因数数组长度为numTaps。但要注意pCoeffs指向的滤波因数应该按照如下的顺序进行排列:
       {b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
    先放第一个二阶Biquad系数,然后放第二个,以此类推。
2. pState指向状态变量数组。
3. blockSize 这个参数的大小没有特殊要求,用户只需保证大于1且小于等于采样点个数即可。

9 c/ M# s0 L& D7 b5 k, A
40.3.2 fdatool获取低通滤波器系数
    设计一个如下的例子:
    信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个巴特沃斯滤波器低通滤波器,采用直接I型,截止频率80Hz,采样400个数据,滤波器阶数设置为4。fadtool的配置如下:
40.11.png
配置好低通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。
/ y9 x& o5 s/ ^0 Z6 {! b
40.3.3 低通滤波器实现
    通过工具箱fdatool获得低通滤波器系数后在开发板上运行函数arm_biquad_cascade_df1_f32来测试低通滤波器的效果。
  1. #define numStages  2                /* 2阶IIR滤波的个数 */' H- H  `' U; a& z+ Q  z9 e9 Q
  2. #define TEST_LENGTH_SAMPLES  400    /* 采样点数 */4 K1 L0 M) T4 c, a0 q

  3. ( O' t$ h( U" Y( M/ v  Y4 H
  4. static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
    8 l" K- m# }. {- ^  ?) p
  5. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
      V# u9 h$ H1 V6 O4 L; `" w
  6. static float32_t IIRStateF32[4*numStages];                      /* 状态缓存,大小numTaps + blockSize - 1*/" y4 K- x( C& p9 t& }
  7.                                                                              & }) j* x4 f+ M  x6 ]. c8 E% a
  8. /* 巴特沃斯低通滤波器系数 80Hz*/                                                                                                                                         . K9 g- f3 D3 N: g$ c3 u
  9. const float32_t IIRCoeffs32LP[5*numStages] = {
    ) X& |3 m0 ^* _5 h& ?' ^7 d
  10. 1.0f,  2.0f,  1.0f, 1.4797988943972167f,  -0.68867695305386178f,        / u: |# {% M! S1 w$ s1 V" j2 [
  11. 1.0f,  2.0f,  1.0f, 1.2128120926202184f,  -0.38400416228655354f                          
    3 |9 j% ]2 u; X0 u! @
  12. };
    - Q  g: [$ m$ |% h6 ^: v: T
  13. /*
    6 n1 p& S& E* V4 V3 v' l
  14. *********************************************************************************************************
    1 r* q5 s2 l7 d3 G
  15. *        函 数 名: arm_iir_f32_lp; X1 U  t3 a6 v& U: e
  16. *        功能说明: 调用函数arm_iir_f32_lp实现低通滤波器9 Y3 I% F" U- ?6 C
  17. *        形    参:无
    : m( e8 y/ \  M& S& f# O
  18. *        返 回 值: 无
    ; f" A# _8 ~. S
  19. *********************************************************************************************************- G+ [' q: }  P' u' Z7 _+ L( i
  20. */
    . [- {6 L! c& w' Q! ~- K" }
  21. static void arm_iir_f32_lp(void)8 o, L- V6 ~- V
  22. {# F3 q. H' y, \* n+ E: E7 s4 c
  23. uint32_t i;
    4 ^# k# s8 E5 c3 I) y$ U
  24. arm_biquad_casd_df1_inst_f32 S;2 p1 Q  v) B1 T! R
  25. float32_t ScaleValue;
    / @) L5 n2 B. c% @; N9 ]$ ~

  26. 5 R( @9 V. |& O/ F
  27. /* 初始化 */. M# v3 [) A' o* D% X
  28. arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32LP[0], (float32_t+ y- H* `; E7 r
  29. *)&IIRStateF32[0]);
    + d; Q: S8 S3 |" @3 u: |
  30. /* IIR滤波 */
    9 ?% E5 I% y% S7 r8 j7 x; k# C2 N
  31.         arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, TEST_LENGTH_SAMPLES);# Y+ _5 ?. \9 g$ j: d' v& s6 _/ O
  32. /*放缩系数 */
    & u3 j+ T( N. I! }
  33. ScaleValue = 0.052219514664161221f * 0.04279801741658381f 5 {% m; i- m( y" O, Z$ ~
  34. /* 打印滤波后结果 */1 m0 H( M) H# k, E9 K
  35. for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    0 x$ ^6 F' I9 s9 y$ y8 ^" K: y
  36. {+ b$ W! G: [# n5 F1 K- {7 J; u
  37. printf("%f\r\n", testOutput[i]*ScaleValue);3 H& b3 m+ u+ ~: j
  38. }$ Z) _; n! J" k
  39. }
复制代码
运行如上函数可以通过串口打印出函数arm_biquad_cascade_df1_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。
    对比前需要先将串口打印出的一组数据加载到Matlab中, arm_biquad_cascade_df1_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
  1. fs=1000;              %设置采样频率 1K* c+ F4 R$ h1 [
  2. N=400;               %采样点数      
    - {# \# `" ^! M5 [2 L" Z
  3. n=0:N-1;
    5 b+ B& H8 t4 U8 N% Y9 }# x# {- |
  4. t=n/fs;                %时间序列7 o9 ^- |. n$ o" n% c
  5. f=n*fs/N;              %频率序列
    . b$ q! q) l& m8 @2 r; B' W# k( P

  6. # O& \/ ~0 z4 R6 y# c
  7. x1=sin(2*pi*50*t);
    0 g! M6 ~$ A- b% H% N. J. @, E' I: R
  8. x2=sin(2*pi*200*t);     %50Hz和200Hz正弦波
    * i1 a$ X! m6 B7 h% E+ K+ B
  9. subplot(211);% `' K1 w- [  P! E, S- i
  10. plot(t, x1);1 \$ V" W8 r% n/ ?
  11. title('滤波后的理想波形');* Y8 R# h4 \. L
  12. grid on;
    5 u1 [( X' V! S/ Q4 e1 @. K: m

  13. ! t* o8 f* H- j8 Q- K* [
  14. subplot(212);2 u. @9 d+ D# r- S
  15. plot(t, sampledata);
    ; ?' c4 R, {3 R4 j
  16. title('ARM官方库滤波后的波形');8 ~. W3 m$ ]6 X0 M
  17. grid on;
复制代码
Matlab计算结果如下:
40.12.png
从上面的波形对比来看,matlab和函数arm_biquad_cascade_df1_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
  1. fs=1000;                %设置采样频率 1K3 ]# x+ J5 u7 A+ }( Q- V6 ^) x
  2. N=400;                 %采样点数      
    0 j- C5 n  @/ d2 I
  3. n=0:N-1;
    , {6 ^) A" c) ~
  4. t=n/fs;                  %时间序列
    $ w/ ]8 r' @4 z/ h
  5. f=n*fs/N;                %频率序列
    ! S8 \# v; }! W

  6.   y$ b) }  a1 a/ [- e6 c
  7. x = sin(2*pi*50*t) + sin(2*pi*200*t);      %50Hz和200Hz正弦波合成. I6 y1 w$ |; a" d  F
  8.   8 L( \7 m4 p  q7 V) s, J# o' z" v
  9. subplot(211);7 g$ {9 p$ T: C) l2 w- _/ {
  10. y=fft(x, N);                %对信号x做FFT   
      o) f, `& @7 u1 P1 X; l- g
  11. plot(f,abs(y));
    4 `* @! ?( \" y5 T/ {
  12. xlabel('频率/Hz');
    % r5 [% _% B4 E* V, U! R- e  |0 B9 r
  13. ylabel('振幅');
    $ K' w- r+ H( C/ J# {9 E2 t1 [
  14. title('原始信号FFT');
    0 ]4 {; x- W) u
  15. grid on;+ _) D: l% T9 Q- X0 ^" F7 V
  16. 2 {! u2 H; T! H6 L
  17. y3=fft(sampledata, N);    %经过IIR滤波器后得到的信号做FFT
    + ?9 O/ y- @0 Y' ~; y9 Y
  18. subplot(212);                              
    % s9 r: z  {+ \9 S! s7 B
  19. plot(f,abs(y3));
    ) e0 k1 X+ u( \$ l: d
  20. xlabel('频率/Hz');
    ' U1 z  X+ J$ c2 J2 F
  21. ylabel('振幅');
    , p8 @# [7 I# P' O; x
  22. title('IIR滤波后信号FFT');& y& S. l3 K) D9 `
  23. grid on;
复制代码
Matlab计算结果如下:
40.13.png
上面波形变换前的FFT和变换后FFT可以看出,200Hz的正弦波基本被滤除。
% b' ]0 m( S5 i2 f  X
baiyongbin2009 回答时间:2015-4-28 10:27:34
40.4 IIR高通滤波器设计
5 X! \2 Q% s' m4 f; F
40.4.1 fdatool获取高通滤波器系数
    设计一个如下的例子:
    信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个巴特沃斯滤波器高通滤波器,采用直接I型,截止频率140Hz,采样400个数据,滤波器阶数设置为4。fadtool的配置如下:
40.14.png
配置好高通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。

5 p3 G( J3 w! B* p6 ^
40.4.2 高通滤波器实现
    通过工具箱fdatool获得高通滤波器系数后在开发板上运行函数arm_biquad_cascade_df1_f32来测试高通滤波器的效果。
  1. #define numStages  2                /* 2阶IIR滤波的个数 */
    7 o+ {1 k* m+ r2 }" U
  2. #define TEST_LENGTH_SAMPLES  400    /* 采样点数 */
    . V' c4 Q, }$ r( v: w/ D! U, p
  3. . ~- }9 A) }+ k# C6 M2 l7 _0 t
  4. static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
      z3 S0 {! T8 @& _
  5. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */, S2 ~$ X- [7 V6 Z# f) h! z
  6. static float32_t IIRStateF32[4*numStages];                      /* 状态缓存,大小numTaps + blockSize - 1*/0 H! y: X$ t5 P. Y/ H/ C" {
  7.                                                                              
    3 v% A4 S( r# J3 l) l' B, @- `
  8. /* 巴特沃斯高通滤波器系数 140Hz */                                                                                                                                         ( o, j( A$ _5 C. D/ R' ^
  9. const float32_t IIRCoeffs32HP[5*numStages] = {" ^( p) @& f( X5 ^8 I1 R7 F" g
  10. 1.0f,  -2.0f,  1.0f,  0.9845430147411518f,   -0.54456536085081642f,      
    ' j/ x7 e  |1 v( T$ e) ?' |
  11. 1.0f,  -2.0f,  1.0f,  0.74471447786432121f,  -0.16831887384397309f,                                
    8 S, k) O) k+ O1 M% a
  12. };
    ' a# ~3 E" d1 J, M

  13. / t+ G6 d  |% b6 U. ?
  14. /*
    & n2 {* d  y' @% s4 [/ t
  15. *********************************************************************************************************4 S" K$ P( J( U5 ^/ @$ `2 e
  16. *        函 数 名: arm_iir_f32_hp
    8 k+ ]# n0 }: G6 m, T9 z3 W
  17. *        功能说明: 调用函数arm_iir_f32_hp实现高通滤波器2 ?  d9 Q$ ?% d- ]) R6 f& e* A
  18. *        形    参:无  G! g- G9 G" a
  19. *        返 回 值: 无+ G( F3 K+ d. F! O3 B4 ^5 a
  20. *********************************************************************************************************
    & l! I, y! ], g' f+ x( h* w5 n( h7 s7 D7 A
  21. */
    ; Q) F( p. J( @3 i
  22. static void arm_iir_f32_hp(void)! C3 `* j2 y: _# v
  23. {
    0 F3 ^. }. `" v9 W, _9 V1 h
  24. uint32_t i;
    % Q6 X' I1 O( ~
  25. arm_biquad_casd_df1_inst_f32 S;
    5 m2 W% j% ^/ S8 C/ [
  26. float32_t ScaleValue;# b" ?  X; l4 c2 s5 u" V+ u, ^' J

  27. ) u( }( N9 S6 ^
  28. /* 初始化 */
    2 j& @' Q" {  F+ a" u  ]
  29. arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32HP[0], (float32_t
    8 |% ]- F% |* e( Q) p3 u
  30. *)&IIRStateF32[0]);! V( |  T9 d1 f( X) }2 j
  31. /* IIR滤波 */
    + t7 Z  b/ ~2 V* E; Q
  32.         arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, TEST_LENGTH_SAMPLES);  @* p0 r/ q& q2 O2 x, B
  33.    
      ^4 @; g& K6 S3 d/ n
  34. /*放缩系数 */    2 y, v$ n1 i/ P. T' L
  35. ScaleValue = 0.63227709389799203f * 0.47825833792707356f;  / k; b& @3 `; |' Y
  36. /* 打印滤波后结果 */
    : P1 [# w2 o3 J9 e6 K
  37. for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    ' ^: Z4 F% e! v5 S! s" n
  38. {
    , Z8 ?' l  F; I/ L4 y0 ~7 j
  39. printf("%f\r\n", testOutput[i]*ScaleValue);1 b. ~5 d, p% D. }# T' t. P& H
  40. }" {+ O/ b; l, v- M: i9 f4 L
  41. }
复制代码
运行如上函数可以通过串口打印出函数arm_biquad_cascade_df1_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。
    对比前需要先将串口打印出的一组数据加载到Matlab中, arm_biquad_cascade_df1_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
  1. fs=1000;              %设置采样频率 1K
    / h8 q0 O9 u; o; ?, `+ j
  2. N=400;               %采样点数      9 `6 L3 t6 h; h4 w% w
  3. n=0:N-1;
    ; J( F4 Q8 x* [; _: o% R' I, P
  4. t=n/fs;                %时间序列7 ]3 o- d# D. P0 t2 W& x
  5. f=n*fs/N;              %频率序列
    1 \7 P0 O9 {, S) A

  6. 2 H7 j$ q* D  ?$ I
  7. x1=sin(2*pi*50*t);6 K, W) s( P9 o" g
  8. x2=sin(2*pi*200*t);     %50Hz和200Hz正弦波
    3 j$ R8 Z0 }( W2 B& b
  9. subplot(211);2 d1 Q: w$ e* f/ @
  10. plot(t, x2);  t: ^1 p7 y! q# J  }
  11. title('滤波后的理想波形');. @8 k8 ?9 T, e7 C. R
  12. grid on;3 E" D- w# p( T2 a

  13. , e% B% I, f8 D! L2 I, M8 {7 A
  14. subplot(212);
    ! M  C) A, [# u9 _4 H# z
  15. plot(t, sampledata);
    3 x4 g2 {/ j+ W2 W
  16. title('ARM官方库滤波后的波形');
    4 ?# p8 i2 b- G% X2 l4 O
  17. grid on;
复制代码
Matlab计算结果如下:
40.15.png
从上面的波形对比来看,matlab和函数arm_biquad_cascade_df1_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
  1. fs=1000;                %设置采样频率 1K+ k* h6 X+ ~/ i9 w0 T3 v
  2. N=400;                 %采样点数      7 P+ h7 K3 V1 ^$ G5 ^6 `* c; h
  3. n=0:N-1;
      C( @# z7 N! |: \' W% O) g
  4. t=n/fs;                  %时间序列( `; I0 Y/ B9 f8 q
  5. f=n*fs/N;                %频率序列1 X, |; `5 a- t% S; n# o6 R. R

  6. 1 B- M/ _6 p8 b
  7. x = sin(2*pi*50*t) + sin(2*pi*200*t);      %50Hz和200Hz正弦波合成/ ?" r! ?/ a$ z+ W
  8.   
    & |) g3 J" z" X2 s7 h) }
  9. subplot(211);0 J) K, {* U/ W0 M
  10. y=fft(x, N);                %对信号x做FFT   ) c9 A- o' N$ @3 D
  11. plot(f,abs(y));( K3 C/ m  y& e/ n) g  h
  12. xlabel('频率/Hz');
    : Q7 {! n+ g3 O- b6 h
  13. ylabel('振幅');
    ( ^" m1 r. [* Y  z
  14. title('原始信号FFT');
    ( O; m; x- t5 `! Z( q- @8 s
  15. grid on;0 j/ z0 @/ y: t: D0 a
  16. + N" P0 @( E6 q- m1 l4 |
  17. y3=fft(sampledata, N);    %经过IIR滤波器后得到的信号做FFT
    # a9 r2 r2 l( v6 I
  18. subplot(212);                              
    9 ^+ s* ^) J5 W. J5 t# l
  19. plot(f,abs(y3));
    # a9 S+ H* ]" E
  20. xlabel('频率/Hz');
    * @8 x: X, y* K! A
  21. ylabel('振幅');+ _4 x- Q9 W: y1 h$ l! O
  22. title('IIR滤波后信号FFT');
    , n* C: W" C% l: Y$ ~7 n8 D
  23. grid on;
复制代码
Matlab计算结果如下:
40.16.png
上面波形变换前的FFT和变换后FFT可以看出,50Hz的正弦波基本被滤除。

  @2 I) Z# M' r3 R
baiyongbin2009 回答时间:2015-4-28 10:32:14
40.5 IIR带通滤波器设计, H% l! y2 O& N- E
40.5.1 fdatool获取低通滤波器系数
    设计一个如下的例子:
    信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个巴特沃斯滤波器带通滤波器,采用直接I型,截止频率140Hz和,采样400个数据,滤波器阶数设置为4。fadtool的配置如下:
40.17.png
配置好带通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。

' I9 R" x) N% i, I9 {4 c/ m+ m
40.5.2 带通滤波器实现
    通过工具箱fdatool获得带通滤波器系数后在开发板上运行函数arm_biquad_cascade_df1_f32来测试带通滤波器的效果。
  1. #define numStages  2                /* 2阶IIR滤波的个数 */( I- @5 Z) Q' H! T+ I
  2. #define TEST_LENGTH_SAMPLES  400    /* 采样点数 */
    6 E" b. j) _  d. N' I
  3. ) v0 a4 m' t7 G
  4. static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
    2 ~% a0 p3 l  z  P
  5. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */3 p- R# |9 [% ]( c) a
  6. static float32_t IIRStateF32[4*numStages];                      /* 状态缓存,大小numTaps + blockSize - 1*// f' i0 ~( u6 o6 F+ D
  7.                                                                              
    & P. v" j8 T' O/ E6 u3 d5 K* Q
  8. /* 巴特沃斯带通滤波器系数140Hz 400Hz*/                                                                                                                                         
    1 j4 K! q. Q1 z# C9 O6 {4 R: g
  9. const float32_t IIRCoeffs32BP[5*numStages] = {
    : R. \# k" D* L" X9 `
  10. 1.0f,  0.0f,  -1.0f,    -1.1276518720541668f,   -0.47001314508753411f,      ! V8 q# d0 I( h3 c
  11. 1.0f,  0.0f,  -1.0f,    0.77495305804604886f,  -0.36707750055668387f                              
    " E, h0 v8 Q. `; [% ]
  12. };
    " c3 J" E4 u! \3 x7 V6 L! O

  13.   w+ e% Y. M- i- ~) F8 K+ ]
  14. /*$ U3 t# L# r2 E5 J6 O9 e9 ^
  15. *********************************************************************************************************6 l2 b) u4 x* B! O0 Z) G
  16. *        函 数 名: arm_iir_f32_bp( p, ?2 R3 F2 Y* p, P; v# k
  17. *        功能说明: 调用函数arm_iir_f32_hp实现带通滤波器- m0 E8 J6 Z, z
  18. *        形    参:无: ~; S, `0 i( W6 O+ o# a
  19. *        返 回 值: 无* e2 I* h0 f( w* {1 K4 `
  20. *********************************************************************************************************
    7 q7 ?( K$ V( N7 [8 B, E
  21. */
    ! k) K5 n- d) U2 E
  22. static void arm_iir_f32_bp(void)$ J3 s; U7 V) \8 ?
  23. {
    , ~; v3 e0 s, U: ^: m
  24. uint32_t i;
    0 e0 T! j- o: N( U) p$ [1 W- e! {7 n0 b
  25. arm_biquad_casd_df1_inst_f32 S;
    4 {, P, C' l. ?. A* n" _7 u
  26. float32_t ScaleValue;% F' f, A, B( E4 k0 X

  27. 6 {. S4 l# J" j/ Q4 k: V5 r
  28. /* 初始化 */
    $ W6 E% P8 ^5 W2 [
  29. arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32BP[0], (float32_t
    % D$ `5 @! Y7 h7 ^2 [8 h+ e1 [; P9 A
  30. *)&IIRStateF32[0]);
    - _* i# j, |* P) t
  31. /* IIR滤波 */; {% V6 L9 I9 X; Y* K
  32.         arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, TEST_LENGTH_SAMPLES);
    8 p) _$ h0 M% `& l8 S
  33.    
    ; ~  G: j/ V& K+ u" L
  34. /*放缩系数 */   
    # c5 ~; L: N& Y# f' W
  35. ScaleValue = 0.55815658576077365f * 0.55815658576077365f;  
    9 o# H! h2 B. r4 h+ E4 B' Q+ F8 x
  36. /* 打印滤波后结果 */
    9 e- |4 q% {* i# S$ Q0 _1 Y
  37. for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    2 e8 C% t: M8 Y& S; J. R
  38. {
    3 N0 J0 i  u% B1 T9 p1 B
  39. printf("%f\r\n", testOutput[i]*ScaleValue);
    % o) v4 T( u) |0 F. Y, j
  40. }
    + q3 b5 q; [9 \6 L
  41. }
复制代码
运行如上函数可以通过串口打印出函数arm_biquad_cascade_df1_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。
    对比前需要先将串口打印出的一组数据加载到Matlab中, arm_biquad_cascade_df1_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
  1. fs=1000;              %设置采样频率 1K, J- S; x5 [' T/ M+ _) l
  2. N=400;               %采样点数      % u7 x# M. }- y. ~
  3. n=0:N-1;
    5 k; K1 g: x, x* ^  L8 B/ k
  4. t=n/fs;                %时间序列
    4 N7 R4 i; \. w1 l, h! J+ A
  5. f=n*fs/N;              %频率序列
    ! \2 s% I! e: x& E# I$ x; l
  6. : b8 `9 S% a1 @  w: Q6 j
  7. x1=sin(2*pi*50*t);
    ) R6 U7 `+ V$ k, E
  8. x2=sin(2*pi*200*t);     %50Hz和200Hz正弦波& U0 W) _( }0 |: u1 b! i0 l
  9. subplot(211);
    0 S" D' y* Z& l/ O% T  Q
  10. plot(t, x1);& W6 {; U1 U( R) B% ]' `' z
  11. title('滤波后的理想波形');
    ! T0 l' H; M  ]6 d  ?5 y
  12. grid on;6 c) {9 j( }5 D0 ?: T

  13. , N' ^# e" Y3 Q7 n# x
  14. subplot(212);- b0 f' l+ ?9 ~: B. H. T# y
  15. plot(t, sampledata);
    $ o' D! ?6 t9 ^. E- f, K. v
  16. title('ARM官方库滤波后的波形');9 M2 I& Z# s! V8 g+ e6 V
  17. grid on;
复制代码
Matlab计算结果如下:
40.18.png
从上面的波形对比来看,matlab和函数arm_biquad_cascade_df1_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
  1. fs=1000;                %设置采样频率 1K
    + d5 H6 g/ S# w4 J$ U$ H# S/ A4 x8 C* ^
  2. N=400;                 %采样点数      
    , p' M; G0 d) p0 S
  3. n=0:N-1;* F7 g7 g% r8 i2 S5 \& w
  4. t=n/fs;                  %时间序列
    2 W9 c9 t- W: h- k8 g/ K) W
  5. f=n*fs/N;                %频率序列
    9 I, b" l7 e" m. T& O+ o5 w* F" L
  6. . ~/ B* q" |9 P( B
  7. x = sin(2*pi*50*t) + sin(2*pi*200*t);      %50Hz和200Hz正弦波合成  @; h4 ?. r. J$ w- L( J. d5 c
  8.   5 b4 a0 M8 Z( \: [" u
  9. subplot(211);0 d$ ]" x1 n- G* ]$ f7 a# X
  10. y=fft(x, N);                %对信号x做FFT   
    % e) h9 l. K$ s% [/ O
  11. plot(f,abs(y));
    / k1 _' k6 R' B. h
  12. xlabel('频率/Hz');
    ; f- h0 v, N% m  X. e+ e! N5 Q
  13. ylabel('振幅');
    3 a/ @0 C- S$ M6 u6 b& w. C) d
  14. title('原始信号FFT');
    9 ]6 u7 c+ R+ o5 J& H4 b
  15. grid on;, m6 }" s; m/ d. l3 o" e
  16. 6 O8 u  C  W! M
  17. y3=fft(sampledata, N);    %经过IIR滤波器后得到的信号做FFT2 k7 [: A: K1 `2 d) Z
  18. subplot(212);                              
    # D7 O7 \/ o) V) {) j' k3 E
  19. plot(f,abs(y3));
    2 F: y, i& i& m5 n  g7 y5 w
  20. xlabel('频率/Hz');' [" p8 {9 G" ]3 F2 u/ `6 L
  21. ylabel('振幅');
    % ]% q( G* L$ D7 a5 B/ `
  22. title('IIR滤波后信号FFT');
    4 H- q% z7 j/ ^# j9 f! {2 S4 R
  23. grid on;
复制代码
Matlab计算结果如下:
40.19.png
上面波形变换前的FFT和变换后FFT可以看出,50Hz的正弦波基本被滤除。

( D. H8 p1 W$ R4 u
wamcncn 回答时间:2015-4-28 11:14:32
标记学习
baiyongbin2009 回答时间:2015-4-28 12:45:41
40.6 IIR带阻滤波器设计
7 t8 Y- n# u/ ~+ N$ S
40.6.1 fdatool获取带阻滤波器系数
    设计一个如下的例子:
    信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个巴特沃斯滤波器带阻滤波器,采用直接I型,截止频率100Hz和325Hz,采样400个数据,滤波器阶数设置为4。fadtool的配置如下:
40.20.png
配置好带阻滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。

( V* n% o1 W3 J. k& N3 q  ?
40.6.2 带阻滤波器实现
    通过工具箱fdatool获得带阻滤波器系数后在开发板上运行函数arm_biquad_cascade_df1_f32来测试带阻滤波器的效果。
  1. #define numStages  2                /* 2阶IIR滤波的个数 */
    , n9 I# {. X9 E3 o) u
  2. #define TEST_LENGTH_SAMPLES  400    /* 采样点数 */, k, R. H" z: @" `7 ?

  3. , q) a1 |) ]' x$ X/ C# D
  4. static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
    3 D" E( t+ z2 M3 r
  5. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
    ! K: ~3 J: `. x$ @
  6. static float32_t IIRStateF32[4*numStages];                      /* 状态缓存,大小numTaps + blockSize - 1*/
      p- n' `3 p: y6 {
  7.                                                                              
    ! v) M# ]" D8 L" Q
  8. /* 巴特沃斯带阻滤波器系数100Hz 325Hz*/                                                                                                                                         " `1 x$ s, }% {' B& [
  9. const float32_t IIRCoeffs32BS[5*numStages] = {
      W" u- B% k. \1 {. I9 L+ u* K
  10. 1.0f,  -0.61400192638335005f,  1.0f,  1.1451427879497746f,   -0.50298007146721391f,
    3 L* _) p3 ^5 m. n4 ~8 X: v
  11. 1.0f,  -0.61400192638335005f,  1.0f,  -0.47458704658841883f, -0.35305199748708849f                        
    * `% p% d) o7 H" Y) G
  12. };/ ?, F$ w: R- p" s

  13. 9 e& o# T7 e8 T
  14. /*- O7 b, I* K$ U/ }5 p# B# V: V
  15. *********************************************************************************************************
    ' M7 j6 y* Y- |" b+ c$ l
  16. *        函 数 名: arm_iir_f32_bs9 c2 L$ Q* q/ p' b! O9 `& l
  17. *        功能说明: 调用函数arm_iir_f32_bs实现带阻滤波器
    + j0 P1 v% e, o4 v( r
  18. *        形    参:无
    / J. T8 \& D/ n8 t/ }
  19. *        返 回 值: 无
    . w* i* P- B; x" t' i( T) ?
  20. ********************************************************************************************************** J# ]( b' V: K3 @& u. D
  21. */9 w7 J! a5 V( ~, l* E
  22. static void arm_iir_f32_bs(void)/ P" i7 v! G; i% D* W1 ^( I
  23. {
    - I; m4 A# f' F6 ~% T1 L+ s
  24. uint32_t i;- z  J) F" K" d! j" `2 \
  25. arm_biquad_casd_df1_inst_f32 S;
    7 P1 a: V2 K2 H  ~5 G
  26. float32_t ScaleValue;
    ) i  b3 B" E1 w! W! X5 J
  27. : _$ F6 A1 @' I; q
  28. /* 初始化 */6 H9 A- Y& o7 H% y4 {+ W# s
  29. arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32BS[0], (float32_t
    8 ~, B; |3 m4 F# i( R
  30. *)&IIRStateF32[0]);  ~+ F0 f& _- z. E% p
  31. /* IIR滤波 */
    ! J3 Y4 j4 n: z" P
  32.         arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, TEST_LENGTH_SAMPLES);0 Z# u& W7 k0 u: t
  33.     ' Q! e* c/ a1 n# ?* p6 q# U* o+ S7 s/ J
  34. /*放缩系数 */   
    8 ^6 _; y; E8 M' H  y% }
  35. ScaleValue = 0.58347920314378698f * 0.58347920314378698f;  
    " U% T2 L: H' _! l6 c8 }
  36. /* 打印滤波后结果 */
    ' p3 {! A9 W+ ~4 H  g
  37. for(i=0; i<TEST_LENGTH_SAMPLES; i++)# q' o9 e  N, _
  38. {% f; Z4 F. p; V. \
  39. printf("%f\r\n", testOutput[i]*ScaleValue);" G3 O: z" U! i
  40. }  o$ g% j0 `* U  o/ x7 N
  41. }
复制代码
运行如上函数可以通过串口打印出函数arm_biquad_cascade_df1_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。
    对比前需要先将串口打印出的一组数据加载到Matlab中, arm_biquad_cascade_df1_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
  1. fs=1000;              %设置采样频率 1K+ t+ ?9 B$ S* I8 ?& D; E+ w2 t6 f
  2. N=400;               %采样点数      
    0 f2 B+ E9 b/ s9 q6 L# W6 m
  3. n=0:N-1;- K: F) ^: p8 p
  4. t=n/fs;                %时间序列$ ]( k% ^0 R# B' g$ J- M) R
  5. f=n*fs/N;              %频率序列8 g  j5 d6 M% q0 Y
  6. 9 }  y$ F; k$ n. Z; P+ G! v+ k, r& l8 T
  7. x1=sin(2*pi*50*t);
    : v- F% l; b+ [8 }
  8. x2=sin(2*pi*200*t);     %50Hz和200Hz正弦波" y& L2 A2 I& ]6 j7 I0 ]7 J
  9. subplot(211);
    6 d% j3 I: |: q- K* ~; o
  10. plot(t, x1);
    $ A2 t: z: t2 S5 h4 |
  11. title('滤波后的理想波形');6 c0 M  f+ E8 w8 S1 L; H3 P( D, j5 Q
  12. grid on;( P& L! @8 p) z8 t+ v& ~

  13. " i: l& W& h) U2 ~9 _
  14. subplot(212);* U2 w) [% E: ^) G
  15. plot(t, sampledata);& ~9 Y( d) _$ u' R! c7 T) U
  16. title('ARM官方库滤波后的波形');; S2 [; M/ x& T" {0 G/ b  t  w- b
  17. grid on;
复制代码
Matlab计算结果如下:
40.21.png
从上面的波形对比来看,matlab和函数arm_biquad_cascade_df1_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
  1. fs=1000;                %设置采样频率 1K+ t- M7 k! h. f/ ?* C# x7 y$ ~
  2. N=400;                 %采样点数      5 O2 `" r" G% H6 g; r5 V
  3. n=0:N-1;
    3 N0 m1 W- `- \4 e8 I3 [
  4. t=n/fs;                  %时间序列0 g0 |% S( ?2 G
  5. f=n*fs/N;                %频率序列
    6 u/ y) O6 ]; Z- \3 x3 d
  6. 4 Z2 Z; h! W% P+ V9 D/ o0 U' q
  7. x = sin(2*pi*50*t) + sin(2*pi*200*t);      %50Hz和200Hz正弦波合成4 z# r% H9 j  `( @( {# k! Y
  8.   * G& b4 j' A1 F3 g; C, P
  9. subplot(211);
    $ f5 t! \( {: S3 ^9 P& u' b. G
  10. y=fft(x, N);                %对信号x做FFT   
    " \4 j3 f6 E, G. i# _+ Z  y( U
  11. plot(f,abs(y));
    ' n- A; P8 ?% K
  12. xlabel('频率/Hz');
    * I6 _5 `1 k- ~# J8 n# H( ^2 a8 |
  13. ylabel('振幅');
    & y- i% o  q' y. G+ q# P
  14. title('原始信号FFT');3 E9 Q7 K& V% e0 o6 j, S( i
  15. grid on;
    + j6 K5 ?& F  }$ A) E
  16. ' Y5 R7 J1 L0 ?
  17. y3=fft(sampledata, N);    %经过IIR滤波器后得到的信号做FFT) U% X4 d3 k7 ^- q+ {9 A* Y
  18. subplot(212);                               ' {) i' G# u: |  s: B7 k
  19. plot(f,abs(y3));# J- ~* ~5 w9 [; }, L/ A
  20. xlabel('频率/Hz');
    6 _# V7 J! S% ?
  21. ylabel('振幅');5 _( B1 {2 L3 Q" g$ @& G
  22. title('IIR滤波后信号FFT');
    - G% x% h: k( m7 ?
  23. grid on;
复制代码
Matlab计算结果如下:
40.22.png
上面波形变换前的FFT和变换后FFT可以看出,200Hz的正弦波基本被滤除。

9 A; v6 `8 \3 x4 Q2 x
baiyongbin2009 回答时间:2015-4-28 12:46:42
40.7 总结
    本章节主要讲解了巴特沃斯低通,高通,带通和带阻滤波器的实现,有兴趣的可以使用同样的方法实现切比雪夫滤波器的设计。

, _* q/ l! g6 o' j
XDLH 回答时间:2015-11-15 13:40:28
不错挺好的!受教了!
zhh 回答时间:2020-12-1 15:57:50
输入信号是连续的,每调用一次arm_biquad_cascade_df1_f32函数,开始几个点都会有畸变,如何做到输出信号连续无畸变呢?

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版