news 2026/6/14 14:11:54

电赛入门必看:一文搞懂 FIR 滤波器与系数,大白话讲透原理与实操

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
电赛入门必看:一文搞懂 FIR 滤波器与系数,大白话讲透原理与实操

很多同学做电赛信号类题目(比如 2023 年 H 题信号分离装置)时,第一次接触 FIR 滤波器都会卡在「系数」上:

代码里这一长串数字到底是啥? 为什么注释说要替换成 MATLAB 生成的值? 我自己随便写几个数不行吗?

这篇文章全程用生活化类比 + 大白话,从底层逻辑到实操步骤讲透,零基础也能看懂,看完就能上手用。


一、先搞懂:FIR 滤波器到底是什么?

1. 一个生活化的类比

想象你手里有一杯混在一起的「细沙子」和「粗石子」,你想把两者分开,你会用什么? 答案很简单:筛子

  • 孔小的筛子:沙子漏下去,石子留在上面 → 留下细的、挡住粗的
  • 孔大的筛子:石子也能漏下去 → 粗的细的都过去

对应到电路的世界里:

  • 混合的沙子石子 = 混合在一起的不同频率的电信号(比如题目里的 50kHz 低频信号 + 100kHz 高频信号)
  • 筛子 =FIR 滤波器,专门用来「按频率分拣信号」
  • 细沙子 = 低频信号,粗石子 = 高频信号
  • 让低频通过、挡住高频 → 低通 FIR 滤波器
  • 让高频通过、挡住低频 → 高通 FIR 滤波器

2. 那「FIR 系数」又是什么?

筛子的过滤效果,完全由「孔的大小、孔的密度、筛子的层数」决定。 对应到 FIR 滤波器里,决定滤波效果的这整套「设计参数」,就是 FIR 系数

更直白一点:

1024 阶的 FIR 滤波器,就有 1024 个系数; 每个系数,对应一个「权重值」; 滤波器干活的本质,就是把历史采样值按权重加权求和。

3. 对应代码:它到底是怎么干活的?

原理非常简单,就是小学级别的「乘法 + 加法」,没有任何玄学。

你的 FPGA 每秒对信号采样很多次(比如 100MHz 就是每秒采 1 亿次),每采一个数就存起来,一共存最近的 1024 个采样值。 每来一个新数据,滤波器就做一件事:

把这 1024 个历史数值,每个都乘上自己对应的权重系数,再把所有结果加起来,最终的和就是「滤波后的输出值」。

举个最小的例子(3 阶 FIR,只有 3 个系数):

  • 滤波器系数:[0.25, 0.5, 0.25]
  • 最近 3 个采样值:[2, 4, 6]
  • 滤波结果 = 2×0.25 + 4×0.5 + 6×0.25 = 0.5 + 2 + 1.5 = 4

1024 阶的 FIR 逻辑完全一模一样,只是从 3 个数相加,变成了 1024 个数相加。 代码里的 BRAM 延迟线,就是用来存这 1024 个历史采样值的;MAC 乘累加单元,就是专门算「乘法 + 加法」的硬件模块。


二、为什么系数不能自己乱写,必须用 MATLAB 生成?

核心一句话:你想要的「刚好留住 50kHz、完美挡住 100kHz」这个效果,对应的 1024 个权重是多少,人工根本算不出来。

展开讲 3 个最实在的原因,每一个都对应电赛里的真实坑点:

1. 精度要求极高,差一点效果就崩

要做到「50kHz 信号几乎原样通过,80kHz 以上的信号削弱 100 倍」,这 1024 个系数的取值是非常精密的。 就像你要做一个筛子,刚好留住 0.05mm 的沙子、挡住 0.1mm 的石子,孔的大小、密度、排列都要精准计算,不是随手画几个孔就能用的。

系数差一点点,就会出现:

  • 该保留的信号被衰减,输出幅值变小
  • 该滤掉的信号没挡住,分离不干净
  • 严重的时候甚至完全分不出两路信号

2. 数量太多,人工根本算不完

1024 个系数,每个都是精确的小数,还要满足「左右严格对称」的要求(这样输出波形才不会变形)。 人工算 1024 个精准的数,算到明年也算不对,还很容易算错。

