MATLAB FIR数字滤波器设计(基于stm32使用matlab)——matlab设置参数设置详解

一、问题引入

在进行数字信号处理时,我遇到了一个困惑:对于同一个100Hz的信号,使用不同的采样率采集会得到不同数量的采样点。那么,FIR滤波器是如何处理这种情况的?具体来说:

  • 如果使用1MHz采样率采集100Hz信号:

       1秒钟采集1,000,000个点

       一个周期采集10,000个点

  • 如果使用10kHz采样率采集100Hz信号:

       1秒钟采集10,000个点

       一个周期采集100个点

这就引发了几个关键问题:

  • 不同采样率下的数据如何影响滤波效果?
  • 如何选择合适的采样率?
  • FIR滤波器的参数应该如何设置?

二、相关参数

1. 归一化频率

归一化频率是将实际频率相对于奈奎斯特频率(采样频率的一半)进行标准化的结果:

归一化频率 = 实际频率/(采样频率/2)

- 取值范围:0~1

  • 0对应直流分量(0Hz)
  • 1对应奈奎斯特频率(Fs/2)

这里比如说我要用1000hz的频率去采信号,希望对这个信号100hz以上的频率进行滤波。设计一个这样的低通滤波器就需要计算我们的归一化截止频率

这里的归一化截止频率就是100/(1000/2)=0.2

打开matlab 输入fdatool,即可进入数字滤波器设置界面


 

图片中的wc((Normalized Cutoff Frequency):归一化截止频率)就是归一化截止频率。

当然除了使用归一化截止频率也可以直接使用

设置fs( (Sampling Frequency):采样频率),fc((Cutoff Frequency):截止频率)

这里点击频率设定里的单位,可以看到

这里就可以选择归一化,或者直接设置采样频率fs,截止频率fc

根据需要选择采样频率,设置截止频率,或计算好归一化系数后点击生成滤波器即可

2.fir滤波器的阶数

典型阶数选择
| 阶数范围 | 特点 | 应用场景 |
|---------|------|---------|
| 20-40 | 资源少,延迟小 | 简单滤波 |
| 40-80 | 性能资源平衡 | 常用范围 |
| 80-256 | 窄过渡带,延迟大 | 高性能要求 |

三、将数字滤波器导出为C头文件代码

点击左上角的编辑,点击转换结构,会出现

选择直接星FIR点击确定

设置好相关参数后,点击设计滤波器

 设计完成后点击左上角的目标,选择生成c头文件

保存即可

打开.h文件可以看到生成的代码

/*
 * Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool
 * Generated by MATLAB(R) 24.1 and Signal Processing Toolbox 24.1.
 * Generated on: 03-Mar-2025 17:34:57
 */

/*
 * 离散时间 FIR 滤波器(实数)
 * ----------------
 * 滤波器结构  : 直接型 FIR 转置
 * 滤波器长度  : 81
 * 稳定     : 是
 * 线性相位   : 是 (Type 1)
 */

/* General type conversion for MATLAB generated C-code  */
#include "tmwtypes.h"
/* 
 * Expected path to tmwtypes.h 
 * D:\ranjian\Matlab2024a\matlab\extern\include\tmwtypes.h 
 */
/*
 * Warning - Filter coefficients were truncated to fit specified data type.  
 *   The resulting response may not match generated theoretical response.
 *   Use the Filter Design & Analysis Tool to design accurate
 *   single-precision filter coefficients.
 */
const int BL = 81;
const real32_T B[81] = {
  -1.248479932e-18,-0.0006325327558,-0.000422134588,0.0004692059301,0.0008627952193,
  -1.794930437e-18,-0.001159708714,-0.0008386048721,0.0009822372813, 0.001859114505,
  -3.351089814e-18,-0.002520596841,-0.001803148654, 0.002078216989, 0.003859200282,
  -5.680047021e-18, -0.00502270367,-0.003522193991, 0.003983821254, 0.007270423695,
  -8.427239153e-18,-0.009186808951,-0.006366339978, 0.007131042425,   0.0129177114,
  -1.11744317e-17, -0.01620636135, -0.01124048699,  0.01264583599,  0.02310281433,
  -1.350338849e-17, -0.02995507978, -0.02135082521,  0.02493774705,  0.04796636105,
  -1.505954766e-17, -0.07404191047, -0.06162585691,  0.09309853613,    0.302559495,
      0.400341481,    0.302559495,  0.09309853613, -0.06162585691, -0.07404191047,
  -1.505954766e-17,  0.04796636105,  0.02493774705, -0.02135082521, -0.02995507978,
  -1.350338849e-17,  0.02310281433,  0.01264583599, -0.01124048699, -0.01620636135,
  -1.11744317e-17,   0.0129177114, 0.007131042425,-0.006366339978,-0.009186808951,
  -8.427239153e-18, 0.007270423695, 0.003983821254,-0.003522193991, -0.00502270367,
  -5.680047021e-18, 0.003859200282, 0.002078216989,-0.001803148654,-0.002520596841,
  -3.351089814e-18, 0.001859114505,0.0009822372813,-0.0008386048721,-0.001159708714,
  -1.794930437e-18,0.0008627952193,0.0004692059301,-0.000422134588,-0.0006325327558,
  -1.248479932e-18
};

