硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1641|回复: 4
收起左侧

[DSP] DSP定点Q31 IIR滤波器的matlab设置,使用函数arm_biquad_cascade_df1_q31

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
发表于 2022-8-24 19:42:54 | 显示全部楼层 |阅读模式
测试工程:
定点Q31 IIR滤波.7z (4.70MB)



测试波形是50Hz和200Hz正弦波,采样率设置的1KHz,IIR低通的截止频率设置的80Hz。

Matlab设置如下(详细设置看DSP教程第2版的IIR章节即可,生成方法不变):

image.png

将生成的参数代入到工程代码,滤波输出效果如下,未做定标处理

滤波效果是没问题的,完全正常(简单做了放缩处理,方便观察)

image.png

代码如下:
由于我们继续使用的浮点生成的系数,这个系统不能直接使用,需要先缩小,防止溢出,然后再调用函数arm_float_to_q31加大。

最后再配合函数arm_biquad_cascade_df1_init_q31做调整

[C] 纯文本查看 复制代码
#define numStages  5                /* 5阶IIR滤波的个数 */
#define TEST_LENGTH_SAMPLES  400    /* 采样点数 */
#define BLOCK_SIZE           400    /* 调用一次arm_biquad_cascade_df1_f32处理的采样点个数 */


uint32_t blockSize = BLOCK_SIZE;
uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE;    /* 需要调用arm_biquad_cascade_df1_f32的次数 */   

/////////////////////////////////////// 定点Q31 /////////////////////////////////////////////////////////////////////////
static q31_t testInput_f32_50Hz_200Hz1[TEST_LENGTH_SAMPLES]; /* 采样点 */
static q31_t testOutput1[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
static q31_t IIRStateF321[4*numStages];                      /* 状态缓存 */

q31_t IIRCoeffs32LP1[5*numStages]; 

/* 巴特沃斯低通滤波器系数 80Hz*/                                                                                                                                         
float32_t IIRCoeffs32LP[5*numStages] = {                                                                                         
        1,  2,  1,    1.62978785624054456349085739930160343647,   -0.85983730736705732411451208463404327631, 
        1,  2,  1,    1.438087052475096605519411241402849555016,  -0.641077359359069620658999610895989462733,
        1,  2,  1,    1.307285028849323404998017394973430782557,  -0.491812237222575276973657310009002685547,
        1,  2,  1,    1.226250602643673470737439856748096644878,  -0.39933955836362394764549321735103148967,
        1 , 2,  1,    1.187550247801674174752406543120741844177,  -0.355176532195590921592298627729178406298
}; 

/*
*********************************************************************************************************
*        函 数 名: arm_iir_q31_lp
*        功能说明: 调用函数arm_iir_q31_lp实现低通滤波器
*        形    参:无
*        返 回 值: 无
*********************************************************************************************************
*/
static void arm_iir_q31_lp(void)
{
        uint32_t i;
        arm_biquad_casd_df1_inst_q31 S;
        q63_t ScaleValue;
        q31_t *inputQ31, *outputQ31;
        
        /* 使用浮点系数先进行一次缩放,然后再使用函数arm_float_to_q31转换为Q31,防止溢出 */
        for(int i = 0; i < 5*numStages; i++)
        {
                IIRCoeffs32LP[i] = IIRCoeffs32LP[i]/8;
        }
        
        arm_float_to_q31(IIRCoeffs32LP, IIRCoeffs32LP1, 5*numStages);
        
        for(int i = 0; i < 5*numStages; i++)
        {
                //printf("%d\r\n", IIRCoeffs32LP1[i]);
        }
        
        /* 初始化输入输出缓存指针 */
        inputQ31 = &testInput_f32_50Hz_200Hz1[0];
        outputQ31 = &testOutput1[0];
        
        for(i=0; i<TEST_LENGTH_SAMPLES; i++)
        {
                /* 50Hz正弦波+200Hz正弦波,采样率1KHz */
                testInput_f32_50Hz_200Hz1[i] =  arm_sin_q31(2147483647/1000*50*i) / 16  + arm_sin_q31(2147483647/1000*200*i)/16;
        }
        
        /* 初始化,根据系数的缩放,此函数的最后一个参数要做调整 */
        arm_biquad_cascade_df1_init_q31(&S, numStages, (q31_t *)&IIRCoeffs32LP1[0], (q31_t *)&IIRStateF321[0], 1);
        
        /* 实现IIR滤波,这里每次处理1个点 */
        for(i=0; i < numBlocks; i++)
        {
                arm_biquad_cascade_df1_q31(&S, inputQ31 + (i * blockSize),  outputQ31 + (i * blockSize),  blockSize);
        }
                
        /* 放缩系数,testOutput1乘以放缩系数才是准确的 */
        //0.057512362781628162400338055704196449369                                                        
        //0.050747576720993219090427572837143088691                                                        
        //0.046131802093312926360546555315522709861                                                        
        //0.043272238929987591471437724521820200607                                                        
        //0.041906571098479158954397405523195629939 
        
        /* 打印滤波后结果 */
        for(i=0; i<TEST_LENGTH_SAMPLES; i++)
        {
                printf("%d, %d\r\n", testInput_f32_50Hz_200Hz1[i], testOutput1[i]);
        }
}

/*
*********************************************************************************************************
*        函 数 名: main
*        功能说明: c程序入口
*        形    参: 无
*        返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
        uint8_t ucKeyCode;                /* 按键代码 */

        bsp_Init();                /* 硬件初始化 */
        PrintfLogo();        /* 打印例程信息到串口1 */

        PrintfHelp();        /* 打印操作提示信息 */
        
        bsp_StartAutoTimer(0, 100);        /* 启动1个100ms的自动重装的定时器 */
        

        /* 进入主程序循环体 */
        while (1)
        {
                bsp_Idle();                /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */
                

                if (bsp_CheckTimer(0))        /* 判断定时器超时时间 */
                {
                        /* 每隔100ms 进来一次 */
                        bsp_LedToggle(2);        /* 翻转LED的状态 */
                }
                
                ucKeyCode = bsp_GetKey();        /* 读取键值, 无键按下时返回 KEY_NONE = 0 */
                if (ucKeyCode != KEY_NONE)
                {
                        switch (ucKeyCode)
                        {
                                case KEY_DOWN_K1:                    /* K1键按下 */
                                        arm_iir_q31_lp();
                                        break;

                                default:
                                        /* 其它的键值不处理 */
                                        break;
                        }
                }

        }
}