MATLAB 里有现成的专业工具函数(比如fir1),你只要告诉它 3 件事:

  1. 你的采样率是多少(比如 100MHz)
  2. 截止频率是多少(比如 60kHz 以下通过)
  3. 滤波器要多少阶(比如 1024 阶)

它 1 秒钟就能算出 1024 个精准的系数,还能直接生成你需要的整数格式,复制粘贴就能用。这是电子行业的标准做法,不是什么 “偷懒技巧”。

3. 没有通用系数,参数一变全得换

FIR 系数不是万能的,它和你的硬件参数是强绑定的。只要下面任意一个参数变了,所有系数都要重新生成:

  • 采样率变了(比如从 100MHz 改成 50MHz)
  • 截止频率变了(比如从 60kHz 改成 70kHz)
  • 滤波器阶数变了(比如从 1024 阶改成 512 阶)

不存在一套 “拿过来就能用在所有项目里” 的通用系数,必须根据你的实际电路参数,用工具生成对应的值。


三、为什么代码里的系数是 “占位符”?

很多网上的示例代码,只中间会写前十几个和最后几个系数,注释一句「由 MATLAB 生成」,不是作者不想写全,原因很现实:

  1. 太长了:1024 个系数全写出来,要占几十上百行代码,示例代码会非常臃肿,影响阅读;
  2. 不通用:作者的采样率、截止频率和你的硬件不一定匹配,全写给你也用不了。

⚠️重点提醒:直接用占位符代码编译上板,一定会出问题。 相当于一个筛子大部分孔的大小都是错的,根本滤不干净,轻则分离效果差,重则完全看不到分离后的波形,基本分都拿不到。


四、高频专业名词大白话对照表

碰到术语不用慌,下面这张表可以直接存下来对照看:

表格

专业名词大白话解释
阶数(如 1024 阶)系数的总个数,相当于筛子的层数。阶数越高,筛得越干净,但运算量越大、占用资源越多。
低通 / 高通 FIR低通 = 低频信号通过、高频挡住;高通 = 高频信号通过、低频挡住。
线性相位所有频率的信号通过滤波器后,延迟时间完全一样。最大的好处是波形不会变形,正弦波进去还是正弦波。要实现这点,系数必须左右严格对称,MATLAB 生成的系数天然满足。
Q1.15 定点格式FPGA 不擅长算小数,所以把所有小数放大 32768 倍,转成整数来运算,最后再缩回去。比如 0.5 就存成 16384。
窗函数(汉宁窗、汉明窗等)设计滤波器的不同「配方」。不同配方效果不同:有的筛得干净但过渡慢,有的边缘锐利但旁瓣大,电赛常规题目用汉宁窗就足够。
通带 / 阻带通带 = 能顺利通过的频率范围;阻带 = 被大幅削弱、挡住的频率范围。
阻带衰减能把不需要的信号削弱多少倍,比如 40dB 就是削弱 100 倍,60dB 就是削弱 1000 倍。
BRAM 延迟线FPGA 里的一块专用高速内存,专门用来存最近的 1024 个采样值,方便每次拿出来乘系数相加。
MAC 乘累加FPGA 里专门算「乘法 + 加法」的硬件单元,FIR 滤波的核心运算全靠它。

五、电赛实操:FIR 滤波器完整落地步骤

讲完原理,给你一套电赛里直接能用的标准流程,照着做就能把 FIR 滤波器跑起来:

步骤 1:确定你的设计指标

先根据题目要求定参数,以分离 50kHz 和 100kHz 为例:

  • 系统采样率:100MHz
  • 低通滤波器:通带截止 60kHz,阻带起始 80kHz
  • 高通滤波器:通带起始 90kHz,阻带截止 70kHz
  • 阶数:1024 阶
  • 窗函数:汉宁窗

步骤 2:用 MATLAB 生成系数

把下面的脚本复制到 MATLAB 里运行,一键就能生成 Verilog 能用的系数文件:

