dsp库实现iir滤波器

问题遇到的现象和发生背景

目的:使用stm32f407zgt6制作一个iir低通滤波器,混频信号200hz加50hz,输出50hz;
使用:
定时器2触发ADC实时采集,定时器6触发DAC输出,采样频率为10k,数据传输都是DMA。
滤波使用dsp库中的 arm_biquad_cascade_df1_f32(&S, inputF32,outputF32,1);
因为想要实时输出,每次只处理一个点。
结果:
输入波形与输出波形一样。没有实现滤波。

img

操作环境、软件版本等信息

环境:cubemx与keilarm

尝试过的解决方法
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dac.h"
#include "dma.h"
#include "tim.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "arm_math.h"
#include "stdio.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
//static void arm_iir_f32_lp(void);
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
#define numStages  2                /* 2阶IIR滤波的个数 */
#define TEST_LENGTH_SAMPLES  400    /* 采样点数 */
#define BLOCK_SIZE           1        /* 调用一次arm_biquad_cascade_df1_f32处理的采样点个数 */


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


static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
static float32_t IIRStateF32[4*numStages];                      /* 状态缓存 */
int a=0;
/* 巴特沃斯低通滤波器系数 80Hz*/                                                                                                                                         
const float32_t IIRCoeffs32LP[5*numStages] = {                                                                                 
    1.0f,  2.0f,  1.0f,  1.479798894397216679763573665695730596781f,  -0.688676953053861784503908438637154176831f,
    1.0f,  2.0f,  1.0f,  1.212812092620218384908525877108331769705f,  -0.384004162286553540894828984164632856846f                                                                                              
};  

uint16_t Sine12bit[32] = {
    2048    , 2460    , 2856    , 3218    , 3532    , 3786    , 3969    , 4072    ,
    4093    , 4031    , 3887    , 3668    , 3382    , 3042    ,2661    , 2255    , 
    1841    , 1435    , 1054    , 714    , 428    , 209    , 65    , 3        ,
    24        , 127    , 310    , 564    , 878    , 1240    , 1636    , 2048
};


uint32_t i;
arm_biquad_casd_df1_inst_f32 S;
float32_t ScaleValue;
float32_t  *inputF32, *outputF32;
float32_t dac_value[1];
float32_t ScaleValue = 0.052219514664161220673932461977528873831f * 0.042798017416583809813257488485760404728f ; 
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */








/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */



/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_DAC_Init();
  MX_TIM6_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
    
    inputF32 = &testInput_f32_50Hz_200Hz[0];
    outputF32 = &testOutput[0];
    
    arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32LP[0], (float32_t *)&IIRStateF32[0]);
    
    HAL_TIM_Base_Start(&htim2);
  HAL_ADC_Start_DMA(&hadc1,(uint32_t *)testInput_f32_50Hz_200Hz,1);
    
  HAL_TIM_Base_Start(&htim6);
  HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)dac_value,1, DAC_ALIGN_12B_R);
    



    
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
        a=~a;
    
        inputF32[0] = (float32_t)testInput_f32_50Hz_200Hz[0];
        arm_biquad_cascade_df1_f32(&S, inputF32,outputF32,1);
    
    
        testOutput[0]=outputF32[0];
        dac_value[0]=testOutput[0]*ScaleValue;

        HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,a);
    
    

}



/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */



img

img

img

img

img

img

img

img

img

img

img

img

我想要达到的结果

滤除200hz的信号

img

img

img

img

img

img

img

img

img

img

img

img

DSP-IIR滤波器设计
非常详细,可以参考下

要实现滤波的功能,首先需要设计滤波器,方法大概为:在MATLAB命令窗口输入fdatool,然后调出滤波器设计窗口,然后填入参数,点击Design Filter,点击Edit->Convert Structure,选择I型,转化好后,点击File-Export,第一项选择Coefficient File(ASCII):第一项选择好以后,第二项选择Decimal:点击Export。
设计滤波器系数之后,就可以使用IIR滤波器函数:arm_biquad_cascade_df1_f32