回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
 楼主| 发表于 2022-8-25 10:27:31 | 显示全部楼层
更新了下
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
 楼主| 发表于 2022-8-25 16:07:31 | 显示全部楼层
再次更新matlab生成系数的溢出问题
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2024-2-20 18:15:34 | 显示全部楼层
汉哥,使用本帖内的工程移植后,我得到滤波前和滤波后得到的波形似乎不正确,移植的平台是HC32F460(M4内核,且开启了FPU加速),IAR的DSP库版本是 V1.5.2。
main函数中的功能仅有一次arm_iir_q31_lp调用,所以没有上传main函数
滤波的结果上传在图片里了,能麻烦汉哥帮看看吗,是什么问题?


[C] 纯文本查看 复制代码
#include "arm_math.h"
#include "Ripple.h"
typedef  unsigned char         BOOL;
typedef  signed char           S8;
typedef  unsigned char         U8;
typedef  signed short          S16;
typedef  unsigned short        U16;
typedef  signed int            S32;
typedef  unsigned int          U32;
typedef  unsigned long long    U64;
typedef  signed long long      S64;
typedef  float                 F32;
typedef  double                F64;

#define STAGE  5                /* 5阶IIR滤波的个数 */
#define TEST_LENGTH_SAMPLES  400    /* 采样点数 */
#define BLOCK_SIZE           400    /* 调用一次arm_biquad_cascade_df1_f32处理的采样点个数 */

U32 blockSize = BLOCK_SIZE;
U32 numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE;    /* 需要调用arm_biquad_cascade_df1_f32的次数 */  