matlab

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 电赛FIR滤波器系数生成脚本 % 输出16位Q1.15定点格式,可直接复制到Verilog代码 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% clear; clc; %% 1. 设置参数 Fs = 100e6; % 采样率 100MHz N = 1024; % 滤波器阶数 F_pass_low = 60e3; % 低通通带截止 60kHz %% 2. 设计低通滤波器并转定点 h_low = fir1(N-1, F_pass_low/(Fs/2), 'low', hann(N)); h_low_fix = round(h_low * 32767); % 转16位Q1.15整数 %% 3. 输出Verilog格式系数到文件 fid = fopen('coeff_low.txt', 'w'); for i = 1:N val = h_low_fix(i); if val >= 0 fprintf(fid, '16''d%d,', val); else fprintf(fid, '-16''d%d,', abs(val)); end if mod(i, 8) == 0 fprintf(fid, '\n'); end end fclose(fid); %% 4. 查看幅频响应,验证效果 fvtool(h_low, 1, 'Fs', Fs); title('低通FIR滤波器幅频响应'); disp('系数生成完成,已保存为 coeff_low.txt');

运行后会弹出一个窗口,显示滤波器的幅频曲线,你可以直观看到通带平不平、阻带衰减够不够。

步骤 3:把系数替换进 Verilog 代码

打开生成的coeff_low.txt,把里面的内容全选复制,替换掉代码里系数数组的占位内容,高通滤波器同理操作。

步骤 4:上板验证

  1. 先输入单频信号,用示波器测输出幅值,确认通带内衰减小、阻带内衰减大;
  2. 再输入混合信号,观测分离效果,确认两路信号无明显串扰。

六、电赛常见踩坑提醒

  1. 不要随便改单个系数:改一个就破坏了整体对称性,线性相位会消失,输出波形会失真。
  2. 注意采样率匹配:MATLAB 里填的采样率,必须和 FPGA 实际的采样时钟一模一样,差一点截止频率就会偏。
  3. 防止溢出:两路信号相加、乘累加后都要注意位宽,要么加饱和截断,要么扩展位宽,避免波形削顶。
  4. 阶数不是越高越好:阶数越高延迟越大,资源占用也越多,满足题目要求即可,不用盲目堆高阶。

最后总结

  • FIR 滤波器本质就是一个「按频率分拣信号的电子筛子」;
  • FIR 系数就是这个筛子的「设计图纸」,决定了滤波效果的好坏;
  • 系数数量多、精度要求高,人工算不现实,用 MATLAB 生成是行业标准做法;
  • 电赛落地流程:定指标 → MATLAB 生成系数 → 替换进代码 → 上板验证。

FIR 滤波器是电赛信号题的基础核心,搞懂原理再动手,比盲目抄代码调 bug 效率高得多。

我接着用「筛沙子」的类比,把这些设计参数一个个掰开讲,每个都讲清:是什么、对应筛子的啥属性、改了会有什么影响,全程不用公式,看完就知道为什么要这么设。

这些参数本质上就是你给 MATLAB 下的「定制筛子的规格要求」,你说清楚要求,工具才能给你生成刚好能用的系数。


一、逐个参数大白话拆解

1. 采样率(Fs)

大白话定义:FPGA 每秒对输入信号采集多少个数据点,单位是 Hz。

  • 100MHz 采样率 = 每秒采 1 亿个点
  • 8.192MHz 采样率 = 每秒采 819.2 万个点

筛子类比:相当于你每秒舀多少勺沙子过筛。舀得越快,单位时间处理的量越大。

为什么重要

  • 它决定了你能处理的最高信号频率(奈奎斯特极限:最高只能处理采样率一半的频率)。100MHz 采样率,最多只能处理 50MHz 以内的信号,超过就会混叠失真。
  • 设计系数和实际硬件必须严格一致。你 MATLAB 里填 100MHz 生成的系数,放到 50MHz 的 FPGA 上,截止频率会直接偏一半,滤波器完全不准。

2. 滤波器阶数(N,也叫抽头数)

大白话定义:滤波器一共有多少个系数,也就是加权求和的时候,要拿多少个历史数据来算。

  • 1024 阶 = 1024 个系数 = 每次算结果要乘 1024 次、加 1024 次

筛子类比:筛子的层数。一层筛不干净,就叠十层、一百层。层数越多,筛得越干净,但筛子越沉、筛得越慢。