参考 https://blog.csdn.net/weixin_50932441/article/details/128064922

数字信号处理(DSP)实验——IIR数字滤波器设计与仿真_修改信号产生函数_Safaearth的博客-CSDN博客 一、实验目的(1)熟悉IIR数字滤波器的原理与方法;(2)学会调用MATLAB信号处理工具箱中滤波器设计函数(或滤波器设计分析工具fdatool)设计各种IIR数字滤波器,学会根据滤波需求确定滤波器指标参数。(3)通过观察滤波器输入输出信号的时域波形及其频谱,建立数字滤波的概念。二、实验原理与方法设计IIR数字滤波器一般采用间接法(脉冲响应不变法和双线性变换法),应用最广泛的是双线性变换法。基本设计过程是:①先将给定的数字滤波器的指标转换成过渡模拟滤波器的指标; ②设计过渡模拟滤波器;③将过渡模拟_修改信号产生函数 https://blog.csdn.net/Insincerity/article/details/115635705

如果你的输入波形与输出波形一样,没有实现滤波的效果,可能有以下几个问题需要检查和解决:

滤波器的系数配置:
确保你正确配置了低通滤波器的系数。滤波器的系数决定了滤波器的特性,包括截止频率等。你可以通过DSPLib库中的函数来计算合适的滤波器系数,以满足你的滤波需求。

数据类型选择:
确保你选择了合适的数据类型来进行滤波计算。arm_biquad_cascade_df1_f32函数使用的是float32类型的数据。如果你的输入数据是int类型,你需要将其转换为float32类型进行滤波计算。

缓冲区设置:
确保你为输入和输出数据分配了足够的缓冲区。arm_biquad_cascade_df1_f32函数需要一个输入缓冲区和一个输出缓冲区。

DMA配置:
确保你正确配置了DMA通道和相关的寄存器。确保DMA从ADC读取数据并将其传输到处理滤波的函数,然后再将滤波后的数据传输到DAC进行输出。

DMA传输触发:
确保你正确配置DMA的传输触发源。定时器2触发ADC实时采集,定时器6触发DAC输出,需要配置DMA的传输触发源为对应的定时器触发。

中断优先级:
确保你正确配置了中断的优先级。如果你在使用中断来触发ADC和DAC的采样和输出,确保中断优先级设置正确,以便确保采样和输出的时间同步。

请检查以上步骤,并确保正确配置了每个模块的设置和参数。如果仍然无法实现滤波效果,请提供更多的代码和相关设置,以便更详细地分析问题并提供进一步的帮助。

在代码中,200Hz的信号被滤除,可以通过修改TEST_LENGTH_SAMPLES和numStages的值来调整滤波器的性能和输出结果。


#include "main.h"
#include "adc.h"
#include "dac.h"
#include "dma.h"
#include "tim.h"
#include "gpio.h"

#include "arm_math.h"
#include "stdio.h"

#define numStages  2                      // 2阶IIR滤波器的个数
#define TEST_LENGTH_SAMPLES  400          // 采样点数
#define BLOCK_SIZE           1            // 调用一次arm_biquad_cascade_df1_f32处理的采样点个数

static float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; // 采样点
static float32_t testOutput[TEST_LENGTH_SAMPLES];               // 滤波后的输出
static float32_t IIRStateF32[4 * numStages];                     // 状态缓存

const float32_t IIRCoeffs32LP[5 * numStages] = {                 // 巴特沃斯低通滤波器系数 80Hz
    1.0f, 2.0f, 1.0f, 1.479798894397216679763573665695730596781f, -0.688676953053861784503908438637154176831f,
    1.0f, 2.0f, 1.0f, 1.212812092620218384908525877108331769705f, -0.384004162286553540894828984164632856846f
};

arm_biquad_cascade_df1_inst_f32 S;
float32_t ScaleValue;
float32_t *inputF32, *outputF32;
float32_t dac_value[1];

