ARM DSP 库下 FIR 的使用
ARM DSP 库下 FIR 的使用

ARM DSP 库下 FIR 的使用

记录 ARM DSP 库下 FIR 滤波器的使用,方便后续使用。

使用示例

ARM DSP 库下 FIR 滤波器的使用如下所示,FIR 以块的形式滤波,示例中的采样点数和滤波快大小可以是一样的。FIR 系数表由 Matlab 的 fdatool 工具导出,示例代码中的系数对应的参数为 500Hz 采样率、低通滤波、汉明窗、16 阶、截止频率为 10Hz。

#include "arm_math.h"

#define SAMPLES_NUM 1024 //采样点数
#define BLOCK_SIZE  8    //FIR 滤波块大小
#define NUM_TAPS    17   //滤波器系数个数

void SGM58031Task(void)
{
  //状态缓存,大小numTaps + blockSize - 1
  static float32_t s_arrFirStateF32[BLOCK_SIZE + NUM_TAPS - 1];

  //FIR 系数表
  const float32_t s_arrFirCoeffF32[NUM_TAPS] = {
    0.007925619371,  0.01188393217,  0.02299686521,  0.04016345739,  0.06104932353,
      0.08247635514,   0.1009953544,   0.1135294884,   0.1179592237,   0.1135294884,
      0.1009953544,  0.08247635514,  0.06104932353,  0.04016345739,  0.02299686521,
      0.01188393217, 0.007925619371
  };

  //其它静态变量
  static u8 s_iInitFlag = 1;
  static arm_fir_instance_f32 s_FirF32;
  static float32_t s_arrInput[SAMPLES_NUM];
  static float32_t s_arrOutput[SAMPLES_NUM];
  static u32 s_iSampleCnt = 0;

  //局部变量
  i16 adc;
  float32_t volt;
  u32 blockBeginAddr, i;

  //需要初始化
  if(0 != s_iInitFlag)
  {
    s_iInitFlag = 0;
    arm_fir_init_f32(&s_FirF32, NUM_TAPS, (float32_t*)&s_arrFirCoeffF32[0], &s_arrFirStateF32[0], BLOCK_SIZE);
    s_iSampleCnt = 0;
  }

  //获取转换结果
  adc = GetADC();

  volt = 3.3 * adc / 4096.0;

  //采样
  s_arrInput[s_iSampleCnt] = volt;
  s_iSampleCnt = (s_iSampleCnt + 1) % SAMPLES_NUM;

  //采够了一批数据
  if(0 == (s_iSampleCnt % BLOCK_SIZE))
  {
    //计算块起始地址
    if(0 == s_iSampleCnt)
    {
      blockBeginAddr = SAMPLES_NUM - BLOCK_SIZE;
    }
    else
    {
      blockBeginAddr = s_iSampleCnt - BLOCK_SIZE;
    }

    //滤波
    arm_fir_f32(&s_FirF32, s_arrInput + blockBeginAddr, s_arrOutput + blockBeginAddr, BLOCK_SIZE);

    //打印
    for(i = 0; i < BLOCK_SIZE; i++)
    {
      printf("%.3f\r\n", s_arrOutput[blockBeginAddr + i]);
    }
  }
}