改了会怎样

  • 阶数越高 → 筛选的边界越锐利(过渡带越窄)、拦得越干净(阻带衰减越大)
  • 阶数越高 → 占用 FPGA 资源越多(乘法器、内存都要更多)、信号延迟越大
  • 电赛里够用就行,不用盲目堆高阶,1024 阶应对基础题完全足够。

3. 通带截止频率(Fpass)

大白话定义:能几乎原样通过、几乎不被削弱的频率边界。

  • 低通滤波器:低于这个频率的信号,都能顺利通过
  • 高通滤波器:高于这个频率的信号,都能顺利通过

筛子类比:筛子的标准孔径。小于孔径的沙子,全能漏下去,几乎不被拦住。

举例子: 低通设置通带截止 60kHz → 50kHz 的信号在通带里,输出幅值和输入几乎一样,损失很小。


4. 阻带起始频率(Fstop)

大白话定义:从这个频率开始,信号会被大幅削弱,基本过不去。

  • 低通滤波器:高于这个频率的信号,都会被大幅度衰减

筛子类比:肯定拦得住的石子尺寸。大于这个尺寸的石子,基本全被扣在筛子上,漏不下去。

举例子: 低通设置阻带起始 80kHz → 100kHz 的信号在阻带里,会被削弱几十上百倍,基本被滤干净。


5. 过渡带(Transition Band)

大白话定义:通带和阻带中间的那段频率区间,信号是慢慢被削弱的,不是一刀切。

  • 比如通带 60kHz、阻带 80kHz,过渡带就是 60kHz ~ 80kHz 这 20kHz 的区间

筛子类比:筛孔不是 100% 均匀的,总有一些不大不小的颗粒,会漏下去一部分、拦住一部分,不是全过也不是全拦。

重点常识: 现实里不存在「60kHz 全过、60.001kHz 全挡」的理想滤波器,所有真实滤波器都有过渡带。

  • 阶数越高,过渡带越窄,筛选边界越锐利
  • 阶数越低,过渡带越宽,边界越模糊

这也是为什么题目要分离 50kHz 和 100kHz,我们不把截止设成 50kHz:要把 50kHz 放在通带里、100kHz 放在阻带里,中间留够过渡带的空间,不然 50kHz 刚好落在过渡带上,会被衰减。


6. 阻带衰减

大白话定义:阻带里的信号,会被削弱到原来的多少分之一,单位是 dB(分贝)。

  • 不用记公式,记住常用值就行:
    • 20dB = 削弱到 1/10
    • 40dB = 削弱到 1/100
    • 60dB = 削弱到 1/1000
  • 数字越大,衰减越狠,滤得越干净

筛子类比:筛子拦石子的干净程度。40dB 就是 100 颗石子里只能漏下去 1 颗;60dB 就是 1000 颗里才漏 1 颗。

电赛参考:一般 40dB 以上就够用,分离出来的两路信号互相串扰很小,示波器上基本看不到干扰。


7. 通带纹波

大白话定义:通带里的信号,幅值波动有多大,也就是通带平不平。

  • 纹波小 = 通带里所有频率的增益几乎一样,输出幅值稳定
  • 纹波大 = 通带里有的频率增益高、有的低,信号会变形

筛子类比:合格的筛子,所有小于孔径的沙子都应该漏得一样快,不能有的漏得快、有的漏得慢。

电赛参考:用窗函数法设计的 FIR,通带纹波本身就很小,比如汉宁窗的纹波可以忽略,基础题基本不用操心这个参数。


8. 窗函数(Window Function)

大白话定义:设计滤波器的「数学配方 / 工艺」,不同的窗函数,做出来的滤波器特性不一样。

筛子类比:不同的筛子编织工艺。

  • 有的工艺做出来的筛子,边缘过渡快,但拦得不够干净
  • 有的工艺拦得特别干净,但边缘过渡慢、边界模糊

常见的几种窗函数对比(电赛够用版)

表格

窗函数阻带衰减过渡带特点
矩形窗最差(21dB)最窄边界最锐利,但拦得最不干净,一般不用
汉宁窗中等(44dB)中等均衡性最好,电赛最常用,不容易出错
汉明窗较好(53dB)略宽于汉宁比汉宁窗干净一点,过渡差不多
布莱克曼窗很好(74dB)最宽滤得最干净,但相同阶数下过渡带最宽