void SystemClock_Config(void);
void Error_Handler(void);

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    inputF32[0] = (float32_t)testInput_f32_50Hz_200Hz[0];
    arm_biquad_cascade_df1_f32(&S, inputF32, outputF32, 1);

    testOutput[0] = outputF32[0];
    dac_value[0] = testOutput[0] * ScaleValue;
}

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    MX_GPIO_Init();
    MX_DMA_Init();
    MX_DAC_Init();
    MX_TIM6_Init();
    MX_ADC1_Init();
    MX_TIM2_Init();

    inputF32 = &testInput_f32_50Hz_200Hz[0];
    outputF32 = &testOutput[0];

    arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32LP[0], (float32_t *)&IIRStateF32[0]);

    HAL_TIM_Base_Start(&htim2);
    HAL_TIM_Base_Start(&htim6);
    HAL_ADC_Start_DMA(&hadc1, (uint32_t *)testInput_f32_50Hz_200Hz, 1);
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)dac_value, 1, DAC_ALIGN_12B_R);

    ScaleValue = 0.052219514664161220673932461977528873831f * 0.042798017416583809813257488485760404728f;

    while (1)
    {
    }
}

void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    RCC_OscInitStruct.PLL.PLLM = 16;
    RCC_OscInitStruct.PLL.PLLN = 336;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
    RCC_OscInitStruct.PLL.PLLQ = 4;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }

    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
                                  RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    {
        Error_Handler();
    }

    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);

    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

void Error_Handler(void)
{
    __disable_irq();
    while (1)
    {
    }
}


基于new bing部分指引作答:
1、首先,请确保您已正确设置IIR滤波器的系数和状态。在您的代码中,您定义了巴特沃斯低通滤波器的系数IIRCoeffs32LP和状态缓存IIRStateF32,并在初始化后将其传递给arm_biquad_cascade_df1_init_f32函数。请确保这些系数和状态是正确的。

2、其次,请确保您正确获取输入样本,并将其传递给滤波器函数。在您的代码中,您在HAL_ADC_ConvCpltCallback回调函数中获取了输入样本,并将其存储在inputF32数组中。然后,您调用arm_biquad_cascade_df1_f32函数并将输入样本传递给它。但是,请注意,您将inputF32和outputF32指针分别定义为&testInput_f32_50Hz_200Hz[0]和&testOutput[0],这可能导致错误的内存访问。您应该直接使用这些数组而不是定义指针。

3、此外,您在arm_biquad_cascade_df1_f32函数之后立即将输出值outputF32[0]存储在testOutput[0]数组中,并将其乘以ScaleValue后传递给DAC。然而,滤波器的输出值可能不是立即可用的,因此在获取输出值之前,您应该等待滤波器完成处理。您可以使用arm_biquad_cascade_df1_f32函数的返回值来判断滤波器是否已完成处理。

下面是对您的代码进行了一些修改的示例:

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_DAC_Init();
  MX_TIM6_Init();
  MX_ADC1_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  
  // 移除下面两行定义
  // inputF32 = &testInput_f32_50Hz_200Hz[0];
  // outputF32 = &testOutput[0];
  
  arm_biquad_cascade_df1_init_f32(&S, numStages, (float32_t *)&IIRCoeffs32LP[0], (float32_t *)&IIRStateF32[0]);
  
  HAL_TIM_Base_Start(&htim2);
  HAL_ADC_Start_DMA(&hadc1, (uint32_t *)testInput_f32_50Hz_200Hz, 1);
  
  HAL_TIM_Base_Start(&htim6);
  HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)dac_value, 1, DAC_ALIGN_12B_R);
  
  while (1)
  {
    // 空闲循环
  }
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  a = ~a;
  
  // 直接使用数组而不是定义指针
  testInput_f32_50Hz_200Hz[0] = (float32_t)testInput_f32_50Hz_200Hz[0];
  
  // 等待滤波器完成处理
  if (arm_biquad_cascade_df1_f32(&S, testInput_f32_50Hz_200Hz, testOutput, 1) == ARM_MATH_SUCCESS)
  {
    dac_value[0] = testOutput[0] * ScaleValue;
  }
  
  HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, a);
}