/* 巴特沃斯低通滤波器系数 80Hz*/                                                                                                                                        
F32 IIRCoeffs32LP[5*STAGE] = 
{                                                                                         
    1,  2,  1,    1.62978785624054456349085739930160343647,   -0.85983730736705732411451208463404327631, 
    1,  2,  1,    1.438087052475096605519411241402849555016,  -0.641077359359069620658999610895989462733,
    1,  2,  1,    1.307285028849323404998017394973430782557,  -0.491812237222575276973657310009002685547,
    1,  2,  1,    1.226250602643673470737439856748096644878,  -0.39933955836362394764549321735103148967,
    1 , 2,  1,    1.187550247801674174752406543120741844177,  -0.355176532195590921592298627729178406298
}; 

static q31_t testInput_f32_50Hz_200Hz1[TEST_LENGTH_SAMPLES]; /* 采样点 */
static q31_t testOutput1[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
static q31_t IIRStateF321[4*STAGE];                      /* 状态缓存 */

q31_t IIRCoeffs32LP1[5*STAGE]; 

void arm_iir_q31_lp(void)

{
    uint32_t i;
    arm_biquad_casd_df1_inst_q31 S;
    q63_t ScaleValue;
    q31_t *inputQ31, *outputQ31;

    /* 使用浮点系数先进行一次缩放,然后再使用函数arm_float_to_q31转换为Q31,防止溢出 */
    for(int i = 0; i < 5*STAGE; i++)
    {
        IIRCoeffs32LP[i] = IIRCoeffs32LP[i]/8;
    }
    arm_float_to_q31(IIRCoeffs32LP, IIRCoeffs32LP1, 5*STAGE);
    for(int i = 0; i < 5*STAGE; i++)
    {
        //printf("%d\r\n", IIRCoeffs32LP1[i]);
    }
    /* 初始化输入输出缓存指针 */
    inputQ31 = &testInput_f32_50Hz_200Hz1[0];
    outputQ31 = &testOutput1[0];
    for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    {
        /* 50Hz正弦波+200Hz正弦波,采样率1KHz */
        testInput_f32_50Hz_200Hz1[i] =  arm_sin_q31(2147483647/1000*50*i) / 16  + arm_sin_q31(2147483647/1000*200*i)/16;
    }

    /* 初始化,根据系数的缩放,此函数的最后一个参数要做调整 */
    arm_biquad_cascade_df1_init_q31(&S, STAGE, (q31_t *)&IIRCoeffs32LP1[0], (q31_t *)&IIRStateF321[0], 1);
    /* 实现IIR滤波,这里每次处理1个点 */
    for(i=0; i < numBlocks; i++)
    {
        arm_biquad_cascade_df1_q31(&S, inputQ31 + (i * blockSize),  outputQ31 + (i * blockSize),  blockSize);
    }

    /* 放缩系数,testOutput1乘以放缩系数才是准确的 */
    //0.057512362781628162400338055704196449369                                                        
    //0.050747576720993219090427572837143088691                                                        
    //0.046131802093312926360546555315522709861                                                        
    //0.043272238929987591471437724521820200607                                                        
    //0.041906571098479158954397405523195629939 
        
    /* 打印滤波后结果 */
    for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    {
        printf("%d\r\n", testInput_f32_50Hz_200Hz1[i]);
    }
        /* 打印滤波后结果 */
    for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    {
        printf("%d\r\n", testOutput1[i]);
    }
}



蓝色为滤波后,橙色为滤波前

蓝色为滤波后,橙色为滤波前
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
 楼主| 发表于 2024-2-21 09:14:50 | 显示全部楼层
KC8022 发表于 2024-2-20 18:15
汉哥,使用本帖内的工程移植后,我得到滤波前和滤波后得到的波形似乎不正确,移植的平台是HC32F460(M4内核 ...

你这个是浮点API,按说不该有问题,直接跑我原始的测试代码,是否正常。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-28 04:00 , Processed in 0.359885 second(s), 37 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表