电赛选型建议:无脑选汉宁窗就行,均衡、好调试、不容易出问题。


二、参数之间的「此消彼长」关系

设计滤波器不是参数越极端越好,它们之间是互相约束的,核心记住 3 条:

  1. 相同阶数下:要阻带衰减越大,过渡带就越宽;要过渡带越窄,阻带衰减就越小。
  2. 既要窄过渡带、又要大衰减:只能提高滤波器阶数,代价是占用更多资源、延迟变大。
  3. 采样率越高:相同阶数下,过渡带的绝对宽度就越大(比如 100MHz 下过渡带 20kHz,换成 50MHz 下过渡带就只有 10kHz)。

三、结合电赛 H 题,完整的参数选型逻辑

给你捋一遍为什么常规方案会选这些参数,你就懂设计思路了:

  1. 需求:分离 50kHz 和 100kHz 的混合信号
  2. 选采样率:FPGA 系统时钟 100MHz,直接用 100MHz 采样,简单省事,也远高于信号频率的 2 倍,不会混叠。
  3. 定通带和阻带
    • 低通:要留住 50kHz,所以通带截止设 60kHz(留 10kHz 余量);要挡住 100kHz,所以阻带起始设 80kHz(留 20kHz 余量)。过渡带 20kHz。
    • 高通:反过来,通带起始 90kHz,阻带截止 70kHz。
  4. 选阶数:1024 阶汉宁窗,刚好能在 20kHz 过渡带里做到 40dB 以上的衰减,资源占用也不高,性价比最高。
  5. 选窗函数:汉宁窗,均衡稳定,调试简单。

最后总结

这些参数本质就是「你想要什么样的筛子」的完整描述:

  • 采样率 = 处理速度
  • 阶数 = 筛子层数
  • 通带 / 阻带 = 孔的大小、拦石子的尺寸
  • 窗函数 = 制作工艺

你把这些要求告诉 MATLAB,它就会算出对应的 1024 个系数,你粘进代码里,滤波器就能按你的要求干活了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/14 14:04:56

MPC823硬件调试:程序流追踪与硬件断点实战解析

1. 项目概述:深入MPC823的调试核心 在嵌入式开发,尤其是涉及PowerPC这类高性能处理器的项目中,调试的深度和效率直接决定了项目的成败。当你的代码在几十兆赫兹甚至上百兆赫兹的时钟下飞驰,传统的“打印日志”或“单步执行”调试手…

作者头像 李华
网站建设 2026/6/14 14:01:57

PowerPC MPC823嵌入式开发:原子操作、中断与性能优化实战

1. 项目概述与核心价值在嵌入式系统和微处理器开发领域,尤其是在通信、工控和汽车电子这些对实时性和可靠性要求极高的场景里,理解处理器内核的“脾气秉性”至关重要。这不仅仅是知道某个寄存器怎么配置,而是要深入到指令执行、内存访问和异常…

作者头像 李华
网站建设 2026/6/14 14:00:23

MPC8323E USB控制器TxBD与TrBD机制详解:从DMA零拷贝到驱动实战

1. 项目概述:从CPU的“搬运工”到数据流的“交通指挥官”在嵌入式系统开发,尤其是涉及高速数据交换的领域,比如网络通信、音视频采集或者我们今天要深入探讨的USB通信,有一个概念是绕不开的,那就是缓冲区描述符。如果你…

作者头像 李华
网站建设 2026/6/14 13:58:23

完整老旧Mac升级实战:让过时设备运行最新系统

完整老旧Mac升级实战:让过时设备运行最新系统 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否还在为手中的老旧Mac无法升级到最新macOS系统…

作者头像 李华
网站建设 2026/6/14 13:57:19

如何快速掌握PPTist:免费在线演示工具的完整指南

如何快速掌握PPTist:免费在线演示工具的完整指南 【免费下载链接】PPTist PowerPoint-ist(/pauəpɔintist/), An online presentation application that replicates most of the commonly used features of MS PowerPoint, allowing for the…

作者头像 李华