/* USER CODE END 3 */

这只是一个示例修改,可能还需要其他更改才能完全解决问题。您可能还需要检查其他代码部分,例如时钟配置和外设初始化,以确保它们正确无误。

要修改您的代码以实现对200Hz信号的滤波,您需要更新滤波器系数和相应的变量。根据您提供的代码,以下是修改的部分:

更新滤波器系数:将巴特沃斯低通滤波器的系数更改为适用于200Hz截止频率的系数。您可以使用MATLAB或其他滤波器设计工具来计算这些系数,然后将其更新到代码中的IIRCoeffs32LP数组。

/* 巴特沃斯低通滤波器系数 200Hz */
const float32_t IIRCoeffs32LP[5*numStages] = {                                                                                 
    1.0f,  2.0f,  1.0f,  0.8850222227396416f,  -0.4300648228049617f,
    1.0f,  2.0f,  1.0f,  0.783011244625315f,  -0.3370114227395669f                                                                                              
};  

这只是一个示例系数,您可能需要根据具体的滤波器设计需求进行调整。

更新采样频率和截止频率:根据您的要求,采样频率为10kHz,截止频率为200Hz。确保在代码中正确设置这些参数。

#define SAMPLING_FREQUENCY 10000  /* 采样频率 */
#define CUTOFF_FREQUENCY 200      /* 截止频率 */

更新ScaleValue的计算:ScaleValue用于将滤波器输出缩放为DAC的输出值。确保根据新的滤波器系数进行适当的计算。

float32_t ScaleValue = <根据新的滤波器系数进行计算>;

这些是您需要修改的主要部分。请注意,这只是一个示例,您可能还需要根据您的具体硬件和应用程序需求进行其他修改。

在进行修改后,重新编译和运行代码,您应该能够看到对200Hz信号的滤波效果。

希望这些信息对您有所帮助!

答案参考ChatGPT Plus版,整理汇总。希望能帮助你解决问题
代码中的一些问题可能导致滤波器无法正常工作。以下是可能的问题和建议的解决方法:

  1. 数组索引错误:在滤波器处理函数HAL_ADC_ConvCpltCallback中,你将输入值和输出值分别存储在inputF32outputF32数组中。然而,在处理函数中,你只处理了第一个采样点(inputF32[0]outputF32[0])。这意味着你只处理了输入和输出缓冲区中的一个采样点。你需要在循环中处理所有的采样点。你可以使用循环来遍历输入和输出缓冲区,如下所示:
for (uint32_t i = 0; i < numBlocks; i++) {
    inputF32[0] = testInput_f32_50Hz_200Hz[i]; // 设置当前采样点的输入值
    arm_biquad_cascade_df1_f32(&S, inputF32, outputF32, blockSize); // 处理当前采样点

    // 更新输出缓冲区的当前采样点
    testOutput[i] = outputF32[0];

    // 更新DAC的输出值
    dac_value[0] = testOutput[i] * ScaleValue;

    // 设置GPIO引脚状态
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, a);

    // 增加数组索引
    inputF32++;
    outputF32++;
}
  1. DMA传输配置:确保DMA配置正确,以实现从ADC到内存和从内存到DAC的数据传输。检查DMA的配置参数,包括数据宽度、数据方向和缓冲区地址等。

  2. ADC和DAC的初始化:确保ADC和DAC的初始化正确,并使用正确的采样率和数据对齐方式。

  3. 系数和状态数组大小:根据你的滤波器配置,确保IIRCoeffs32LPIIRStateF32数组的大小足够存储所有的滤波器系数和状态。根据你的代码,每个滤波器阶段需要4个状态变量,因此状态数组的大小应为4 * numStages

  4. 系数的设置:根据你的要求,你使用了巴特沃斯低通滤波器的系数。确保这些系数是正确的,以实现所需的滤波效果。

请仔细检查以上问题,并对代码进行相应的修改。如果问题仍然存在,请提供更多关于硬件配置和问题描述的信息,以便更详细地分析问题的原因。