精华内容
下载资源
问答
  • IIR滤波器

    千次阅读 2019-09-28 10:14:02
    IIR滤波器的单位冲击响应是无限的。 N表示滤波器的级数 N=1时 y为输出数据,x为输入数据,a.b为滤波器系数。 x[n]为本次滤波的输入数据,x[n-1]为上一次滤波前的输入数据,y[n-1]为上一次滤波器输出的数据 ...

    1、

    IIR滤波器的单位冲击响应是无限的。

    N表示滤波器的级数

    N=1时

    y为输出数据,x为输入数据,a.b为滤波器系数。

    x[n]为本次滤波的输入数据,x[n-1]为上一次滤波前的输入数据,y[n-1]为上一次滤波器输出的数据

     

    设计一个采样率1000,截至频率100,滤波类型Butterworth,阶数为1阶的IIR低通

    B[0]=+1

    B[1]=-1

    A[1]=-0.59

    代入公式得:y[n]=x[n]+x[n-1]+0.59*y[n-1]

    数字低通滤波器分为以下两种FIR  IIR

    1、IIR是无限脉冲响应滤波器,特点输出与无限久以前的输入有关

    2、FIR是有限脉冲响应滤波器,特点是输出与有限久以前的输入有关

     

     

     

    展开全文
  • IIR 滤波器

    千次阅读 2018-04-16 21:04:00
    IIR 滤波器的实现(C++) 原创 2014年08月26日 16:46:32 <ul class="article_tags clearfix...


    IIR 滤波器的实现(C++)





    原创

    2014年08月26日 16:46:32

            <ul class="article_tags clearfix csdn-tracking-statistics tracking-click" data-mod="popu_377" style="display: none;">
                <li class="tit">标签:</li>
    







    IIR 滤波器的实现(C++

    最近在写的一个程序需要用到IIR滤波器,而且IIR滤波器的系数需要动态调整。因此就花了点时间研究IIR 滤波器的实现。

    以前用到的IIR滤波器的参数都是事先确定好的,有个网站,只要把滤波器的参数特性输进去,直接就能生成需要的C代码。

    http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html

    一直都偷懒直接用这个网站的结果,所以手上也没积累什么有用的代码。这次就需要自己从头做起。

    我面临的问题有两个:

    1. 根据滤波器的参数(滤波器的类型、截止频率、滤波器的阶数等),计算出滤波器对应的差分方程的系数。

    2. 利用得到的差分方程的系数构造一个可以工作的滤波器。

    其中第一个问题,对于不同类型的滤波器,比如Butterworth型、Bessel型等,滤波器系数的计算方法都不同。这部分工作我还没做完全,等我把常见的几种滤波器类型的系数计算方法都实现后再来写一篇文章。

    这里就先写写第二个问题。IIR 滤波器对应的差分方程为:


    相应的系统函数为:

    这里默认a[0] = 1。实际上,总可以通过调整a[k] 与 b[k] 的值使得a[0] = 1,所以这个条件时总能满足的。

    按照奥本海默写的《离散时间信号处理》上面的介绍,IIR 滤波器有两种基本的实现形式,分别成为直接I型和直接II型。我分别写了两个类,实现这两种形式。

    直接I

    1. class IIR_I  
    2. {  
    3. private:  
    4.     double *m_pNum;  
    5.     double *m_pDen;  
    6.     double *m_px;  
    7.     double *m_py;  
    8.     int m_num_order;  
    9.     int m_den_order;  
    10. public:  
    11.     IIR_I();  
    12.     void reset();  
    13.     void setPara(double num[], int num_order, double den[], int den_order);  
    14.     void resp(double data_in[], int m, double data_out[], int n);  
    15.     double filter(double data);  
    16.     void filter(double data[], int len);  
    17.     void filter(double data_in[], double data_out[], int len);  
    18. };  
    class IIR_I
    {
    private:
        double *m_pNum;
        double *m_pDen;
        double *m_px;
        double *m_py;
        int m_num_order;
        int m_den_order;
    public:
        IIR_I();
        void reset();
        void setPara(double num[], int num_order, double den[], int den_order);
        void resp(double data_in[], int m, double data_out[], int n);
        double filter(double data);
        void filter(double data[], int len);
        void filter(double data_in[], double data_out[], int len);
    };
    

    其中 m_px 存放x[n-k] 的值(m_px[0]存放x[n-0]、 m_px[1] 存放x[n-1],以此类推),m_py存放y[n-k] 的值(m_py[0]存放y[n-0]、 m_py[1] 存放y[n-1],以此类推)。

    三个filter函数用来做实际的滤波操作。在这之前,需要用setPara函数初始化滤波器的系数。

    下面是实现代码:

    1. /** \brief 将滤波器的内部状态清零,滤波器的系数保留 
    2.  * \return 
    3.  */  
    4. void IIR_I::reset()  
    5. {  
    6.     for(int i = 0; i <= m_num_order; i++)  
    7.     {  
    8.         m_pNum[i] = 0.0;  
    9.     }  
    10.     for(int i = 0; i <= m_den_order; i++)  
    11.     {  
    12.         m_pDen[i] = 0.0;  
    13.     }  
    14. }  
    15. IIR_I::IIR_I()  
    16. {  
    17.     m_pNum = NULL;  
    18.     m_pDen = NULL;  
    19.     m_px = NULL;  
    20.     m_py = NULL;  
    21.     m_num_order = -1;  
    22.     m_den_order = -1;  
    23. };  
    24. /** \brief 
    25.  * 
    26.  * \param num 分子多项式的系数,升序排列,num[0] 为常数项 
    27.  * \param m 分子多项式的阶数 
    28.  * \param den 分母多项式的系数,升序排列,den[0] 为常数项 
    29.  * \param m 分母多项式的阶数 
    30.  * \return 
    31.  */  
    32. void IIR_I::setPara(double num[], int num_order, double den[], int den_order)  
    33. {  
    34.     delete[] m_pNum;  
    35.     delete[] m_pDen;  
    36.     delete[] m_px;  
    37.     delete[] m_py;  
    38.     m_pNum = new double[num_order + 1];  
    39.     m_pDen = new double[den_order + 1];  
    40.     m_num_order = num_order;  
    41.     m_den_order = den_order;  
    42.     m_px = new double[num_order + 1];  
    43.     m_py = new double[den_order + 1];  
    44.     for(int i = 0; i <= m_num_order; i++)  
    45.     {  
    46.         m_pNum[i] = num[i];  
    47.         m_px[i] = 0.0;  
    48.     }  
    49.     for(int i = 0; i <= m_den_order; i++)  
    50.     {  
    51.         m_pDen[i] = den[i];  
    52.         m_py[i] = 0.0;  
    53.     }  
    54. }  
    55.   
    56. /** \brief 滤波函数,采用直接I型结构 
    57.  * 
    58.  * \param data 传入输入数据 
    59.  * \return 滤波后的结果 
    60.  */  
    61. double IIR_I::filter(double data)  
    62. {  
    63.     m_py[0] = 0.0; // 存放滤波后的结果  
    64.     m_px[0] = data;  
    65.     for(int i = 0; i <= m_num_order; i++)  
    66.     {  
    67.         m_py[0] = m_py[0] + m_pNum[i] * m_px[i];  
    68.     }  
    69.     for(int i = 1; i <= m_den_order; i++)  
    70.     {  
    71.         m_py[0] = m_py[0] - m_pDen[i] * m_py[i];  
    72.     }  
    73.     for(int i = m_num_order; i >= 1; i–)  
    74.     {  
    75.         m_px[i] = m_px[i-1];  
    76.     }  
    77.     for(int i = m_den_order; i >= 1; i–)  
    78.     {  
    79.         m_py[i] = m_py[i-1];  
    80.     }  
    81.     return m_py[0];  
    82. }  
    83.   
    84.   
    85. /** \brief 滤波函数,采用直接I型结构 
    86.  * 
    87.  * \param data[] 传入输入数据,返回时给出滤波后的结果 
    88.  * \param len data[] 数组的长度 
    89.  * \return 
    90.  */  
    91. void IIR_I::filter(double data[], int len)  
    92. {  
    93.     int i, k;  
    94.     for(k = 0; k < len; k++)  
    95.     {  
    96.         m_px[0] = data[k];  
    97.         data[k] = 0.0;  
    98.         for(i = 0; i <= m_num_order; i++)  
    99.         {  
    100.             data[k] = data[k] + m_pNum[i] * m_px[i];  
    101.         }  
    102.         for(i = 1; i <= m_den_order; i++)  
    103.         {  
    104.             data[k] = data[k] - m_pDen[i] * m_py[i];  
    105.         }  
    106.         // we get the y value now  
    107.         m_py[0] = data[k];  
    108.         for(i = m_num_order; i >= 1; i–)  
    109.         {  
    110.             m_px[i] = m_px[i-1];  
    111.         }  
    112.         for(i = m_den_order; i >= 1; i–)  
    113.         {  
    114.             m_py[i] = m_py[i-1];  
    115.         }  
    116.     }  
    117. }  
    118. /** \brief 滤波函数,采用直接I型结构 
    119.  * 
    120.  * \param data_in[] 输入数据 
    121.  * \param data_out[] 保存滤波后的数据 
    122.  * \param len 数组的长度 
    123.  * \return 
    124.  */  
    125. void IIR_I::filter(double data_in[], double data_out[], int len)  
    126. {  
    127.     int i, k;  
    128.     for(k = 0; k < len; k++)  
    129.     {  
    130.         m_px[0] = data_in[k];  
    131.         m_py[0] = 0.0;  
    132.         for(i = 0; i <= m_num_order; i++)  
    133.         {  
    134.             m_py[0] = m_py[0] + m_pNum[i] * m_px[i];  
    135.         }  
    136.         for(i = 1; i <= m_den_order; i++)  
    137.         {  
    138.             m_py[0] = m_py[0] - m_pDen[i] * m_py[i];  
    139.         }  
    140.         for(i = m_num_order; i >= 1; i–)  
    141.         {  
    142.             m_px[i] = m_px[i-1];  
    143.         }  
    144.         for(i = m_den_order; i >= 1; i–)  
    145.         {  
    146.             m_py[i] = m_py[i-1];  
    147.         }  
    148.         data_out[k] = m_py[0];  
    149.     }  
    150. }  
    /** \brief 将滤波器的内部状态清零,滤波器的系数保留
     * \return
     */
    void IIR_I::reset()
    {
        for(int i = 0; i <= m_num_order; i++)
        {
            m_pNum[i] = 0.0;
        }
        for(int i = 0; i <= m_den_order; i++)
        {
            m_pDen[i] = 0.0;
        }
    }
    IIR_I::IIR_I()
    {
        m_pNum = NULL;
        m_pDen = NULL;
        m_px = NULL;
        m_py = NULL;
        m_num_order = -1;
        m_den_order = -1;
    };
    /** \brief
     *
     * \param num 分子多项式的系数,升序排列,num[0] 为常数项
     * \param m 分子多项式的阶数
     * \param den 分母多项式的系数,升序排列,den[0] 为常数项
     * \param m 分母多项式的阶数
     * \return
     */
    void IIR_I::setPara(double num[], int num_order, double den[], int den_order)
    {
        delete[] m_pNum;
        delete[] m_pDen;
        delete[] m_px;
        delete[] m_py;
        m_pNum = new double[num_order + 1];
        m_pDen = new double[den_order + 1];
        m_num_order = num_order;
        m_den_order = den_order;
        m_px = new double[num_order + 1];
        m_py = new double[den_order + 1];
        for(int i = 0; i <= m_num_order; i++)
        {
            m_pNum[i] = num[i];
            m_px[i] = 0.0;
        }
        for(int i = 0; i <= m_den_order; i++)
        {
            m_pDen[i] = den[i];
            m_py[i] = 0.0;
        }
    }
    
    /** \brief 滤波函数,采用直接I型结构
     *
     * \param data 传入输入数据
     * \return 滤波后的结果
     */
    double IIR_I::filter(double data)
    {
        m_py[0] = 0.0; // 存放滤波后的结果
        m_px[0] = data;
        for(int i = 0; i <= m_num_order; i++)
        {
            m_py[0] = m_py[0] + m_pNum[i] * m_px[i];
        }
        for(int i = 1; i <= m_den_order; i++)
        {
            m_py[0] = m_py[0] - m_pDen[i] * m_py[i];
        }
        for(int i = m_num_order; i >= 1; i--)
        {
            m_px[i] = m_px[i-1];
        }
        for(int i = m_den_order; i >= 1; i--)
        {
            m_py[i] = m_py[i-1];
        }
        return m_py[0];
    }
    
    
    /** \brief 滤波函数,采用直接I型结构
     *
     * \param data[] 传入输入数据,返回时给出滤波后的结果
     * \param len data[] 数组的长度
     * \return
     */
    void IIR_I::filter(double data[], int len)
    {
        int i, k;
        for(k = 0; k < len; k++)
        {
            m_px[0] = data[k];
            data[k] = 0.0;
            for(i = 0; i <= m_num_order; i++)
            {
                data[k] = data[k] + m_pNum[i] * m_px[i];
            }
            for(i = 1; i <= m_den_order; i++)
            {
                data[k] = data[k] - m_pDen[i] * m_py[i];
            }
            // we get the y value now
            m_py[0] = data[k];
            for(i = m_num_order; i >= 1; i--)
            {
                m_px[i] = m_px[i-1];
            }
            for(i = m_den_order; i >= 1; i--)
            {
                m_py[i] = m_py[i-1];
            }
        }
    }
    /** \brief 滤波函数,采用直接I型结构
     *
     * \param data_in[] 输入数据
     * \param data_out[] 保存滤波后的数据
     * \param len 数组的长度
     * \return
     */
    void IIR_I::filter(double data_in[], double data_out[], int len)
    {
        int i, k;
        for(k = 0; k < len; k++)
        {
            m_px[0] = data_in[k];
            m_py[0] = 0.0;
            for(i = 0; i <= m_num_order; i++)
            {
                m_py[0] = m_py[0] + m_pNum[i] * m_px[i];
            }
            for(i = 1; i <= m_den_order; i++)
            {
                m_py[0] = m_py[0] - m_pDen[i] * m_py[i];
            }
            for(i = m_num_order; i >= 1; i--)
            {
                m_px[i] = m_px[i-1];
            }
            for(i = m_den_order; i >= 1; i--)
            {
                m_py[i] = m_py[i-1];
            }
            data_out[k] = m_py[0];
        }
    }

    除此之外,还提供了个resp函数,这个函数可以计算滤波器的时域响应。并且不要求data_indata_out 的数组长度相同。默认data_in[0] 之前的数据全为0data_in[M-1]之后的数字全部为data_in[M-1]。因此,用这个函数计算阶跃响应输入数据只需要提供一个数据点就行了。并且这个函数不改变滤波器的内部状态。


    1. /** \brief 计算 IIR 滤波器的时域响应,不影响滤波器的内部状态 
    2.  * \param data_in 为滤波器的输入,0 时刻之前的输入默认为 0,data_in[M] 及之后的输入默认为data_in[M-1] 
    3.  * \param data_out 滤波器的输出 
    4.  * \param M 输入数据的长度 
    5.  * \param N 输出数据的长度 
    6.  * \return 
    7.  */  
    8. void IIR_I::resp(double data_in[], int M, double data_out[], int N)  
    9. {  
    10.     int i, k, il;  
    11.     for(k = 0; k < N; k++)  
    12.     {  
    13.         data_out[k] = 0.0;  
    14.         for(i = 0; i <= m_num_order; i++)  
    15.         {  
    16.             if( k - i >= 0)  
    17.             {  
    18.                 il = ((k - i) < M) ? (k - i) : (M - 1);  
    19.                 data_out[k] = data_out[k] + m_pNum[i] * data_in[il];  
    20.             }  
    21.         }  
    22.         for(i = 1; i <= m_den_order; i++)  
    23.         {  
    24.             if( k - i >= 0)  
    25.             {  
    26.                 data_out[k] = data_out[k] - m_pDen[i] * data_out[k - i];  
    27.             }  
    28.         }  
    29.     }  
    30. }  
    /** \brief 计算 IIR 滤波器的时域响应,不影响滤波器的内部状态
     * \param data_in 为滤波器的输入,0 时刻之前的输入默认为 0,data_in[M] 及之后的输入默认为data_in[M-1]
     * \param data_out 滤波器的输出
     * \param M 输入数据的长度
     * \param N 输出数据的长度
     * \return
     */
    void IIR_I::resp(double data_in[], int M, double data_out[], int N)
    {
        int i, k, il;
        for(k = 0; k < N; k++)
        {
            data_out[k] = 0.0;
            for(i = 0; i <= m_num_order; i++)
            {
                if( k - i >= 0)
                {
                    il = ((k - i) < M) ? (k - i) : (M - 1);
                    data_out[k] = data_out[k] + m_pNum[i] * data_in[il];
                }
            }
            for(i = 1; i <= m_den_order; i++)
            {
                if( k - i >= 0)
                {
                    data_out[k] = data_out[k] - m_pDen[i] * data_out[k - i];
                }
            }
        }
    }

    直接II

    1. /**< IIR 滤波器直接II型实现 */  
    2. class IIR_II  
    3. {  
    4. public:  
    5.     IIR_II();  
    6.     void reset();  
    7.     void setPara(double num[], int num_order, double den[], int den_order);  
    8.     void resp(double data_in[], int m, double data_out[], int n);  
    9.     double filter(double data);  
    10.     void filter(double data[], int len);  
    11.     void filter(double data_in[], double data_out[], int len);  
    12. protected:  
    13.     private:  
    14.     double *m_pNum;  
    15.     double *m_pDen;  
    16.     double *m_pW;  
    17.     int m_num_order;  
    18.     int m_den_order;  
    19.     int m_N;  
    20. };  
    21.   
    22. class IIR_BODE  
    23. {  
    24. private:  
    25.     double *m_pNum;  
    26.     double *m_pDen;  
    27.     int m_num_order;  
    28.     int m_den_order;  
    29.     complex<double> poly_val(double p[], int order, double omega);  
    30. public:  
    31.     IIR_BODE();  
    32.     void setPara(double num[], int num_order, double den[], int den_order);  
    33.     complex<double> bode(double omega);  
    34.     void bode(double omega[], int n, complex<double> resp[]);  
    35. };  
    /**< IIR 滤波器直接II型实现 */
    class IIR_II
    {
    public:
        IIR_II();
        void reset();
        void setPara(double num[], int num_order, double den[], int den_order);
        void resp(double data_in[], int m, double data_out[], int n);
        double filter(double data);
        void filter(double data[], int len);
        void filter(double data_in[], double data_out[], int len);
    protected:
        private:
        double *m_pNum;
        double *m_pDen;
        double *m_pW;
        int m_num_order;
        int m_den_order;
        int m_N;
    };
    
    class IIR_BODE
    {
    private:
        double *m_pNum;
        double *m_pDen;
        int m_num_order;
        int m_den_order;
        complex<double> poly_val(double p[], int order, double omega);
    public:
        IIR_BODE();
        void setPara(double num[], int num_order, double den[], int den_order);
        complex<double> bode(double omega);
        void bode(double omega[], int n, complex<double> resp[]);
    };

    直接II型实现中所需的存储单元少了很多。另外,这两种实现的外部接口是完全相同的。

    1. IIR_II::IIR_II()  
    2. {  
    3.     //ctor  
    4.     m_pNum = NULL;  
    5.     m_pDen = NULL;  
    6.     m_pW = NULL;  
    7.     m_num_order = -1;  
    8.     m_den_order = -1;  
    9.     m_N = 0;  
    10. };  
    11.   
    12. /** \brief 将滤波器的内部状态清零,滤波器的系数保留 
    13.  * \return 
    14.  */  
    15. void IIR_II::reset()  
    16. {  
    17.     for(int i = 0; i < m_N; i++)  
    18.     {  
    19.         m_pW[i] = 0.0;  
    20.     }  
    21. }  
    22. /** \brief 
    23.  * 
    24.  * \param num 分子多项式的系数,升序排列,num[0] 为常数项 
    25.  * \param m 分子多项式的阶数 
    26.  * \param den 分母多项式的系数,升序排列,den[0] 为常数项 
    27.  * \param m 分母多项式的阶数 
    28.  * \return 
    29.  */  
    30. void IIR_II::setPara(double num[], int num_order, double den[], int den_order)  
    31. {  
    32.     delete[] m_pNum;  
    33.     delete[] m_pDen;  
    34.     delete[] m_pW;  
    35.     m_num_order = num_order;  
    36.     m_den_order = den_order;  
    37.     m_N = max(num_order, den_order) + 1;  
    38.     m_pNum = new double[m_N];  
    39.     m_pDen = new double[m_N];  
    40.     m_pW = new double[m_N];  
    41.     for(int i = 0; i < m_N; i++)  
    42.     {  
    43.         m_pNum[i] = 0.0;  
    44.         m_pDen[i] = 0.0;  
    45.         m_pW[i] = 0.0;  
    46.     }  
    47.     for(int i = 0; i <= num_order; i++)  
    48.     {  
    49.          m_pNum[i] = num[i];  
    50.     }  
    51.     for(int i = 0; i <= den_order; i++)  
    52.     {  
    53.         m_pDen[i] = den[i];  
    54.     }  
    55. }  
    56. /** \brief 计算 IIR 滤波器的时域响应,不影响滤波器的内部状态 
    57.  * \param data_in 为滤波器的输入,0 时刻之前的输入默认为 0,data_in[M] 及之后的输入默认为data_in[M-1] 
    58.  * \param data_out 滤波器的输出 
    59.  * \param M 输入数据的长度 
    60.  * \param N 输出数据的长度 
    61.  * \return 
    62.  */  
    63. void IIR_II::resp(double data_in[], int M, double data_out[], int N)  
    64. {  
    65.     int i, k, il;  
    66.     for(k = 0; k < N; k++)  
    67.     {  
    68.         data_out[k] = 0.0;  
    69.         for(i = 0; i <= m_num_order; i++)  
    70.         {  
    71.             if( k - i >= 0)  
    72.             {  
    73.                 il = ((k - i) < M) ? (k - i) : (M - 1);  
    74.                 data_out[k] = data_out[k] + m_pNum[i] * data_in[il];  
    75.             }  
    76.         }  
    77.         for(i = 1; i <= m_den_order; i++)  
    78.         {  
    79.             if( k - i >= 0)  
    80.             {  
    81.                 data_out[k] = data_out[k] - m_pDen[i] * data_out[k - i];  
    82.             }  
    83.         }  
    84.     }  
    85. }  
    86. /** \brief 滤波函数,采用直接II型结构 
    87.  * 
    88.  * \param data 输入数据 
    89.  * \return 滤波后的结果 
    90.  */  
    91. double IIR_II::filter(double data)  
    92. {  
    93.     m_pW[0] = data;  
    94.     for(int i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态  
    95.     {  
    96.         m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];  
    97.     }  
    98.     data = 0.0;  
    99.     for(int i = 0; i <= m_num_order; i++)  
    100.     {  
    101.         data = data + m_pNum[i] * m_pW[i];  
    102.     }  
    103.     for(int i = m_N - 1; i >= 1; i–)  
    104.     {  
    105.         m_pW[i] = m_pW[i-1];  
    106.     }  
    107.     return data;  
    108. }  
    109. /** \brief 滤波函数,采用直接II型结构 
    110.  * 
    111.  * \param data[] 传入输入数据,返回时给出滤波后的结果 
    112.  * \param len data[] 数组的长度 
    113.  * \return 
    114.  */  
    115. void IIR_II::filter(double data[], int len)  
    116. {  
    117.     int i, k;  
    118.     for(k = 0; k < len; k++)  
    119.     {  
    120.         m_pW[0] = data[k];  
    121.         for(i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态  
    122.         {  
    123.             m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];  
    124.         }  
    125.         data[k] = 0.0;  
    126.         for(i = 0; i <= m_num_order; i++)  
    127.         {  
    128.             data[k] = data[k] + m_pNum[i] * m_pW[i];  
    129.         }  
    130.   
    131.         for(i = m_N - 1; i >= 1; i–)  
    132.         {  
    133.             m_pW[i] = m_pW[i-1];  
    134.         }  
    135.     }  
    136. }  
    137. /** \brief 滤波函数,采用直接II型结构 
    138.  * 
    139.  * \param data_in[] 输入数据 
    140.  * \param data_out[] 保存滤波后的数据 
    141.  * \param len 数组的长度 
    142.  * \return 
    143.  */  
    144. void IIR_II::filter(double data_in[], double data_out[], int len)  
    145. {  
    146.     int i, k;  
    147.     for(k = 0; k < len; k++)  
    148.     {  
    149.         m_pW[0] = data_in[k];  
    150.         for(i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态  
    151.         {  
    152.             m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];  
    153.         }  
    154.         data_out[k] = 0.0;  
    155.         for(i = 0; i <= m_num_order; i++)  
    156.         {  
    157.             data_out[k] = data_out[k] + m_pNum[i] * m_pW[i];  
    158.         }  
    159.   
    160.         for(i = m_N - 1; i >= 1; i–)  
    161.         {  
    162.             m_pW[i] = m_pW[i-1];  
    163.         }  
    164.     }  
    165. }  
    IIR_II::IIR_II()
    {
        //ctor
        m_pNum = NULL;
        m_pDen = NULL;
        m_pW = NULL;
        m_num_order = -1;
        m_den_order = -1;
        m_N = 0;
    };
    
    /** \brief 将滤波器的内部状态清零,滤波器的系数保留
     * \return
     */
    void IIR_II::reset()
    {
        for(int i = 0; i < m_N; i++)
        {
            m_pW[i] = 0.0;
        }
    }
    /** \brief
     *
     * \param num 分子多项式的系数,升序排列,num[0] 为常数项
     * \param m 分子多项式的阶数
     * \param den 分母多项式的系数,升序排列,den[0] 为常数项
     * \param m 分母多项式的阶数
     * \return
     */
    void IIR_II::setPara(double num[], int num_order, double den[], int den_order)
    {
        delete[] m_pNum;
        delete[] m_pDen;
        delete[] m_pW;
        m_num_order = num_order;
        m_den_order = den_order;
        m_N = max(num_order, den_order) + 1;
        m_pNum = new double[m_N];
        m_pDen = new double[m_N];
        m_pW = new double[m_N];
        for(int i = 0; i < m_N; i++)
        {
            m_pNum[i] = 0.0;
            m_pDen[i] = 0.0;
            m_pW[i] = 0.0;
        }
        for(int i = 0; i <= num_order; i++)
        {
             m_pNum[i] = num[i];
        }
        for(int i = 0; i <= den_order; i++)
        {
            m_pDen[i] = den[i];
        }
    }
    /** \brief 计算 IIR 滤波器的时域响应,不影响滤波器的内部状态
     * \param data_in 为滤波器的输入,0 时刻之前的输入默认为 0,data_in[M] 及之后的输入默认为data_in[M-1]
     * \param data_out 滤波器的输出
     * \param M 输入数据的长度
     * \param N 输出数据的长度
     * \return
     */
    void IIR_II::resp(double data_in[], int M, double data_out[], int N)
    {
        int i, k, il;
        for(k = 0; k < N; k++)
        {
            data_out[k] = 0.0;
            for(i = 0; i <= m_num_order; i++)
            {
                if( k - i >= 0)
                {
                    il = ((k - i) < M) ? (k - i) : (M - 1);
                    data_out[k] = data_out[k] + m_pNum[i] * data_in[il];
                }
            }
            for(i = 1; i <= m_den_order; i++)
            {
                if( k - i >= 0)
                {
                    data_out[k] = data_out[k] - m_pDen[i] * data_out[k - i];
                }
            }
        }
    }
    /** \brief 滤波函数,采用直接II型结构
     *
     * \param data 输入数据
     * \return 滤波后的结果
     */
    double IIR_II::filter(double data)
    {
        m_pW[0] = data;
        for(int i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态
        {
            m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];
        }
        data = 0.0;
        for(int i = 0; i <= m_num_order; i++)
        {
            data = data + m_pNum[i] * m_pW[i];
        }
        for(int i = m_N - 1; i >= 1; i--)
        {
            m_pW[i] = m_pW[i-1];
        }
        return data;
    }
    /** \brief 滤波函数,采用直接II型结构
     *
     * \param data[] 传入输入数据,返回时给出滤波后的结果
     * \param len data[] 数组的长度
     * \return
     */
    void IIR_II::filter(double data[], int len)
    {
        int i, k;
        for(k = 0; k < len; k++)
        {
            m_pW[0] = data[k];
            for(i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态
            {
                m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];
            }
            data[k] = 0.0;
            for(i = 0; i <= m_num_order; i++)
            {
                data[k] = data[k] + m_pNum[i] * m_pW[i];
            }
    
            for(i = m_N - 1; i >= 1; i--)
            {
                m_pW[i] = m_pW[i-1];
            }
        }
    }
    /** \brief 滤波函数,采用直接II型结构
     *
     * \param data_in[] 输入数据
     * \param data_out[] 保存滤波后的数据
     * \param len 数组的长度
     * \return
     */
    void IIR_II::filter(double data_in[], double data_out[], int len)
    {
        int i, k;
        for(k = 0; k < len; k++)
        {
            m_pW[0] = data_in[k];
            for(i = 1; i <= m_den_order; i++) // 先更新 w[n] 的状态
            {
                m_pW[0] = m_pW[0] - m_pDen[i] * m_pW[i];
            }
            data_out[k] = 0.0;
            for(i = 0; i <= m_num_order; i++)
            {
                data_out[k] = data_out[k] + m_pNum[i] * m_pW[i];
            }
    
            for(i = m_N - 1; i >= 1; i--)
            {
                m_pW[i] = m_pW[i-1];
            }
        }
    }

    测试

    下面是几个测试例子,首先计算一个4阶切比雪夫低通滤波器的阶跃响应。

    1. void resp_test(void)  
    2. {  
    3.     double b[5] = {0.0018360.0073440.0110160.0073440.001836};  
    4.     double a[5] = {1.0, -3.05443.8291, -2.29250.55075};  
    5.     double x[2] = {1.01.0};  
    6.     double y[100];  
    7.   
    8.     IIR_II filter;  
    9.     filter.setPara(b, 4, a, 4);  
    10.     filter.resp(x, 2, y, 100);  
    11.   
    12.     for(int i= 0; i< 100; i++)  
    13.     {  
    14.         cout << y[i] << endl;  
    15.     }  
    16. }  
    void resp_test(void)
    {
        double b[5] = {0.001836, 0.007344, 0.011016, 0.007344, 0.001836};
        double a[5] = {1.0, -3.0544, 3.8291, -2.2925, 0.55075};
        double x[2] = {1.0, 1.0};
        double y[100];
    
        IIR_II filter;
        filter.setPara(b, 4, a, 4);
        filter.resp(x, 2, y, 100);
    
        for(int i= 0; i< 100; i++)
        {
            cout << y[i] << endl;
        }
    }

    得到的结果如下:

    同样是这个滤波器,计算输入信号为 delta 函数时的结果。

    1. void filter_test(void)  
    2. {  
    3.     double b[5] = {0.001836, 0.007344, 0.011016, 0.007344, 0.001836};  
    4.     double a[5] = {1.0, -3.0544, 3.8291, -2.2925, 0.55075};  
    5.     double x[100], y[100];  
    6.     int len = 100;  
    7.     IIR_I filter;  
    8.     //IIR_II filter;  
    9.     filter.setPara(b, 4, a, 4);  
    10.   
    11.     for (int i = 0; i < len; i++)  
    12.     {  
    13.         x[i] = 0.0;  
    14.         y[i] = 0.0;  
    15.     }  
    16.     x[0] = 1.0;  
    17.     filter.filter(x, y, 100);  
    18.     filter.reset();  
    19.     filter.filter(x, 100);  
    20.   
    21.     for (int i = 0; i < len; i++)  
    22.     {  
    23.         cout << x[i] <<”, ” << y[i]<<  endl;  
    24.     }  
    25. }  
    void filter_test(void)
    {
        double b[5] = {0.001836, 0.007344, 0.011016, 0.007344, 0.001836};
        double a[5] = {1.0, -3.0544, 3.8291, -2.2925, 0.55075};
        double x[100], y[100];
        int len = 100;
        IIR_I filter;
        //IIR_II filter;
        filter.setPara(b, 4, a, 4);
    
        for (int i = 0; i < len; i++)
        {
            x[i] = 0.0;
            y[i] = 0.0;
        }
        x[0] = 1.0;
        filter.filter(x, y, 100);
        filter.reset();
        filter.filter(x, 100);
    
        for (int i = 0; i < len; i++)
        {
            cout << x[i] <<", " << y[i]<<  endl;
        }
    }


    得到的结果如下:






                    </div>
        <script>
        $(".MathJax").remove();
        </script>
    </article>
    
    展开全文
  • 基于MATLAB的IIR滤波器设计 ? ? ? 第一章 绪论 1.1 研究的动机与目的 ? 数字滤波器是数字信号处理理论的一部分数字信号处理是一种通过使用数学技巧执行转换或提取信息来处理现实信号的方法这些信号由数字序列表示...
  • 数字信号处理.FIR和IIR滤波器实验 数字信号处理.FIR和IIR滤波器实验
  • 基于matlab的IIR滤波器设计-基于matlab的IIR数字滤波器设计-刘智.doc 全面的介绍IIR滤波器的设计
  • IIR滤波器实现

    2014-12-02 18:06:01
    stm32实现的IIR滤波器,结合IIR滤波器特点,写出IIR算法C语言实现,并进行实现显示在屏上
  • IIR滤波器的传递函数为: 由此得到的线性差分方程为(时域卷积 --> 频域乘积): 其对应的结构图如下: IIR滤波器和FIR滤波器的区别: FIR滤波器为零极点滤波器,IIR滤波器为带反馈的有极点滤波器,...

     

    IIR滤波器的传递函数为:

    由此得到的线性差分方程为(时域卷积 --> 频域乘积):

    其对应的结构图如下:

    IIR滤波器和FIR滤波器的区别:

    FIR滤波器为零极点滤波器,IIR滤波器为带反馈的有极点滤波器,所以FIR滤波器为更稳定的滤波器,如上为IIR滤波器的实现框图。

     

     

     

    展开全文
  • 如果在嵌入式系统中可以满足且有必要实时iir运算,那么使用iir滤波器相对fir滤波器可以在使用更小的阶数的情况下实现更好的效果。实验证明,可能20阶的iir效果堪比500阶左右的fir滤波器效果。 首先放出iir的matlab...

    对于fir滤波器,已经在前面的文章中记录了(https://blog.csdn.net/suiji2442/article/details/112394026POWER-Z仿制DIY&关于MATLAB中滤波器设计工具的使用心得记录),其设计和实现都非常简单。如果在嵌入式系统中可以满足且有必要实时iir运算,那么使用iir滤波器相对fir滤波器可以在使用更小的阶数的情况下实现更好的效果。实验证明,可能20阶的iir效果堪比500阶左右的fir滤波器效果。

    首先放出iir的matlab仿真代码:

    %本程序为直接2型iir滤波器的实现
    %当阶数较高或fc与fs相差多个数量级时,建议使用基本二阶结的级联形式,避免计算出来的b和a系数非常小或者非常大,因运算中有限字长导致运算出错
    
    NN=8000;
    NNN=20+1;%在这里写iir滤波器的阶数+1
    
    
    t=0:1/NN:1;%采样1秒的信号
    %y= 10+10*cos(2*pi*5*t-pi*30/180)+5*cos(2*pi*50*t-pi*30/180);
    %y= 10+10*cos(2*pi*50*t-pi*30/180)+10*cos(2*pi*200*t-pi*30/180);
    %y= 10+10*cos(2*pi*5*t-pi*30/180)+10*cos(2*pi*50*t-pi*30/180)+2*cos(2*pi*200*t-pi*30/180);
    y= 10+2*cos(2*pi*5*t-pi*30/180)+2*cos(2*pi*30*t-pi*30/180)+10*cos(2*pi*100*t-pi*30/180)+100*cos(2*pi*1000*t-pi*30/180);
    N=length(t); %样点个数
    figure(1);
    plot(t,y);
    fs=NN;%采样频率
    df=fs/(N-1);%分辨率
    f=(0:N-1)*df;%其中每点的频率
    Y=fft(y(1:N))/N*2;%真实的幅值
    figure(2)
    plot(f(1:floor(N/2)),abs(Y(1:floor(N/2))));
    
    
    [b,a]=sos2tf(SOS,G);
    
    pre_x = zeros(1,NNN);% 前几个时刻的输入值
    pre_y = zeros(1,NNN);% 前几个时刻的输出值
    res_iir = zeros(1,N);
    
    for i=1:N
        pre_x(1) = y(i);
        % 差分方程
        % res_iir(i) = b(1)*pre_x(1)+b(2)*pre_x(2)+b(3)*pre_x(3)+b(4)*pre_x(4)-a(2)pre_y(2)-a(3)pre_y(3)-a(4)pre_y(4);
        bx = 0;
        ay = 0;
        for k=1:NNN
            bx = bx + b(k) * pre_x(k);
        end
        for k=2:NNN
            ay = ay + a(k) * pre_y(k);  
        end  
        res_iir(i) = bx - ay;
              
        pre_y(1) = res_iir(i);
        
        for j = NNN : -1 : 2  %更新历史数据
            pre_x(j) = pre_x(j-1);
            pre_y(j) = pre_y(j-1);
        end
    end
    
    
    figure(3);
    plot(t,res_iir);
    fs=NN;%采样频率
    df=fs/(N-1);%分辨率
    f=(0:N-1)*df;%其中每点的频率
    Y2=fft(res_iir(1:N))/N*2;%真实的幅值
    figure(4)
    plot(f(1:floor(N/2)),abs(Y2(1:floor(N/2))));
    
    

    上面代码中,需要使用fdatool生成对应阶数的iir系数,并将系数导出到matlab的工作空间,即导出SOS矩阵和G数组。上述代码是20阶IIR滤波器的实现代码。

    上面的代码是直接结构的IIR实现,首先放出一个出问题的情况:
    其噪声信号为:y= 10+2cos(2pi5t-pi30/180)+2cos(2pi30t-pi30/180)+10cos(2pi100t-pi30/180)+100cos(2pi1000t-pi30/180);
    使用fdatool设计20阶iir,采样频率8000Hz,低通截止频率10Hz(与8000Hz差别很大)。
    代码执行效果如下:

    图1 实验1的原始含噪声信号的时域及频域波形
    在这里插入图片描述

    图2 实验1的20阶iir滤波器滤波之后信号的时域及频域波形
    在这里插入图片描述
    可以从上图看到,滤波结果明显出错。
    那么问题在哪呢?问题就是数字滤波器的运算中有限字长效应。可以看到,将fdatool生成的10个基本二阶结的参数转换为直接形式,得到下面的b和a系数
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    可以看到,其中b系数的值非常非常小,基本都是10的-几十次方,而a系数的值相对正常。那么,会导致什么问题呢?即便是使用双精度浮点进行运算,也会在运算的过程中出现运算字长不足从而使得运算出错的现象,或者iir滤波器的极点出现在单位圆上,出现极限环振荡现象,或者iir滤波器的极点直接出了单位圆,出现不稳定现象,上面的现象便是iir滤波器不稳定,不能正常工作。

    那么有什么解决办法呢?办法有三种:
    一、降低iir滤波器的阶数
    因为在级联的过程中,每一个基本二阶结是级联相乘的,所以当iir的阶数较高时计算出来的直接结构的b、a参数很病态(非常小或者非常大),某些情况下即使使用双精度浮点计算,也是远远不够的,会出现稳定性问题。
    但是当阶数较少的时候就没问题了,例如,还是上面的输入信号,将iir的阶数改为2阶iir,即一个基本二阶结,得到如下的效果(注意将matlab代码中的NNN改成2+1):

    图3 实验2的原始含噪声信号的时域及频域波形
    在这里插入图片描述
    图4 实验2的2阶iir滤波器滤波之后信号的时域及频域波形
    在这里插入图片描述
    可以看到,上面的iir输出波形,已经明显将高频的30Hz、100Hz、1000Hz的高频噪声滤除,只剩下直流分量10,和5Hz的交流低频分量,滤波效果还可以接受,试想,这只是一个2阶的iir呀,效果真好了,使用得当足以秒杀fir滤波器的效果。

    但是上面的2阶iir效果还不是很好,那么再试一下4阶的iir吧!见下图:

    图5 实验3的原始含噪声信号的时域及频域波形
    在这里插入图片描述

    图6 实验3的4阶iir滤波器滤波之后信号的时域及频域波形
    在这里插入图片描述
    看到没,iir滤波器的效果就是这么棒,仅用了一个4阶的iir,上面已经完全把高频分量滤除了,5Hz的原始信号是多么光滑。更加印证了iir滤波器的厉害之处。
    但是,小心,万事都有其两面性。不要沉醉在iir滤波器使用较小的阶数便可以获得较好的结果的优势上,想想,我们为什么要对2阶和4阶iir进行实验?
    因为高阶的iir直接实现形式不稳定!!!
    此时再看,同样的滤波器参数,使用4阶的时候,计算出来的b,a参数:
    在这里插入图片描述
    在这里插入图片描述
    可以看到,其实b参数已经特别小了,达到了10的-10次方数量级,这样的精度在计算过程中其实也比较难了,也可能会出现稳定性问题,但是相对前面20阶的iir,已经好很多了,因此上面的滤波结果也可以正常运行。

    可以看到,降低iir滤波器的阶数,可以帮助稳定iir滤波器。
    那么还有没有其它办法呢?
    有!

    二、使用直接形式的iir滤波器时,fc与fs不要相差多个数量级

    上面的实验中,fs是8000Hz,而低通滤波器的截止频率仅为10Hz,相差800倍,太大了,因此使用直接形式的iir计算出来的b和a系数可能会很病态。
    下面进行实验:
    fs为8000Hz,而iir低通滤波器的截止频率为1000Hz,iir的阶数为20阶,使用直接形式进行计算,看能不能稳定。
    此时输入信号改为:y= 10+2cos(2pi10t-pi30/180)+2cos(2pi1500t-pi30/180)+10cos(2pi2000t-pi30/180)+100cos(2pi3000t-pi30/180);

    实验结果如下:

    图7 实验4的原始含噪声信号的时域及频域波形
    在这里插入图片描述
    图8 实验4的20阶iir滤波器滤波之后信号的时域及频域波形
    在这里插入图片描述
    如上图,可以看到,上面的滤波效果也非常好,将1000Hz以上的高频分量已经滤除。而且即便使用20阶的iir的直接形式,其输出也能基本稳定,原因就是不让fs和fc差别特别大即可。
    此时,计算得到的直接形式的iir滤波器的b,a参数如下:
    在这里插入图片描述
    在这里插入图片描述
    可以看到,只要让fs和fc别差别很大,那么计算得到的b,a参数就不会很病态,此时iir滤波器就能正常运行,当然,前提是使用双精度浮点进行运算是这样的,如果使用单精度浮点进行运算,也不一定能稳定。。。。。。这里顺带再夸一句fir滤波器!!!yyds

    上面,也是可以稳定的一种方法,但是,第一中方法没法做高阶的iir,第二种方法又不得不改变iir的截止频率fc和fs之间的关系。。。。显然,在某些情况下,这两种方法都不能被同时接受,那么,还有没有更好的办法呢?

    劳动人民(此处指代研究人员=打工人)的智慧是无穷的!!!

    三、使用级联结构实现高阶的iir滤波器
    一般情况下,使用的都是多个基本二阶结形式进行级联从而实现高阶的iir滤波器,这样的话,便可以让每个基本二阶结的系数不那么病态了,可以避免因为计算字长的限制而导致的iir滤波器不稳定情况。
    下面便是基本二阶结结构实现的高阶iir形式:
    在这里插入图片描述
    在这里插入图片描述
    下面是基本二阶结级联形式的代码(需要SOS和G矩阵,与上面相同):

    %本程序为多个基本二阶结形式的iir滤波器的实现
    %当阶数较高或fc与fs相差多个数量级时,建议使用基本二阶结的级联形式,避免计算出来的b和a系数非常小或者非常大,因运算中有限字长导致运算出错
    
    NN=8000;
    NNN=20+1;%在这里写iir滤波器的阶数+1
    Sections = floor(NNN/2);%得到iir滤波器的级联形式基本二阶结的级数
    
    t=0:1/NN:1;%采样1秒的信号
    %y= 10+10*cos(2*pi*5*t-pi*30/180)+5*cos(2*pi*50*t-pi*30/180);
    %y= 10+10*cos(2*pi*50*t-pi*30/180)+10*cos(2*pi*200*t-pi*30/180);
    %y= 10+10*cos(2*pi*5*t-pi*30/180)+10*cos(2*pi*50*t-pi*30/180)+2*cos(2*pi*200*t-pi*30/180);
    y= 1+0.5*cos(2*pi*5*t-pi*30/180)+2*cos(2*pi*15*t-pi*30/180)+1*cos(2*pi*50*t-pi*30/180)+5*cos(2*pi*2000*t-pi*30/180);
    N=length(t); %样点个数
    figure(1);
    plot(t,y);
    fs=NN;%采样频率
    df=fs/(N-1);%分辨率
    f=(0:N-1)*df;%其中每点的频率
    Y=fft(y(1:N))/N*2;%真实的幅值
    figure(2)
    plot(f(1:floor(N/2)),abs(Y(1:floor(N/2))));
    
    
    %[b,a]=sos2tf(SOS,G);%不需要再计算直接形式的b和a的系数了
    
    
    %首先需要先定义存放数据的空间
    data = zeros(Sections,6);%有3个维度。第一个维度存放基本二阶结的信息,第二个维度是当前和历史x,y信息
    %data(k,1)表示第k级的x
    %data(k,2)表示第k级的x(n-1)
    %data(k,3)表示第k级的x(n-2)
    %data(k,4)表示第k级的y
    %data(k,5)表示第k级的y(n-1)
    %data(k,6)表示第k级的y(n-2)
    
    res_iir = zeros(1,N);%存放滤波的结果
    
    for i=1:N
        data(1,1) = y(i);%将当前点的信息放进来
        for k=1:Sections
            data(k,4) =  G(k) * (SOS(k,1)*data(k,1)+SOS(k,2)*data(k,2)+SOS(k,3)*data(k,3)) -SOS(k,5)*data(k,5)-SOS(k,6)*data(k,6);
            
            data(k,6) = data(k,5);
            data(k,5) = data(k,4);
            data(k,3) = data(k,2);
            data(k,2) = data(k,1);
    
            if(k~=Sections)%如果不是计算到了最后一级,就将当前的输出送给下一级输入
                data(k+1,1) = data(k,4);
            else
                 res_iir(i) = data(k,4);%如果是计算到了最后一级,就将当前得到结果输出
            end
        end
    end
    
    
    
    figure(3);
    plot(t,res_iir);
    fs=NN;%采样频率
    df=fs/(N-1);%分辨率
    f=(0:N-1)*df;%其中每点的频率
    Y2=fft(res_iir(1:N))/N*2;%真实的幅值
    figure(4)
    plot(f(1:floor(N/2)),abs(Y2(1:floor(N/2))));
    

    设计一个20阶的iir滤波器,同样,采样频率为8000Hz,低通截止频率为10Hz。信号为:y= 1+0.5cos(2pi5t-pi30/180)+2cos(2pi15t-pi30/180)+1cos(2pi50t-pi30/180)+5cos(2pi2000t-pi30/180);效果如下:

    图9 实验5的原始含噪声信号的时域及频域波形
    在这里插入图片描述
    图10 实验5的20阶iir级联滤波器滤波之后信号的时域及频域波形
    在这里插入图片描述
    可以见到上图,使用级联的模式的情况下,便可以使用高阶的iir滤波器对采样的数据进行滤波,即使fs和fc相差非常大也不会带来稳定性问题。

    另外,再进行一个小实验,试一下20阶和50阶的iir带阻滤波器(陷波器)效果怎么样,其中信号中含有幅度非常巨大的49、50、51Hz干扰,输入信号如下:y= 1+2cos(2pi5t-pi30/180)+100cos(2pi49t-pi30/180)+100cos(2pi50t)+100cos(2pi51t-pi30/180)+0.5cos(2pi70t-pi30/180)+5cos(2pi2000t-pi*30/180);

    实验中,因为iir阶数变大,所以将数据时间长度调大到了5秒的数据长度。
    陷波器阻带为45Hz~55Hz。采样频率8000Hz。

    下面是实验结果:

    图11 实验6的原始含噪声信号的时域及频域波形
    在这里插入图片描述
    图12 实验6的20阶iir级联带阻滤波器滤波之后信号的时域及频域波形
    在这里插入图片描述
    可以看到仅使用20阶iir滤波效果就非常好了。

    下面开始50阶iir滤波器的验证:

    图13 实验7的原始含噪声信号的时域及频域波形
    在这里插入图片描述

    图14 实验7的50阶iir级联带阻滤波器滤波之后信号的时域及频域波形
    在这里插入图片描述

    可以看到上面20阶和50阶iir滤波器的对比,发现50阶iir滤波器需要更长的时间才能稳定,即其反馈环路更长,然而他们的实际滤波效果并差不多,因此,给我们的启示是:在实际的系统中,应当合理选择iir滤波器的阶数,并不是越高越好。

    下面展示一下两个滤波器(20阶和50阶)的滤波后稳定波形的细节放大图:

    图15 20阶iir级联带阻滤波器滤波之后信号的时域波形细节图
    在这里插入图片描述
    图16 50阶iir级联带阻滤波器滤波之后信号的时域波形细节图
    在这里插入图片描述
    对比图15和图16,发现无论是20阶还是50阶iir滤波器稳定之后的滤波效果都非常好,输出的波形里面只包含了幅度为1的直流分量、幅度为2的5Hz低频分量和幅度为0.5的70Hz高频分量。两个图的波形基本一致。然而50阶的iir滤波器需要更长时间稳定。

    至此,无论是fir滤波器还是iir滤波器,我们均从其具体实现方法方面进行了一些实验,发现、解决了一些问题,对于里面的代码,可以非常方便地修改为C语言代码应用于嵌入式开发中。

    这两篇小文档作为自己进行这些实验的一个小结和心得吧,可以留给以后的自己去看。

    但是,这两种滤波器仅当噪声的频率与实际信号频率之间不重叠的时候有用。对于一些随机时间信号噪声,这种经典滤波器是无能为力的,然后就需要一些现代统计最优滤波器去对这些噪声进行滤波,例如维纳滤波器、卡尔曼滤波器、自适应滤波等。这些统计最优滤波器的相关实验等待后面更新吧~
    最后,再次感谢本学期“信号处理与数据分析”课程的邱老师,这门课程真的很有用,特别是应用于实践之后。

    展开全文
  • IIR滤波器的C实现

    2020-07-31 04:43:01
    本文给出一个IIR滤波器的C实现程序。
  • 华东师范大学 IIR滤波器的DSP及Matlab实现 PAGE 1 IIR滤波器的DSP及Matlab实现 华东师范大学 2010届学士学位论文 专业班级 姓 名 时 间 指导教师 2010 年 5 月 12 日 设计目的 掌握数字滤波器的设计过程 了解IIR的...
  • matlab FIR IIR 滤波器

    2017-05-31 12:59:03
    主要是FIR IIR 滤波器的matlab实现
  • 2IIR滤波器的 MATLAB实现 2.1 IIR 滤波器的设计方法及原理 IIR 数字滤波器是一种离散时间系统其系统函数为: H(Z)二Mbk H(Z)二 M bkZ上 k =0 ~N 1 akZ 上 y(z) XcZ) 假设 M N,当M> N寸,系统函数可以看作一个IIR的子...
  • IIR滤波器程序

    2015-01-21 17:00:52
    比较全面的IIR滤波器程序,非常适用于学习滤波器课程的同学 参考使用
  • 数字滤波器的MATLAB和FPGA实现 第5章 IIR滤波器MATLAB与FPGA实现 5.1 IIR滤波器的理论基础 5.1.1 IIR滤波器的原理及特性 5.1.1 IIR滤波器的原理及特性 直接I型 直接II型 级联型 并联型 5.2.1 几种典型的模拟滤波器 1...
  • 主要介绍在TMS320C54X DSP上如何实现扩展精度的乘法、IIR滤波器的基本原理和算法实现,以及二阶级联IIR滤波器应用于均衡器的具体编程实现。
  • IIR滤波器设计用表

    2018-06-11 22:24:11
    设计iir滤波器,根据滤波器阶数,查表得到的归一化传输函数。,
  • IIR滤波器 参考如何快速设计一个IIR滤波器,对模型滤波器到数字滤波器的双线性变换解释比较清楚
  • IIR滤波器(1)

    2021-01-20 12:44:18
    1. IIR滤波器的数学表达式 区别于FIR滤波器,IIR滤波器的冲激响应是无限的。 用差分方程来表示一个滤波器,如下式所示: y(n)=∑k=1Naky(n−k)+∑k=0Nbkx(n−k) y(n) = \sum_{k=1}^Na_ky(n-k)+\sum_{k=0}^Nb_kx(n-k)...
  • 最后在CCS环境和DES5402PP开发板的基础上,给出了系统具体的设计方案,实现了IIR滤波器的功能。  1 IIR滤波器的MATLAB设计  IIR滤波器有以下几个特点:  ⑴ IIR数字滤波器的系统函数可以写成封闭函数的形式。 ...
  • 基于IIR滤波器和FIR滤波器的matlab仿真,完整设计,无需再改,可以直接运行。毕设必备 ,谢谢大家运行。
  • 学习随笔之IIR滤波器与FIR滤波器IIR滤波器(Infinite Impulse Response Digital Filter无限冲击响应数字滤波器)与FIR滤波器(Finite Impulse Response Digital Filter有限冲击响应数字滤波器),是数字信号处理系统中...
  • 针对传统的滤波器设计方法效率低、方法复杂、不能满足高效高精度的需要等缺点,基于MATLAB研究了分别使用窗函数法和双线性变换法的FIR和IIR滤波器。将加入噪声的信号分别通过两种滤波器,滤除加入的噪声,对滤波前后...
  • 实验六 IIR滤波器的设计一、实验目的:在理论学习的基础上,掌握不同IIR滤波器的性质、特点,并通过实验学习如何设计各种常用的IIR滤波器,以便在实际工作中能根据具体情况使用IIR滤波器。二、实验要求:1、执行例6-1...
  • IIR滤波器的实现

    千次阅读 2018-03-19 15:54:14
    转载自: http://www.stmcu.org/module/forum/thread-601141-1-1.html  本... 40.1 IIR滤波器介绍 40.2 Matlab工具箱fdatool生成IIR滤波器系数 40.3 IIR低通滤波器设计 40.4 IIR高通滤波器设计 40.5 IIR带...
  • FIR和IIR滤波器.rar

    2019-11-29 10:05:02
    本文档主要运用matlab语言设计了FIR和IIR低通滤波器、高通滤波器和带通滤波器,FIR滤波器的设计主要采用了巴特沃斯滤波器的设计方法,设计出了相应的函数,IIR滤波器主要使用汉明窗来设计,实际使用可以根据自己需要...
  • 基于DSP的IIR滤波器,大作业
  • 利用MATLAB的设计IIR滤波器.ppt
  • 这是欧拉线性放大里的IIR滤波器的图形仿真,有兴趣可以看看
  • FIR和IIR滤波器的一个主要区别:FIR是线性相位,IIR为非线性相位(双线性变换法),对于非线性相位会造成的影响,可以这样考虑:对于输入的不同频率分量,造成的相位差与频率不成正比,则输出时不同频率分量的叠加的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,045
精华内容 818
关键字:

iir滤波器