信号基础:时域与频域的基本概念,采样定理入门

各位同学,欢迎来到第二讲。

上一章我们聊了为什么要做滤波,以及噪声从哪来。今天咱们要打一个真正的地基——时域与频域。说实话,我当年在学校学信号与系统时,也觉得这东西太抽象了,不就是一堆正弦波嘛。直到后来做项目,遇到一个死活滤不掉的50Hz工频干扰,才真正明白:不懂频域,你连噪声长什么样都看不清楚。

好,咱们开始。

1. 时域:我们最熟悉的视角

时域,说白了就是信号随时间怎么变

你拿示波器看一个波形,横轴是时间,纵轴是电压——这就是时域。我们平时采集到的传感器数据,比如温度、加速度、心率,都是时域信号。

举个例子:

// 一个简单的正弦波时域表示
// 幅度 A = 1.0,频率 f = 50Hz,采样率 fs = 1000Hz
for (int n = 0; n < 1000; n++) {
    float t = n / 1000.0f;          // 时间:0 ~ 1秒
    float x = 1.0f * sin(2 * PI * 50 * t);
    printf("%f\n", x);
}

这段代码输出的是50Hz正弦波在1秒内的采样点。你在纸上画出来,就是一条上下起伏的波浪线。嗯,这就是时域。

时域的核心问题:信号里有哪些频率成分?它们各自多大?——时域很难直接回答。

我在做电机振动监测时,采集到的加速度信号看起来乱糟糟的,根本分不清是机械共振还是电气噪声。时域波形像一锅粥。这时候,就得请出频域了。

2. 频域:换个角度看世界

频域看的是信号由哪些频率的正弦波组成

你想想看,一个复杂的信号,其实可以拆成很多个不同频率、不同幅度、不同相位的正弦波加起来。这就是傅里叶变换的核心思想——任何周期信号都可以分解为一系列正弦波的叠加

我习惯用一个比喻:时域是菜谱上的配料表,频域是告诉你每种调料放了多少克。你看一道菜的颜色(时域),很难猜出放了多少盐;但如果你看成分分析表(频域),一目了然。

来个直观的例子:

// 合成信号:50Hz + 120Hz 两个正弦波叠加
float signal[1000];
for (int n = 0; n < 1000; n++) {
    float t = n / 1000.0f;
    signal[n] = 1.0f * sin(2 * PI * 50 * t) 
              + 0.5f * sin(2 * PI * 120 * t);
}

这个信号在时域里看起来是两个正弦波叠加后的复杂波形。但如果你对它做FFT(快速傅里叶变换),频域里会清晰地看到两个尖峰:一个在50Hz处,幅度1.0;另一个在120Hz处,幅度0.5。

个人经验:我刚开始做嵌入式滤波时,总想着在时域里把噪声“抠”出来。后来发现,先看频域再设计滤波器,效率高十倍。因为频域告诉你:哪些频率是信号,哪些是噪声,一目了然。

3. 时域与频域的关系:一枚硬币的两面

时域和频域不是对立的,它们是同一个信号的两种描述方式。就像一个人有中文名和英文名,指的是同一个人。

转换工具就是傅里叶变换

  • 时域 → 频域:傅里叶变换(或FFT)
  • 频域 → 时域:逆傅里叶变换(IFFT)

我画了一张图,帮你理解这个关系:

时域 横轴:时间 (t) 纵轴:幅度 信号随时间变化 直观但频率信息隐藏 例:示波器波形 频域 横轴:频率 (Hz) 纵轴:幅度/功率 频率成分一目了然 适合分析噪声来源 例:频谱分析仪 FFT IFFT 时域和频域是同一信号的两种描述方式 通过傅里叶变换相互转换

这张图很关键。你每次做滤波,其实都是在做一件事:在频域里识别噪声,在时域里把它干掉

4. 采样定理:数字世界的基石

好,现在问题来了:我们嵌入式系统里处理的都是数字信号,也就是对模拟信号进行采样得到的。那么,采样频率该设多高?

这就引出了数字信号处理里最重要的一条规则——奈奎斯特采样定理

采样频率必须大于信号最高频率的两倍,否则会发生混叠(Aliasing)。

公式:fs > 2 * fmax

为什么会这样?我简单解释一下:

假设你有一个100Hz的正弦波,你用150Hz去采样。那么采样点看起来会像一个50Hz的波形——这就是混叠。高频信号“伪装”成了低频信号,你根本分不清。

我曾经踩过这个坑。做一个声音采集项目,麦克风能听到20kHz,我偷懒用了30kHz采样。结果录出来的声音里总有奇怪的“嗡嗡”声,怎么都滤不掉。后来一查,是20kHz附近的超声信号混叠到了10kHz附近,进入了可听频段。嗯,从那以后我再也不敢低于2.5倍采样了。

避坑指南:实际工程中,我建议采样率取信号最高频率的3~5倍。因为抗混叠滤波器不是理想砖墙,需要留过渡带。比如你要采集1kHz以内的信号,采样率至少设3kHz以上。

5. 一个完整的例子:从时域到频域

咱们用代码走一遍流程。假设你有一个传感器信号,包含50Hz的有用信号和200Hz的噪声:

#include <stdio.h>
#include <math.h>

#define FS 1000      // 采样率 1000Hz
#define N 1024       // 采样点数

int main() {
    float signal[N];
    float t;
    
    // 生成信号:50Hz有用信号 + 200Hz噪声
    for (int i = 0; i < N; i++) {
        t = (float)i / FS;
        signal[i] = 1.0f * sin(2 * PI * 50 * t)   // 有用信号
                  + 0.3f * sin(2 * PI * 200 * t); // 噪声
    }
    
    // 此时 signal[] 是时域数据
    // 你可以对它做FFT,得到频域数据
    // 在频域里你会看到:
    //   - 50Hz处有一个高峰(幅度1.0)
    //   - 200Hz处有一个小峰(幅度0.3)
    // 然后你就可以设计低通滤波器,把200Hz干掉
    
    return 0;
}

这个例子虽然简单,但包含了滤波的全部逻辑:时域采集 → 频域分析 → 设计滤波器 → 时域滤波

6. 本章知识体系总览

最后,我用一张图把今天的内容串起来:

信号基础:知识体系 信号分析基础 时域分析 频域分析 采样定理 信号随时间变化的规律 示波器、ADC采样 直观但频率信息隐藏 频率成分与幅度分布 FFT、频谱分析 识别噪声来源 fs > 2 * fmax 防止混叠(Aliasing) 工程建议:3~5倍 三者结合:时域采集 → 频域分析 → 设计滤波器

这张图把今天的内容串成了一个整体。你记住:时域是采集和滤波的战场,频域是分析和设计的参谋,采样定理是保证一切成立的底线

我的建议:初学者可以先不用深究FFT的数学细节。先学会看频谱图,能分辨出信号和噪声的频率范围,这就够了。数学推导可以后面慢慢补。

好,今天就到这儿。下一章咱们正式进入滤波器设计,从最简单的移动平均滤波开始,一步步搭建你自己的滤波工具箱。


公众号:蓝海资料掘金营,微信deep3321