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

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

[复制链接]
baiyongbin2009 发布时间:2015-4-28 10:04
特别说明:完整45期数字信号处理教程,原创高性能示波器代码全开源地址:链接
: ?8 Z+ ^/ b3 n
" _, J+ L# w# l$ l# a' K
第40章 IIR滤波器的实现
* ~% _- j* S- D3 v5 W
    本章节讲解IIR滤波器直接I型的低通,高通,带通和带阻滤波器的实现。
    40.1 IIR滤波器介绍
    40.2 Matlab工具箱fdatool生成IIR滤波器系数
    40.3 IIR低通滤波器设计
    40.4 IIR高通滤波器设计
    40.5 IIR带通滤波器设计
    40.6 IIR带阻滤波器设计
    40.7 总结

3 u+ Q! C$ E8 h, V+ B40.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)。

; j+ Z4 w1 [0 @" _; D% u* ]! M. d
' m; b. m1 q. z8 s6 b7 ~0 [# p8 i
收藏 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. %  x- x9 c( m7 A) X. v2 E
  2. % Generated by MATLAB(R) 7.14 and the Signal Processing Toolbox 6.17., C( r7 G& d; J4 `8 F1 S# f
  3. %2 \) s7 _* w" C3 z
  4. % Generated on: 30-Dec-2014 21:08:50
    / m# I% c2 z3 n  x; f
  5. %0 T% N6 a+ r+ ?5 H. l# j9 f
  6.   W4 }; h& `* Y
  7. % Coefficient Format: Decimal
    : e& o; M4 j( X/ Q6 Z# v! @8 Q

  8. 4 S# Q5 T. _/ Z, V1 I
  9. % Discrete-Time IIR Filter (real)                            3 @, l) t( e) ?2 |
  10. % -------------------------------                           
    5 Z( L5 i- O0 d3 W1 H0 y& o
  11. % Filter Structure    : Direct-Form II, Second-Order Sections
    3 A  J' K8 @6 L. @
  12. % Number of Sections  : 2                                    
    5 U: z3 j: ?9 A% S. O
  13. % Stable              : Yes                                  , x4 B2 K- F! X: V/ W; `$ D4 j( y0 `8 K
  14. % Linear Phase        : No                                   " R5 X$ \% v3 ]% v4 j' U

  15. - g# q; I  B3 }6 J5 t3 ^4 l
  16.                                                             
    7 y& g2 t  R% l/ _2 g4 V: l
  17. SOS Matrix:                                                  / c( i. y; `8 {1 V0 i
  18. 1  2  1  1  -1.1130298541633479   0.57406191508395477        & O' ~! t4 S% A
  19. 1  2  1  1  -0.85539793277517018  0.20971535775655475        : l5 H0 j5 N7 u( h& p" |
  20.                                                             
    . r1 F* [  R7 F' E( Z1 A" ^
  21. Scale Values:                                                
    * @1 C) P# k  R4 {* `5 n
  22. 0.11525801523015171                                          ( a* ~2 u& u6 _! X8 A+ u" @6 S; _
  23. 0.08857935624534613
复制代码
由于咱们前面选择的是4阶IIR滤波,生成的结果就是由两组二阶IIR滤波系数组成,系数的对应顺序如下:
  1. SOS Matrix:                                                  0 c2 O& y9 V( L$ z, ]
  2. 1   2   1   1   -1.1130298541633479   0.57406191508395477        
    5 M6 m  D/ i1 F* P8 \: Q( X8 {/ T
  3. b0  b1  b2  a0        a1                      a2) t8 M& v9 k8 S+ Z5 H7 r7 l
  4. 1 2   1   1   -0.85539793277517018  0.20971535775655475        
    0 n1 o. x9 c( m5 a
  5. b0  b1  b2  a0        a1                      a2
复制代码
注意,实际使用ARM官方的IIR函数调用的时候要将a1和a2取反。另外下面两组是每个二阶滤波器的增益,滤波后的结果要乘以这两个增益数值才是实际结果:
  1. 0.11525801523015171                                          * u( R! X, p! G5 I, Q! c
  2. 0.08857935624534613
复制代码
实际的滤波系数调用方法,看下面的例子即可。
' [! L& ]: e! M2 A8 i: o
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且小于等于采样点个数即可。

. c; Z- v  C9 [+ e
40.3.2 fdatool获取低通滤波器系数
    设计一个如下的例子:
    信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个巴特沃斯滤波器低通滤波器,采用直接I型,截止频率80Hz,采样400个数据,滤波器阶数设置为4。fadtool的配置如下:
40.11.png
配置好低通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。
2 s" c2 r3 S$ K, U- ]- [/ d2 W2 Y
40.3.3 低通滤波器实现
    通过工具箱fdatool获得低通滤波器系数后在开发板上运行函数arm_biquad_cascade_df1_f32来测试低通滤波器的效果。
  1. #define numStages  2                /* 2阶IIR滤波的个数 */- E0 c& ~8 t4 V
  2. #define TEST_LENGTH_SAMPLES  400    /* 采样点数 */3 J* B9 t7 B( _
  3. ; [! O! Z; v2 z8 V5 A
  4. static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */% Y( k' _# M9 c: Z  w- w) @$ Y! \
  5. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
    & l- j. g5 u" c
  6. static float32_t IIRStateF32[4*numStages];                      /* 状态缓存,大小numTaps + blockSize - 1*/( M3 v+ o9 a+ f5 f( C- I/ ^6 c
  7.                                                                              
    3 Y$ K! @* |0 f
  8. /* 巴特沃斯低通滤波器系数 80Hz*/                                                                                                                                         
      `1 t' K3 A: t. l# y3 J% V& C
  9. const float32_t IIRCoeffs32LP[5*numStages] = {
    " K% v' `1 f0 z4 x* I
  10. 1.0f,  2.0f,  1.0f, 1.4797988943972167f,  -0.68867695305386178f,        
    $ }0 z3 H9 ^7 ^4 _1 s
  11. 1.0f,  2.0f,  1.0f, 1.2128120926202184f,  -0.38400416228655354f                          
    ; |8 Z/ m+ Y: s+ H2 w/ L- c
  12. };
    : i* k( Z" O1 B& e1 H
  13. /*
    + @8 U- n9 \) _
  14. *********************************************************************************************************, I' h$ G" T6 p& t3 F
  15. *        函 数 名: arm_iir_f32_lp
    4 b  C: {' ^# r( G
  16. *        功能说明: 调用函数arm_iir_f32_lp实现低通滤波器. N* W: `" n- N. L
  17. *        形    参:无2 h  J6 c) f) k" i/ ^0 m  X) N
  18. *        返 回 值: 无9 l0 {  ^% G( t4 E% g4 e* t7 [- [
  19. *********************************************************************************************************" J  q+ b2 k2 `+ |# ~0 u
  20. */9 L0 C  {: \& T) E, C. [1 f
  21. static void arm_iir_f32_lp(void)
    ' a( L  j; b! v" P
  22. {
      r; s4 N& g1 h7 H1 R
  23. uint32_t i;* X. `6 l: F* o# k7 x: J1 q
  24. arm_biquad_casd_df1_inst_f32 S;# |, t# E* `! `% }& O
  25. float32_t ScaleValue;( b* T  v" H; C) Y1 e
  26. . P/ Z5 \8 x1 \
  27. /* 初始化 */
    : V. g( n" O/ M9 X/ _% g( _
  28. arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32LP[0], (float32_t9 V& z; ^: \, F# @  ]' A& n* @
  29. *)&IIRStateF32[0]);- r5 L: A0 m) v. W3 l/ o4 q
  30. /* IIR滤波 */" k1 N! _$ |! F) T, o1 E. w2 J( l+ ~
  31.         arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, TEST_LENGTH_SAMPLES);
    . p# m2 t3 t7 Q
  32. /*放缩系数 */$ R6 d; W8 e  c7 d7 x" X) K
  33. ScaleValue = 0.052219514664161221f * 0.04279801741658381f
    ! V8 {; J( ]+ G6 C* C7 s! B' k, b
  34. /* 打印滤波后结果 */
    . I2 E0 Q$ }% R, ~0 C6 i* n- j) ]) D
  35. for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    8 x' k+ n- e# L' t  Y: z4 s
  36. {' A# X4 \! R8 ~; A4 M  _
  37. printf("%f\r\n", testOutput[i]*ScaleValue);
    % V1 H8 I1 X  `- B9 p5 q
  38. }4 Y' @- M7 k$ n0 L2 F
  39. }
复制代码
运行如上函数可以通过串口打印出函数arm_biquad_cascade_df1_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。
    对比前需要先将串口打印出的一组数据加载到Matlab中, arm_biquad_cascade_df1_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
  1. fs=1000;              %设置采样频率 1K: {, V6 j- J( T! Q  V
  2. N=400;               %采样点数      - N- O6 q/ ^- T
  3. n=0:N-1;5 n6 u$ E8 W3 i4 i
  4. t=n/fs;                %时间序列
    ( `! g4 s1 j  @7 m
  5. f=n*fs/N;              %频率序列3 g( v* v# W1 [) H% C; ?* ~  s

  6. " _% {5 f5 u- a- L( I; Q
  7. x1=sin(2*pi*50*t);3 C- C! p, Y, S4 z* f
  8. x2=sin(2*pi*200*t);     %50Hz和200Hz正弦波
    , @/ ]0 S3 n$ f" J# j2 V/ B
  9. subplot(211);  Z, p) w0 G6 {
  10. plot(t, x1);
    : }$ W4 {+ {: L5 }5 R# A) R) }
  11. title('滤波后的理想波形');
    $ L' \% v( C' a5 ?: t& I/ l
  12. grid on;) h- R5 s/ W. T) D8 F

  13. 7 J; l& [/ B/ D5 M! Z
  14. subplot(212);
    $ a8 E( o, I6 X  b
  15. plot(t, sampledata);
    $ [+ u. ?. f& ?' G9 C* ]6 b# C4 Z$ g
  16. title('ARM官方库滤波后的波形');
    1 d& v0 W/ E! l* b
  17. grid on;
复制代码
Matlab计算结果如下:
40.12.png
从上面的波形对比来看,matlab和函数arm_biquad_cascade_df1_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
  1. fs=1000;                %设置采样频率 1K% v9 m1 D& _* c. y9 _# V5 i: c
  2. N=400;                 %采样点数      
    % V0 p' v# T$ x% e# X- W* A4 ~
  3. n=0:N-1;  ?( i- w' ^. f4 z
  4. t=n/fs;                  %时间序列, a$ g& g  D  W
  5. f=n*fs/N;                %频率序列4 F/ v# h. b6 n* w! q2 l

  6. 0 {5 m3 [- c3 V5 F5 p2 ?* ^  J
  7. x = sin(2*pi*50*t) + sin(2*pi*200*t);      %50Hz和200Hz正弦波合成5 D7 D8 ?, L8 S
  8.   
    & B0 v9 l2 X8 v/ ]
  9. subplot(211);# z" o, b# n' z2 q" d. F
  10. y=fft(x, N);                %对信号x做FFT   $ z; H; v7 T- g" b6 J3 v- b
  11. plot(f,abs(y));
    ' {' B6 @$ K6 z) z4 n
  12. xlabel('频率/Hz');$ |. {7 E4 W6 F. Z' `4 t
  13. ylabel('振幅');  U/ c9 i. Q! R% Z3 D; S9 q& B
  14. title('原始信号FFT');
    6 L* K  p6 n5 w" W2 j
  15. grid on;
    ! R6 `: j/ a) ^3 {( \4 M

  16. ; B& M+ m, F1 N; p- }1 Z5 o
  17. y3=fft(sampledata, N);    %经过IIR滤波器后得到的信号做FFT% G2 o( Z, C& Y2 h$ t$ s
  18. subplot(212);                              
    . o, ^4 I$ y. _
  19. plot(f,abs(y3));
    ( E5 ^' {% g4 z9 v  B5 a& G: @0 L! n
  20. xlabel('频率/Hz');
    . H/ ~' C* a) U( r; n% H3 E
  21. ylabel('振幅');
    + v: h4 m, j9 B, P
  22. title('IIR滤波后信号FFT');
    0 T: t9 c4 m) Q, m( q* J
  23. grid on;
复制代码
Matlab计算结果如下:
40.13.png
上面波形变换前的FFT和变换后FFT可以看出,200Hz的正弦波基本被滤除。

" `  w6 \9 O; l( h- [/ l6 R+ G
baiyongbin2009 回答时间:2015-4-28 10:27:34
40.4 IIR高通滤波器设计
1 V- b  z- I" F  O% C2 H  T8 C8 Y
40.4.1 fdatool获取高通滤波器系数
    设计一个如下的例子:
    信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个巴特沃斯滤波器高通滤波器,采用直接I型,截止频率140Hz,采样400个数据,滤波器阶数设置为4。fadtool的配置如下:
40.14.png
配置好高通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。

/ y3 r9 ]; [- `5 j* w' \6 j: n
40.4.2 高通滤波器实现
    通过工具箱fdatool获得高通滤波器系数后在开发板上运行函数arm_biquad_cascade_df1_f32来测试高通滤波器的效果。
  1. #define numStages  2                /* 2阶IIR滤波的个数 */
    * j- a; A2 Y  b( s5 H
  2. #define TEST_LENGTH_SAMPLES  400    /* 采样点数 */* Y! J" g9 |9 H9 l8 A6 v# k, `
  3. ) d; Q9 [. J2 R# F: K1 D$ [+ g& T
  4. static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
    , X. h$ b2 _% l5 r& O
  5. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
    : y; U! e4 o0 G" S
  6. static float32_t IIRStateF32[4*numStages];                      /* 状态缓存,大小numTaps + blockSize - 1*/7 O+ F4 F4 d- d8 w$ p2 c# M; J' c
  7.                                                                              ! `8 \% a( G2 ~4 m% x( `, h7 Y
  8. /* 巴特沃斯高通滤波器系数 140Hz */                                                                                                                                         ! Q( v: k+ ]! y8 y4 C( P
  9. const float32_t IIRCoeffs32HP[5*numStages] = {# l# l/ B& z4 j
  10. 1.0f,  -2.0f,  1.0f,  0.9845430147411518f,   -0.54456536085081642f,      
    : E3 K! n; g, I8 `% O% G( E$ Z- z
  11. 1.0f,  -2.0f,  1.0f,  0.74471447786432121f,  -0.16831887384397309f,                                $ @/ M: H, x" p, L& A3 T' ~
  12. };& w6 J! J+ Y" g. ^& {# A

  13. 4 H  N8 ^, `6 S2 E4 p( s
  14. /*/ A; G6 I, V4 ~7 U( ~8 {" ~
  15. *********************************************************************************************************# @. L7 @: k- }, d6 i
  16. *        函 数 名: arm_iir_f32_hp: b, v1 {) H' D0 g6 g( v
  17. *        功能说明: 调用函数arm_iir_f32_hp实现高通滤波器( w- H' X7 B8 A, I6 s; ~
  18. *        形    参:无
      |; x( ^  g- e, f# C* R# k
  19. *        返 回 值: 无) q( N4 J. R; p0 z3 k
  20. *********************************************************************************************************+ n$ m& B, P$ p
  21. */* ~+ W* e7 A9 L5 U" T/ k* X' T
  22. static void arm_iir_f32_hp(void)
    ) D. h+ j; \- ?5 Q
  23. {: t) f4 o$ ~- Q+ w9 K
  24. uint32_t i;" i) _3 v" N7 k; N; {" z! Q( R
  25. arm_biquad_casd_df1_inst_f32 S;
    7 M+ h8 Q" y( o
  26. float32_t ScaleValue;! T7 S6 O  p3 C4 T3 i  Z  {% p, i
  27. 7 [; K+ R6 @$ ~" }
  28. /* 初始化 */5 a# {5 a2 Y; E9 H4 k3 e
  29. arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32HP[0], (float32_t
    , y9 I7 k+ ?$ _0 [/ z1 N: ]5 t
  30. *)&IIRStateF32[0]);& k! I- D: H6 m4 V) h! a" }
  31. /* IIR滤波 */
    : N$ W. Z' t4 o4 ^  k- R5 A  k
  32.         arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, TEST_LENGTH_SAMPLES);
    ) B- S4 ]5 p9 k) b
  33.    
    6 s5 N3 V  N5 a& J& K  i; f' e
  34. /*放缩系数 */    ! _" ?7 Y! u& O, i  k3 W5 |
  35. ScaleValue = 0.63227709389799203f * 0.47825833792707356f;  ! S7 C; m' x* Q& |. p- w; t
  36. /* 打印滤波后结果 */0 v$ A# [/ d% \0 [4 y7 \1 _2 U
  37. for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    . R3 [. S7 }5 l0 s0 _+ ?# I
  38. {1 M7 }4 e* B7 o% v8 E4 w
  39. printf("%f\r\n", testOutput[i]*ScaleValue);$ H9 r8 @  n: M$ }  ^) X
  40. }
    7 K7 S! h' l' e5 g0 ?# d. A
  41. }
复制代码
运行如上函数可以通过串口打印出函数arm_biquad_cascade_df1_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。
    对比前需要先将串口打印出的一组数据加载到Matlab中, arm_biquad_cascade_df1_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
  1. fs=1000;              %设置采样频率 1K# K- q/ O" ~# [5 y4 t( v5 _
  2. N=400;               %采样点数      
      K+ Z. r: D" [( u4 l
  3. n=0:N-1;) ^$ {, g) X+ ^: m7 P
  4. t=n/fs;                %时间序列0 Q( U% B  V0 E/ K
  5. f=n*fs/N;              %频率序列2 N7 e: c3 W& T4 m3 }! O

  6. ) T3 }# l+ a% t6 D' `* m
  7. x1=sin(2*pi*50*t);9 i7 h% z3 S: J9 y  k2 l
  8. x2=sin(2*pi*200*t);     %50Hz和200Hz正弦波
    , F- l  L) ^9 ]3 e
  9. subplot(211);9 A7 A  L" e0 r* K, U
  10. plot(t, x2);9 [; Y. W8 v2 m' p) A9 i
  11. title('滤波后的理想波形');  {4 U9 _7 I- ?# B
  12. grid on;
    + x3 J' z" a6 d9 [7 w$ d" W9 Y, v
  13. 7 J  g( s4 ]0 z. h& W5 _6 K
  14. subplot(212);
    & w: O4 \0 H& i# W% @0 C
  15. plot(t, sampledata);" N2 P3 x- K3 f
  16. title('ARM官方库滤波后的波形');& h. D8 t7 L! a4 ^' U
  17. grid on;
复制代码
Matlab计算结果如下:
40.15.png
从上面的波形对比来看,matlab和函数arm_biquad_cascade_df1_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
  1. fs=1000;                %设置采样频率 1K
    # U4 X' F5 F7 Z3 z
  2. N=400;                 %采样点数      % r' A* L9 p6 H2 T# Q
  3. n=0:N-1;
    1 B/ \+ {' k6 s2 t! F
  4. t=n/fs;                  %时间序列4 }( \( c4 J6 ?
  5. f=n*fs/N;                %频率序列
    3 |0 a- q6 k' Q

  6. ( \/ K7 z6 `6 ]' T/ p
  7. x = sin(2*pi*50*t) + sin(2*pi*200*t);      %50Hz和200Hz正弦波合成, [# [2 N3 ^  D7 I4 N% I" V* E
  8.   3 D3 V5 ~8 a- `4 X: F+ |
  9. subplot(211);2 j+ m" J# F" i9 \/ @
  10. y=fft(x, N);                %对信号x做FFT   / w0 p7 Z" a+ f; y; N9 x
  11. plot(f,abs(y));* I4 D: Z8 K3 `6 l. T2 _
  12. xlabel('频率/Hz');* r' }/ j$ K( f7 \4 n5 b
  13. ylabel('振幅');
    ! K0 N2 _0 q7 L& L* W7 l
  14. title('原始信号FFT');
    - Z3 _* Q+ w' |( I" f# \# ^5 o1 U
  15. grid on;" p3 @3 v: G# K- u$ m5 l6 Y5 b
  16. 3 b) U$ h$ ^5 _/ z: t- g; j+ n) h$ P
  17. y3=fft(sampledata, N);    %经过IIR滤波器后得到的信号做FFT
    ) P+ M5 m, w- A8 F0 ]
  18. subplot(212);                              
    6 r- X! v# [# M$ ?; t) ^0 q
  19. plot(f,abs(y3));; X* @0 ^$ \. S2 B& m
  20. xlabel('频率/Hz');6 I1 E( Y! ]. t- P$ @2 P9 e
  21. ylabel('振幅');9 ~' T# F: E- G1 z9 q
  22. title('IIR滤波后信号FFT');7 V1 W/ x& q0 w) _
  23. grid on;
复制代码
Matlab计算结果如下:
40.16.png
上面波形变换前的FFT和变换后FFT可以看出,50Hz的正弦波基本被滤除。
( Z7 A) P: L% f$ k9 u
baiyongbin2009 回答时间:2015-4-28 10:32:14
40.5 IIR带通滤波器设计3 B! |( s$ z9 q5 m
40.5.1 fdatool获取低通滤波器系数
    设计一个如下的例子:
    信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个巴特沃斯滤波器带通滤波器,采用直接I型,截止频率140Hz和,采样400个数据,滤波器阶数设置为4。fadtool的配置如下:
40.17.png
配置好带通滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。
6 a# R& [. |% P' }% Q( d
40.5.2 带通滤波器实现
    通过工具箱fdatool获得带通滤波器系数后在开发板上运行函数arm_biquad_cascade_df1_f32来测试带通滤波器的效果。
  1. #define numStages  2                /* 2阶IIR滤波的个数 */
      r+ g' Z9 K( C8 F1 u% `
  2. #define TEST_LENGTH_SAMPLES  400    /* 采样点数 */
    4 T8 ^' D9 {, P& y6 Q' x" I

  3. ( ~& z& f5 X* e, I' ^9 _& @
  4. static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
    ) q: L4 a/ g: e
  5. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */8 T8 v# T, Q6 }3 G, Z' s
  6. static float32_t IIRStateF32[4*numStages];                      /* 状态缓存,大小numTaps + blockSize - 1*/3 k* t# l  Y8 D* K% @% ]
  7.                                                                              
    7 J& Q. G  l5 j
  8. /* 巴特沃斯带通滤波器系数140Hz 400Hz*/                                                                                                                                           x! s/ W4 W8 k# A# B; D
  9. const float32_t IIRCoeffs32BP[5*numStages] = {
    " Q* P0 y& P( S3 ^5 h+ J3 g
  10. 1.0f,  0.0f,  -1.0f,    -1.1276518720541668f,   -0.47001314508753411f,      : o0 Q6 e3 J: C6 E$ L' P
  11. 1.0f,  0.0f,  -1.0f,    0.77495305804604886f,  -0.36707750055668387f                              
    " M$ l0 |3 d4 |; e/ L# t
  12. };
    6 [: h" ^* B) f2 l- t5 y
  13. ( {' v; U) o6 X& s% V3 ]0 B
  14. /** `9 X- U2 q% M8 z+ `: x
  15. *********************************************************************************************************5 h  v9 q  [; V; j
  16. *        函 数 名: arm_iir_f32_bp0 Y  x5 ~4 |7 W# N9 W
  17. *        功能说明: 调用函数arm_iir_f32_hp实现带通滤波器
    + Y% u2 t2 ]2 I( ]3 [0 h
  18. *        形    参:无
    ' _# Z/ `7 Z$ Z; U) q, ~1 N
  19. *        返 回 值: 无
    0 n% t* U# t+ f9 `& f& D% {' K
  20. *********************************************************************************************************
    6 R3 k; d3 e, A) F. N
  21. */
    4 @4 A7 g5 X: M) }  }
  22. static void arm_iir_f32_bp(void)
    $ w9 R: o7 b3 ]( ^5 k
  23. {
    ! C/ P+ [0 T0 a3 v
  24. uint32_t i;0 }( y. X, b* ?4 R8 H* F
  25. arm_biquad_casd_df1_inst_f32 S;8 E. L2 T3 h1 d# l
  26. float32_t ScaleValue;5 w4 n) q$ _7 @% Y) m

  27. 1 b( {. e" D5 H( N, H+ {8 v
  28. /* 初始化 */# l+ E' K* N! A7 G' k$ H
  29. arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32BP[0], (float32_t
    ) w% Z$ e4 _& Q1 s7 U
  30. *)&IIRStateF32[0]);
    9 A) b8 K% ]$ K4 N2 E2 H0 W$ n
  31. /* IIR滤波 */; X, ~3 `( _* ~+ o) \
  32.         arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, TEST_LENGTH_SAMPLES);$ a/ {+ f2 ]5 e" M- G) ?
  33.     3 E7 ~6 [6 E3 Z6 u
  34. /*放缩系数 */   
    1 }, N* P: c3 r. z" R2 I8 Z, h+ i. d
  35. ScaleValue = 0.55815658576077365f * 0.55815658576077365f;  
    : g( `& |3 `. O
  36. /* 打印滤波后结果 */
    ( q5 K+ G- i7 R% ?
  37. for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    / ?" w0 Y( D$ e$ x; N( D
  38. {
    9 P* B% X0 I5 J, ~. {! S6 |
  39. printf("%f\r\n", testOutput[i]*ScaleValue);
    9 a, }* R, u; T5 @+ V: x6 l# p
  40. }" B; a0 b" j8 y( R& l) V
  41. }
复制代码
运行如上函数可以通过串口打印出函数arm_biquad_cascade_df1_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。
    对比前需要先将串口打印出的一组数据加载到Matlab中, arm_biquad_cascade_df1_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
  1. fs=1000;              %设置采样频率 1K
    " n' e7 W% G/ U8 S3 H/ b
  2. N=400;               %采样点数      ) Y3 g7 r3 |6 E8 l
  3. n=0:N-1;, W2 e# o" y* t+ z4 A3 }
  4. t=n/fs;                %时间序列  B: m' e' x4 `2 @/ }
  5. f=n*fs/N;              %频率序列/ L1 n' Y2 ?' e; e

  6. + F' o& Z" x' p. Y
  7. x1=sin(2*pi*50*t);: O' L6 a" N5 p# z0 h
  8. x2=sin(2*pi*200*t);     %50Hz和200Hz正弦波- C) L1 ~( ^$ @% [" _& W% u
  9. subplot(211);( ?) g6 f: q( E6 Y  i( Z
  10. plot(t, x1);4 V  p2 D) Y/ W/ O
  11. title('滤波后的理想波形');
    ; m+ D  p7 Y) j0 D: w
  12. grid on;
    6 }/ T: c! r1 U

  13. ; h. ]0 F# e8 A$ t7 T3 q$ ~
  14. subplot(212);- m/ E9 l  ^1 G, P  D- M. E
  15. plot(t, sampledata);
    6 M5 A- Z5 W/ i7 C6 O# p4 {& I3 ]3 d
  16. title('ARM官方库滤波后的波形');
    $ `, Z! [+ E5 q
  17. grid on;
复制代码
Matlab计算结果如下:
40.18.png
从上面的波形对比来看,matlab和函数arm_biquad_cascade_df1_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
  1. fs=1000;                %设置采样频率 1K
    1 z6 R. F1 e0 n5 P
  2. N=400;                 %采样点数      ( m) w* C& t' u9 Y/ D, t  ?
  3. n=0:N-1;
    . [- Y0 o7 S8 s% t
  4. t=n/fs;                  %时间序列
    / |+ M6 U$ T0 V9 \* @- G
  5. f=n*fs/N;                %频率序列
    , @% l, l9 H" C, I3 h, U

  6. 2 S1 ]$ e4 }8 l% b# R7 q
  7. x = sin(2*pi*50*t) + sin(2*pi*200*t);      %50Hz和200Hz正弦波合成+ T# ?( V4 `( U8 t; c& k' @3 s
  8.   6 n) e8 H5 r( X9 C5 z
  9. subplot(211);9 H1 p& V6 F& Q  i' b  R4 }
  10. y=fft(x, N);                %对信号x做FFT   - e7 u& T6 b% K- Z9 ?
  11. plot(f,abs(y));" m3 h; Q) V8 i" M% Z5 S' @
  12. xlabel('频率/Hz');
    * z% B/ W  n- W0 y- j) a
  13. ylabel('振幅');# ?0 h- d) Z$ V/ |, j
  14. title('原始信号FFT');# J- m* f2 L) y# {: w
  15. grid on;
    $ ^) h% h8 T! q4 G  ^/ D6 z
  16. 5 ^+ v' j7 d1 f$ F
  17. y3=fft(sampledata, N);    %经过IIR滤波器后得到的信号做FFT7 ]8 I$ |1 `: C
  18. subplot(212);                               / N. _0 V" l" S/ ]
  19. plot(f,abs(y3));
    6 Y9 H. w7 V+ P9 L
  20. xlabel('频率/Hz');
    : b2 O7 p5 O& z
  21. ylabel('振幅');
    ' x$ U7 ?1 i- k) }8 K
  22. title('IIR滤波后信号FFT');
    7 B1 I( j" [2 W& ]
  23. grid on;
复制代码
Matlab计算结果如下:
40.19.png
上面波形变换前的FFT和变换后FFT可以看出,50Hz的正弦波基本被滤除。
; h# E& p, Y4 O6 n! m- ~7 s
wamcncn 回答时间:2015-4-28 11:14:32
标记学习
baiyongbin2009 回答时间:2015-4-28 12:45:41
40.6 IIR带阻滤波器设计
- q& }9 t7 m  ^. C# P8 v9 u" T8 c& W
40.6.1 fdatool获取带阻滤波器系数
    设计一个如下的例子:
    信号由50Hz正弦波和200Hz正弦波组成,采样率1Kbps,现设计一个巴特沃斯滤波器带阻滤波器,采用直接I型,截止频率100Hz和325Hz,采样400个数据,滤波器阶数设置为4。fadtool的配置如下:
40.20.png
配置好带阻滤波器后,具体滤波器系数的生成大家参考本章第二小节的方法即可。
: m& V$ ~5 C0 D+ N, z, L
40.6.2 带阻滤波器实现
    通过工具箱fdatool获得带阻滤波器系数后在开发板上运行函数arm_biquad_cascade_df1_f32来测试带阻滤波器的效果。
  1. #define numStages  2                /* 2阶IIR滤波的个数 */
    , X: Q" ^0 e6 ?$ v( Q1 k+ A* Y
  2. #define TEST_LENGTH_SAMPLES  400    /* 采样点数 */8 C4 i( n$ S4 x! a: h# b; P+ q' F
  3. - }: ~7 F) s0 W; K* V/ U
  4. static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */& X; F: c- |, O) ^7 G
  5. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
    ; {& Y6 C5 H. V% V* P" [  k1 B+ h
  6. static float32_t IIRStateF32[4*numStages];                      /* 状态缓存,大小numTaps + blockSize - 1*/
    0 [& q9 v9 o6 ^$ _8 W4 A
  7.                                                                              # d7 p$ K# N' m, v- q: Y
  8. /* 巴特沃斯带阻滤波器系数100Hz 325Hz*/                                                                                                                                         ! I. D1 d/ \" w# T4 W& C7 U9 H8 f
  9. const float32_t IIRCoeffs32BS[5*numStages] = {
    2 [& ~" }- p* S6 O! N5 {
  10. 1.0f,  -0.61400192638335005f,  1.0f,  1.1451427879497746f,   -0.50298007146721391f,, I) m' `3 M, \- }% `* e
  11. 1.0f,  -0.61400192638335005f,  1.0f,  -0.47458704658841883f, -0.35305199748708849f                        
    & _7 ?+ R; G, ~/ i8 [
  12. };( X: E# G: C3 M/ K' v

  13. ) Z4 I+ l" B- x: K6 F) Z# j. d
  14. /*
    : f) Z, E" y' n' l4 x
  15. *********************************************************************************************************  A3 C) M6 \; [+ }
  16. *        函 数 名: arm_iir_f32_bs( m3 M, X( X. \$ n, H# C2 q: T
  17. *        功能说明: 调用函数arm_iir_f32_bs实现带阻滤波器
    # b: m1 ~% W9 }  @$ @/ a
  18. *        形    参:无
    5 O5 ^3 C' E( Z3 n: a* ^' \
  19. *        返 回 值: 无
    , }# ^$ X# Y7 }  \9 y  D2 X
  20. *********************************************************************************************************! C4 k9 G$ t8 B
  21. */. k& z9 Q) F# Z/ y: H/ P
  22. static void arm_iir_f32_bs(void)
    / p8 Y/ s7 R$ \" y' Q. _
  23. {
    * c; [4 N/ B4 f( v
  24. uint32_t i;
    $ f8 O- k1 _8 E& ~* Q
  25. arm_biquad_casd_df1_inst_f32 S;$ P3 t4 j" ?/ c5 c
  26. float32_t ScaleValue;- i  x) v/ u* \

  27. . Q5 h! ?& q' W
  28. /* 初始化 */7 V" ]4 C/ A& ~9 {7 a* D, B
  29. arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32BS[0], (float32_t: I7 R0 I2 l  \
  30. *)&IIRStateF32[0]);
    ; m5 Q$ s# o; b* @
  31. /* IIR滤波 */7 {  y! \' o2 J: {/ n  l. ?  {, ~
  32.         arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, TEST_LENGTH_SAMPLES);
    ; Y6 R" q/ `; \6 N( K9 I
  33.     ! w* a) L) c8 D% \. P3 t- p
  34. /*放缩系数 */   
    ' Z' J2 A0 }8 `4 h: t) r3 ^: r6 j
  35. ScaleValue = 0.58347920314378698f * 0.58347920314378698f;  : Z) P/ O9 S% H/ t2 c7 {' t
  36. /* 打印滤波后结果 */
    ! d( G& \/ X  e8 u" F( I5 O0 D
  37. for(i=0; i<TEST_LENGTH_SAMPLES; i++)' V4 {1 H' Y" O
  38. {, d3 `$ ~& e2 g3 u( E; }
  39. printf("%f\r\n", testOutput[i]*ScaleValue);7 }5 B6 H' w! V0 {; F( {6 E; n
  40. }
    ( \6 G6 k7 i( t' F% [
  41. }
复制代码
运行如上函数可以通过串口打印出函数arm_biquad_cascade_df1_f32滤波后的波形数据,下面通过Matlab绘制波形来对比Matlab计算的结果和ARM官方库计算的结果。
    对比前需要先将串口打印出的一组数据加载到Matlab中, arm_biquad_cascade_df1_f32的计算结果起名sampledata,加载方法在前面的教程中已经讲解过,这里不做赘述了。Matlab中运行的代码如下:
  1. fs=1000;              %设置采样频率 1K
    9 v- P* s& F! a$ e
  2. N=400;               %采样点数      9 v0 F9 Z! {& c1 S$ R( g* Q
  3. n=0:N-1;$ m3 K) O5 Z! j! l# K5 g
  4. t=n/fs;                %时间序列
    8 Z# J1 b6 x5 V& \: `( V- F  i& I
  5. f=n*fs/N;              %频率序列
    5 h. ?. [$ Q: ^; u8 s" U" }

  6. % {1 L; ]( x: f0 o* B& ~* W
  7. x1=sin(2*pi*50*t);
    3 x! B* n# b# y' \
  8. x2=sin(2*pi*200*t);     %50Hz和200Hz正弦波: Y( A* X; P0 j# ~. a: x
  9. subplot(211);. l' Q% G* z. b7 o1 _6 s% E9 f  C
  10. plot(t, x1);/ Q- L/ }" q4 G1 f
  11. title('滤波后的理想波形');
      _* M4 r! b8 M1 ^
  12. grid on;6 w) s5 X/ C+ H! J2 {+ P

  13.   `5 d. A' z' j# K
  14. subplot(212);
    6 @6 B# ~9 ]0 e4 @: D' J/ E% V
  15. plot(t, sampledata);& W- i& c' [3 T; M3 r
  16. title('ARM官方库滤波后的波形');
    1 v* o; I' Y9 c1 r
  17. grid on;
复制代码
Matlab计算结果如下:
40.21.png
从上面的波形对比来看,matlab和函数arm_biquad_cascade_df1_f32计算的结果基本是一致的。为了更好的说明滤波效果,下面从频域的角度来说明这个问题,Matlab上面运行如下代码:
  1. fs=1000;                %设置采样频率 1K, J4 O8 A- G7 p+ k, |+ H5 P4 z! S9 p
  2. N=400;                 %采样点数      
    " ?% j: U7 P( Q# ~; |; i& u
  3. n=0:N-1;
    5 P  V5 x6 S% z# E- }9 d: ^$ M1 s
  4. t=n/fs;                  %时间序列
    : ~0 J6 @& k( z0 L& j# w: c) Y
  5. f=n*fs/N;                %频率序列6 s8 `$ e5 I6 K! V+ W7 e
  6. - k, `$ w& _  E; e
  7. x = sin(2*pi*50*t) + sin(2*pi*200*t);      %50Hz和200Hz正弦波合成
    3 a8 o- u2 o" I& e
  8.   ) V( |2 Q$ l! H$ ?4 I; `% s
  9. subplot(211);
    " M- o8 r, O5 V1 T5 `" V8 ]
  10. y=fft(x, N);                %对信号x做FFT   
    6 {! W3 r, N+ @4 `; u
  11. plot(f,abs(y));4 x5 ], s' Z+ Z' H" R
  12. xlabel('频率/Hz');
    * X5 ?; ~6 I& e" c. W; k
  13. ylabel('振幅');
    2 [0 u( A) k. F/ {8 b# v8 d9 z
  14. title('原始信号FFT');
    5 V7 k; Y8 t1 S
  15. grid on;
    # D0 w7 i: e1 S

  16. 9 k/ }) \8 k/ K8 j+ ~2 G
  17. y3=fft(sampledata, N);    %经过IIR滤波器后得到的信号做FFT
    ) O. g. ~2 m; N/ h. D
  18. subplot(212);                               4 \6 k" M! ~1 z$ l
  19. plot(f,abs(y3));1 i3 A% ?1 o1 ^8 C. k* ^) `& s. M: z! c
  20. xlabel('频率/Hz');( w' h  h  b5 ]# n6 a1 l
  21. ylabel('振幅');
    6 V# _; v5 V2 p/ ~# v5 G
  22. title('IIR滤波后信号FFT');
    " Z1 _$ ?) E9 }$ p2 P" h3 m) M
  23. grid on;
复制代码
Matlab计算结果如下:
40.22.png
上面波形变换前的FFT和变换后FFT可以看出,200Hz的正弦波基本被滤除。
$ f+ o, J# P- A5 G1 A( B  c
baiyongbin2009 回答时间:2015-4-28 12:46:42
40.7 总结
    本章节主要讲解了巴特沃斯低通,高通,带通和带阻滤波器的实现,有兴趣的可以使用同样的方法实现切比雪夫滤波器的设计。
0 l, }! L: J3 y1 U* }& {
XDLH 回答时间:2015-11-15 13:40:28
不错挺好的!受教了!
zhh 回答时间:2020-12-1 15:57:50
输入信号是连续的,每调用一次arm_biquad_cascade_df1_f32函数,开始几个点都会有畸变,如何做到输出信号连续无畸变呢?

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版