这样就成功将它导出了

四、设计实例,将输入的矩形波滤波成为一个方波

这里我们使用1Mhz的采样频率,去采集一个矩形波。

将矩形波滤为一个正弦波,对矩形波做fft可得其基波及谐波,如以1Mhz采样,归一化截止频率为0.4,则对应频率为200Khz,则输入正弦波的频率的基波要<<200K,3次谐波的频率要大于200K,及输入频率在66.6K到200K时可以将它滤波为正弦波

1. 矩形波频谱特性

基波:50kHz(需要保留)
3次谐波:150kHz
5次谐波:250kHz
7次谐波:350kHz

2. 截止频率选择

Fs = 1e6;           % 采样频率1MHz
Fc = 200e3;         % 截止频率200kHz
wc = Fc/(Fs/2);     % 归一化截止频率 = 0.4

3.生成滤波器数据

这里同上,先生成滤波器数据备用。

4.利用cubemx生成keil工程

adc配置

这里选择一个adc通道,配置为单端输入

选择分辨率为12位

这里使用定时器触发adc采集精准控制采样时间

adcDMA设置

添加adcdma,设置为normal

定时器配置

使用内部时钟

配置分频系数

这里我的主时钟是80M,80-1,采样频率为1Mhz

开启自动重装载和触发事件

到这里定时器配置完成

串口配置

串口这里配置为全双工,其他参数默认即可

DSP库添加

点击software packs

点击select components

勾选dsplibrary

然后在middleware and sorftware packs选择x-cube-algobuild

勾选dsp

然后生成工程代码

keil代码

在define添加这段代码

,ARM_MATH_CM4,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING

串口重回定向(记得添加stdio.h标准输入输出输出库使用printf)

勾选微库

编写fir.h文件

// fir.h
#ifndef __FIR_H
#define __FIR_H

#include "main.h"
#include "arm_math.h"
#include "stdio.h"
#include "stdlib.h"

void firtest(void);

#endif

编写fir.c文件 

// fir.c
#include "fir.h"

/* 滤波器参数说明
 * 采样频率: 1MHz
 * 截止频率: 200kHz (归一化频率0.4)
 * 滤波器长度: 81 (80阶)
 * 窗函数: 汉宁窗
 * 结构: 直接型FIR转置
 */

const int BL = 81;  // 滤波器长度
float32_t pCoeffs[81] = {
    // MATLAB生成的滤波器系数
    -1.248479932e-18,-0.0006325327558,-0.000422134588,
    // ... 省略中间系数 ...
    -0.000422134588,-0.0006325327558,-1.248479932e-18
};

// 全局变量定义
__IO uint8_t adcok = 0;                    // ADC完成标志
uint16_t numTaps = 81;                     // 滤波器系数个数
float32_t pState[336] = {0.0f};            // 状态缓存(numTaps + blockSize - 1)
uint32_t blockSize = 256;                  // 数据块大小
float32_t inbuf[256] = {0.0f};            // 输入缓存
uint16_t adcbuf[256] = {0};               // ADC数据缓存
float32_t outbuf[256] = {0.0f};           // 输出缓存
arm_fir_instance_f32 * S;                  // FIR实例指针

void firtest(void)
{
    // 1. 延时等待系统稳定
    HAL_Delay(3000);
    
    // 2. 启动定时器和ADC采样
    HAL_TIM_Base_Start_IT(&htim3);
    HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcbuf, 256);
    while(adcok);  // 等待采样完成
    
    // 3. 数据格式转换(ADC原始值转换为电压值)
    for(int i = 0; i < 256; i++) {
        inbuf[i] = adcbuf[i]/4096.0f*3.3f;
        printf("%f\n", inbuf[i]);  // 打印输入数据
    }
    
    // 4. 分配FIR实例内存
    S = (arm_fir_instance_f32 *)malloc(sizeof(arm_fir_instance_f32));
    if (S == NULL) {
        printf("Memory allocation error\n");
        return;
    }
    
    printf("\n\n\n\n\n\n\n\n\n");
    
    // 5. 初始化并执行滤波
    arm_fir_init_f32(S, numTaps, pCoeffs, pState, blockSize);
    arm_fir_f32(S, inbuf, outbuf, blockSize);
    
    // 6. 输出滤波结果
    for(int i = 0; i < 256; i++) {
        printf("%f\n", outbuf[i]);
    }
    
    // 7. 释放资源
    free(S);
    S = NULL;
}

参数说明

  • 滤波器设计参数:
  • 采样频率:1MHz
  • 截止频率:200kHz
  • 归一化截止频率:0.4
  • 阶数:80(81个系数)
  • 窗函数:汉宁窗
  • 缓存大小设计:
  • 数据块大小:256点
  • 状态缓存:336点(numTaps + blockSize - 1)

打印串口,数据可视化

将数据复制粘贴到excel表格

选中一列数据之后点击插入,选择折线图

滤波效果

这样就实现了滤波操作

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值