SAR ADC(逐次逼近型模数转换器)以其低功耗、结构简单、采样延迟短等优点在很多应用中广泛使用,尤其是在需要中等采样率(~几十kHz到几MHz)且低延迟的场合。然而,它对输入信号带宽内的噪声频谱的处理能力有其自身的特性与局限,本篇文章就试图使用理论和代码模拟的方法说明其中的细节。

文章的起因是因为之前写LTC2005,下面一位ADI的大哥提出的问题,这段日子研究了下,可以做个回答。

另外我发现ADI有个岗位叫PAE是:支持现场应用工程师(FAE)和远程应用团队,协助解决技术难题,提出产品/应用改进建议,好像也会负责FAE和内部研发之间的工作,就是做更深层次的支持,我们平时看见的文章就是这些写出来的,这里模拟一下写一篇看看(😂)。

ADI 官方书籍:Analog-Digital Conversion 3.125是今天的图。

先说结论:

SAR ADC 对带内噪声频谱的处理特性总结:实时性好,适合快速采样 , 无内建带内噪声抑制或滤波能力,可外加模拟滤波器抑制带外噪声, 对低频噪声(如 1/f 噪声)不敏感 ,可通过平均提升带内噪声鲁棒性。

SAR ADC 的采样和噪声频谱处理机制

1. 采样-保持机制导致等效带宽有限

SAR ADC 通过采样保持电路(S/H)对输入模拟信号进行瞬时采样,该过程类似于一个 带宽有限的开关采样网络。其行为可以理解为一个周期性抽样+带宽限制系统,具体有以下影响:

项目
说明
采样频率 fs
决定了奈奎斯特带宽(fs/2)
采样瞬间
仅对信号在采样瞬间的值敏感,无积分过程
无抗混叠能力
不像Σ-Δ ADC那样具备内建滤波特性,噪声/高频信号需要靠外部模拟滤波抑制
采样时间有限
采样时间(Ts)短,电荷注入与动态输入电流可能产生瞬态误差或高频耦合噪声

带宽内噪声处理能力对比

特性
SAR ADC
Σ-Δ ADC
输入信号带宽
通常接近采样率的一半
带宽较窄(由过采样和滤波器决定)
带内噪声积分能力
无积分,以瞬时值为准
有积分,带内噪声被平滑
抗带外噪声能力
差,需外部抗混叠滤波器
好,内置滤波器抑制带外频率
带内噪声能量转化机制
若噪声能量集中在 fs/2 以内,则无法通过 ADC 本身滤除
能通过 OSR+滤波器抑制带内噪声
实时性
极好,转换时间短
差,延迟大

对带内噪声的影响

因为采样瞬间的噪声会直接被转换进去,无法被平均或抑制,这对带宽内存在的 1/f 噪声、热噪声是个问题。也没有类似 Σ-Δ 架构中的噪声整形器或数字滤波器来处理带外噪声。

如果系统中带内噪声对性能影响较大,而实时性要求又不是特别极限,可以考虑以下两种方案:

SAR + 前置模拟低通滤波器 + 数字平均处理(也是后文中重点要使用的方法)

若允许延迟,改用 Σ-Δ ADC 或混合架构(如 LTC2500、MAX11905 等)

然后就出现了这样俩者结合的类型
美信,也被收购了

全差分输入 + 高精度 20-bit;高速 SAR 架构,无 pipeline 延迟

SAR ADC 的量化噪声建模

1.1 理想 ADC 的量化误差

假设 SAR ADC 有  位分辨率,满量程电压范围为 ,则其量化步长为:

理想情况下,量化误差服从均匀分布

则其均方根(RMS)为:


1.2 量化噪声功率谱密度(PSD)

若采样频率为 ,量化噪声在 0 到  范围均匀分布,则其功率谱密度为白噪声


五、带宽内噪声积分与 SNR 计算

设系统信号带宽为 ,我们希望知道在这个频段内的量化噪声功率:

而满量程信号功率为:

因此,带宽内 SNR(信噪比)为

代入 ,得到:


结论 1:

SAR ADC 的 SNR(在信号带宽内)依赖于过采样比。SNR 可以通过提高采样率来增强(即“过采样增益”):

其中 OSR 为 Over Sampling Ratio,


带宽内总噪声与热噪声、1/f 噪声的叠加

实际模拟前端存在三种噪声:

  1. 热噪声:白噪声,PSD 为常数 
  2. 1/f 噪声:低频增强型,PSD 形式为 
  3. 量化噪声:如前所述,带宽内为平坦噪声

带内噪声总功率为(信号带宽为 ):

热噪声噪声量化噪声

可以看到:

SAR ADC 无法区分/抑制上述噪声;

积分型 ADC( Σ-Δ)可以通过噪声整形将低频噪声“削弱”


SAR和 Σ-Δ ADC 的频谱比较(数学对比)

项目
SAR ADC(非积分)
Σ-Δ ADC(积分+整形)
噪声 PSD 
常数 (白噪声)
噪声整形为 (高频集中)
带宽内噪声能量

(大大减小)
SNR 提升
每 4×OSR 提升 6 dB
每 4×OSR 提升 15 dB(2阶整形)

结论(数学角度)

结论项
数学描述
解释
实时性
SAR ADC 转换时间 = 
适合快速采样控制
带内噪声 PSD
白噪声特性,带内无法抑制
SNR 与 OSR
可通过过采样略提升 SNR
噪声积分
SAR 无整形,ΣΔ 有降噪特性

很自然的,我们想加滤波器来改善这一现象,在 SAR ADC 前端加入一个 RC 低通滤波器(抗混叠滤波器) 后,它将如何影响输入信号的噪声功率谱密度以及总噪声功率(积分值)?下面的部分将会给出答案。


系统建模:RC 滤波器 + SAR ADC

设输入为某模拟信号  与其叠加噪声 ,系统结构如下:

噪声源 + 信号源 ──> RC 滤波器 ──> S/H + SAR ADC

其中 RC 滤波器为一阶低通:

电阻 R、 电容 C,截止频率(–3 dB)为:

其幅频响应为:


输入噪声 PSD 及其通过滤波器后的 PSD

2.1 白噪声输入 

这是热噪声模型的常见近似,如运算放大器输出、采样保持器输入电流热噪声等。

2.2 RC 滤波器输出 PSD:

滤波器将输入的 PSD 乘以传递函数的幅值平方:

这个谱型就是一个Lorentzian 分布(洛伦兹谱),在频率域中呈钟形衰减。

高斯分布+柯西-洛伦兹分布+三种光谱线型函数(洛伦兹线型函数+多普勒[高斯]线型函数+vogit 线型函数)

噪声功率积分(总噪声)

总噪声功率为 PSD 的积分值,即

做变量代换:

积分上限变为 ,则:


总结:RC 滤波器后的总噪声功率为


特殊情况分析:

**当 **(常见情况):

这说明 RC 滤波器将白噪声带宽从无限降低为一个有限带宽  的过程,从而使噪声功率不再随带宽无限上升。


结合 ADC 采样过程

一旦经过 RC 滤波,ADC 的采样将等效于在 PSD 上施加一个周期抽样窗。带外频率(> fs/2)的信号会混叠进来,因此:

RC 滤波器同时也充当了 抗混叠滤波器(Anti-Aliasing Filter),若滤波器的截止频率 ,则混叠噪声将大幅减少。


对于 1/f 噪声源

如果输入噪声为 ,则:

这个积分可用换元积分解成两个区间,近似为:

  1. 低频区域)近似为 ,呈对数增长
  2. 高频区域)近似为 ,呈快速衰减

最终噪声功率变为:常数 → 滤波器可显著压缩 1/f 噪声高频拖尾


总结一下以上的计算结果

项目
数学表达式
含义与结论
白噪声经过 RC 滤波后 PSD
滤除高频成分
白噪声总噪声功率(积分)
滤波器抑制总功率
高采样率下的极限值
白噪声积分有限
对 1/f 噪声谱的压缩作用
积分约为 
RC 抑制 1/f 高频扩展

在前面数学推导的基础上,我们从实际工程设计角度出发,再讨论一下:

SAR ADC 前端 RC 滤波器的设计建议,特别是:如何根据采样频率  合理选择 RC 常数;同时还要兼顾 抗混叠、噪声抑制、信号保真度 三个指标。

RC 滤波

RC 一阶低通滤波器的截止频率为:

它会决定信号和噪声的通过范围,因此需要针对抗混叠 + 保信号进行平衡设计。


设计目标权衡

设计目标
要求
说明
抗混叠能力
减少混叠进带内的高频干扰与噪声
信号保真度
不应削弱有用信号
噪声抑制能力

 越低,积分总噪声越小
白噪声 PSD 经 RC 滤波后能量减少
驱动能力匹配

 不宜太大,否则影响 ADC 输入动态响应
通常 R < 10 kΩ(防止带宽限制和 RC 时间太长)

这里使用一个经验设计流程,假设系统信号最大频率为 ,ADC 采样频率为 

推荐设计公式:

然后用截止频率计算 RC 值:


对于抗混叠(aliasing):

由于奈奎斯特采样理论要求:

推荐设置为:

这是为了保证 ADC 带宽内噪声主要落在 0 ~ ,带外快速衰减。

结合起来,推荐区间为:


以 100kHz 采样为例

参数
数值
采样率 
100 kHz
奈奎斯特频率 
50 kHz
信号最大频率 
20 kHz
推荐截止频率 
25 ~ 33 kHz
得到 RC 值

 到 

若选 ,则:

在最后的设计阶段需要选用无源器件搭建滤波器,需要考虑热噪音和功耗以及诸多非线形的问题,比如带宽等。

选项
建议
R
1~10 kΩ,避免过高引起响应延迟和热噪声提升
C
适配 R 选择,构成所需截止频率
f_c
带宽裕量
至少留 20~30% 的余量避免信号被衰减
实际测试
用 Bode plot 测试 RC 滤波器,确认实际 f_c 和滚降特性

若信号中存在突变或高频边缘(如步进信号),不要让 RC 滤波器严重削弱高频响应;

若 ADC 前有放大器,考虑运放带宽对 RC 滤波器的影响,避免形成非理想零极点;

若 ADC 输入电容较大(如 10pF~100pF),实际滤波器可能为 **R + (C + C_ADC)**,应计入总电容。

在这里我绘制了一阶 RC 滤波器在不同输入下(信号 + 噪声)的 频率响应曲线(Bode 图)以及 噪声功率谱密度(PSD)变化,来直观理解滤波器对信号和噪声的作用。

RC滤波器

第一张图(上图):RC 滤波器的幅频响应曲线,显示信号在不同频率上的衰减。

第二张图(下图):虚线是原始白噪声 PSD,频率范围内为常数;实线是经过 RC 滤波器后的 PSD,截止频率之后逐渐衰减;可视化带内与带外噪声的区别。

继续仿真,模拟带有 1/f 噪声的输入信号通过 RC 滤波器之后,噪声功率谱密度(PSD)的变化。

1/f 噪声建模

1/f 噪声,也称作粉红噪声(Pink Noise),其功率谱密度满足:

一般

我们令 ,即:

在频率较高时,这种噪声会逐渐减弱,但其总能量积分发散(必须设置下限)。

image-20250521083602399

图中

原始 1/f 噪声曲线呈 –10 dB/decade(即 )下降;

滤波器起作用后,截止频率附近拐弯变陡峭,高频部分被抑制;

在频率远高于  时,滤波器衰减趋势为 ,因为:

RC 滤波器对低频 1/f 噪声无能为力;但能显著抑制1/f 噪声的高频拖尾成分

我们从功率谱就是能量的角度再来看看这个问题:

**1/f 噪声经过 RC 滤波器后的 PSD 变化**

图展示了1/f 噪声经过 RC 滤波器后的 PSD 变化,以及标出了:

信号通带区域(0–5 kHz):目标有用信号频率;

抽取后系统的奈奎斯特带宽(0–6.2 kHz):对应过采样比 OSR = 8 的情形;

滤波器截止频率(2.5 kHz) 和采样频率的一半(50 kHz);

为了直观计算了不同频率范围下的噪声功率(单位为 V²),通过频谱积分得到:

区域
描述
噪声功率 (V²)
未滤波
总的 1/f 噪声
0.000851
滤波后(全带宽)
RC 滤波器后剩余噪声(0–fs/2)
0.000552
滤波后(信号带宽)
0–5 kHz 内的噪声功率
0.000541
抽取带宽
0–6.2 kHz 内的噪声功率
0.000545

RC 滤波器显著削减了高频的 1/f 拖尾,整体噪声下降约 35%信号通带内已包含大部分噪声能量(541 µV² vs 552 µV²);适当的抽取(如 OSR=8)不会引入过多额外噪声,因高频部分已经被滤波抑制;如果没有 RC 滤波器,抽取过程将混叠大量高频 1/f 噪声进低频 → 性能显著下降;这个问题也就是文章核心想说明的问题。

接下来分析:混合 1/f + 白噪声建模; 加入二阶滤波器对比; 以及采样/量化模拟后的 ENOB 估算:

Mixed Noise PSD with 1st & 2nd Order Filtering

图展示了混合 1/f 噪声 + 白噪声源通过不同滤波器(1阶 RC vs 2阶 Butterworth)后的 PSD 曲线比较。可以看到:

原始 PSD(黑色虚线)由  与常值白噪声叠加构成;

两种滤波器都在截止频率  kHz 处开始滚降;

2阶滤波器对带外高频噪声抑制明显强于 1阶,下降更陡峭(-40 dB/dec);

还是可以看到滤波器对低频  噪声无抑制能力,但能压制高频拖尾成分,特别有利于防止混叠。

ENOB 和噪声性能对比

滤波器类型
带宽内噪声功率(V²)
SNR (dB)
ENOB (bits)
1阶 RC 滤波器
0.003509
15.52
2.29 bits
2阶 Butterworth 滤波器
0.002410
17.15
2.56 bits
  1. 混合噪声源下的 ENOB 由噪声积分主导,而非量化误差主导;
  2. 提高滤波器阶数可提升 SNR 和 ENOB,特别是在高噪声场景;
  3. 二阶滤波器带来约 1.4 dB SNR 提升,ENOB 提升约 0.27 bit,在精度敏感系统中是显著改进;
  4. 带宽设置与抽取策略配合抗混叠滤波器至关重要,防止高频 1/f 拖尾噪声混入有效信号频带。

可以在后面加一个数字滤波器,比如基于采样率  kHz、过采样比 OSR = 8 设计的**FIR 抽取滤波器(Decimation Filter):

  1. 滤波器类型:FIR 低通

  2. 阶数(numtaps):64

  3. 截止频率:6.25 kHz(即抽取后系统的 Nyquist 频率)

  4. 采样率抽取:原始 100 kHz → 12.5 kHz

图 1:FIR 频率响应

显示 FIR 滤波器具有 良好的通带平坦性和陡峭的带外衰减;红线标注为抽取后系统的新奈奎斯特频率(6.25 kHz)。可有效防止混叠的高频分量进入信号带内。

图 2:时间域信号比较

蓝色:原始过采样信号(带有高频噪声);

橙色:经过 FIR 滤波 + 8 倍抽取之后的信号;

明显看出:高频成分被平滑滤除,信号更清洁,适合后续处理或存储

也可以看到滤波器的第一个若干系数(总共 64 项)已列在表中,可直接用于硬件或 MCU 实现:

h[n] ≈ [-0.00016, -0.00048, -0.00080, ..., +0.01, ..., -0.00048]

该 FIR 滤波器为对称线性相位结构(适合 FPGA/MCU 实时实现)

上面只是对SAR架构的计算,在ADI的文档里面也有别的分析,也可以看一下:

在The Data Conversion Handbook 中的解释

数据转换手册,2005年

这张图清晰地展示了三种不同的 ADC 结构与其对量化噪声频谱的影响,重点在于过采样(Oversampling)数字滤波(Digital Filtering)抽取(Decimation)噪声整形(Noise Shaping)的配合方式对系统性能的改善。

我们逐一解读图中 A/B/C 三种结构及其频谱图:


图 A — Nyquist Operation(奈奎斯特采样操作)

左边结构框图:

使用标准 ADC(如 SAR ADC),采样频率为 fs,没有额外的处理。

右边频谱图:

在 0 ~ fs/2 的信号带宽中,量化噪声是均匀分布的(白噪声)。

噪声功率密度 = q²/12,其中 q 是 1 LSB。

特征总结:

优点:结构简单,响应快。

缺点:所有带宽内的量化噪声都直接影响有效信号,ENOB 受限,没有任何削弱噪声的手段。


图 B — Oversampling + Digital Filter + Decimation

左边结构框图:

ADC 的采样频率提高到 K·fs(K 倍过采样),仍然是常规 ADC(如 SAR ADC 或 Flash);后级加入数字滤波器,将信号带外的噪声滤除。

抽取(Decimation):把采样率降低回 fs

右边频谱图:

  1. 初始量化噪声仍然均匀分布在 0 ~ Kfs/2,但经过滤波器抑制了带外噪声。
  2. 有效带宽在 fs/2 内,噪声被压低,因此信噪比(SNR)提升。
  3. 噪声“能量”没有减少,但因为能量分布在更宽的频带,单位频率的噪声密度变小,通过数字滤波器“削减”掉带外的噪声。

特征总结:

**ENOB 增加约 = 0.5 × log₂(K)**;比如 16× 过采样,可以提升 2 bit,SAR ADC 也能用这个方式提升性能(需要硬件允许高速采样)。


图 C — Oversampling + Noise Shaping + Digital Filter + Decimation

左边结构框图:

使用 Σ-Δ 模数转换器(ΣΔ Modulator);内部包含噪声整形器(Noise Shaper),本质上是反馈环结构,会将量化噪声“挤”到高频段

同样使用数字滤波器和抽取来保留有效信号、滤除高频噪声。

右边频谱图:

原始量化噪声不是白噪声,而是被重定向到高频区域(越阶的ΣΔ调制器,整形越陡峭)。

带内频率区域的噪声密度显著下降,极大地提升带内 SNR 和 ENOB。

数字滤波器只保留带内部分并下采样,去除带外高能噪声。

特征总结:

这种结构是音频 ADC 和高精度低速测量 ADC 的主流架构(比如 ADS1256, AD717x, LTC2500 等)。

ADI 音频ADC

可以实现 >20 bit 的分辨率,带内噪声非常低。


总结比较:

架构类型
噪声整形
是否过采样
是否滤波
是否抽取
带内噪声表现
ENOB 提升潜力
常见架构
A(Nyquist)
×
×
×
×
量化噪声平坦,无法滤除
SAR / Flash
B(Oversampling)
×
带内部分较干净
增加 ~0.5·log₂(K)
SAR + DSP
C(Σ-Δ)
带内非常干净(量化噪声被推到高频)
可高达 20~24 bit
Σ-Δ ADC

高速控制类 ADC(如电机控制、电源控制、SAR ADC),B 是可行方案。

高分辨率低速信号采集(如温度、电压、电流、传感器、生理信号等),C 是首选。

A 适用于预算有限或简单系统,但对抗噪声和提高精度非常有限。

使用 SAR ADC,但信号带宽中含有大量噪声(如 1/f 噪声或宽带热噪声),可以从以下几方面优化:

外部抗混叠滤波器(Anti-aliasing Filter)

设计一个低通滤波器,使噪声频谱能量集中于目标带宽内,避免 aliasing:

典型拓扑:RC、Sallen-Key、多级巴特沃斯或椭圆滤波器

截止频率设置为:略小于 fs/2

其中增加阶数可更有效抑制高频噪声,但也引入相位延迟。

低噪声驱动器匹配

SAR ADC 的输入电容会导致动态输入电流变化,驱动放大器必须具备:足够带宽和压摆率低输出阻抗输出负载稳定性好

否则会在采样瞬间引入额外噪声或非线性。

采样策略优化(平均/超采样)

如果系统带宽允许,可以用多次采样平均(不是过采样滤波),提高信噪比(SNR):

其中  为平均次数,对高频白噪声特别有效

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# 采样频率和RC滤波器参数
fs = 100e3  # 100 kHz
fc = 25e3   # 截止频率 25 kHz
RC = 1 / (2 * np.pi * fc)

# 定义频率轴(对数刻度)
f = np.logspace(1, 5, 1000)  # 从10Hz到100kHz
w = 2 * np.pi * f

# RC 滤波器幅频响应 H(f)
H = 1 / (1 + 1j * w * RC)
H_dB = 20 * np.log10(np.abs(H))

# 假设输入白噪声 PSD 是常数
S_white = np.ones_like(f)

# 滤波后 PSD = S_white × |H(f)|²
S_filtered = S_white * np.abs(H)**2

# 绘图
plt.figure(figsize=(10, 6))
plt.subplot(2, 1, 1)
plt.semilogx(f, H_dB, label="|H(f)| in dB")
plt.axvline(fc, color='gray', linestyle='--', label=f"fc = {fc/1e3:.1f} kHz")
plt.title("RC Low-Pass Filter Frequency Response")
plt.ylabel("Magnitude (dB)")
plt.grid(True, which='both')
plt.legend()

plt.subplot(2, 1, 2)
plt.semilogx(f, 10*np.log10(S_white), '--', label="Input PSD (white noise)")
plt.semilogx(f, 10*np.log10(S_filtered), label="Output PSD (filtered)")
plt.axvline(fc, color='gray', linestyle='--')
plt.ylabel("PSD (dB/Hz)")
plt.xlabel("Frequency (Hz)")
plt.grid(True, which='both')
plt.legend()

plt.tight_layout()
plt.show()

1/f 噪声 + RC 滤波器

import numpy as np
import matplotlib.pyplot as plt

# 频率轴(对数刻度)
f = np.logspace(1, 5, 1000)  # 10 Hz 到 100 kHz
fs = 100e3                  # 采样率
fc = 2.5e3                  # RC 滤波器的截止频率
RC = 1 / (2 * np.pi * fc)

# RC 滤波器频率响应 H(f)
w = 2 * np.pi * f
H = 1 / (1 + 1j * w * RC)

# --- 1/f 噪声建模 ---
K = 1e-4   # 1/f 噪声强度
S_1f = K / f

# 滤波后 PSD
S_1f_filtered = S_1f * np.abs(H)**2

# 绘图
plt.figure(figsize=(10, 6))

plt.semilogx(f, 10 * np.log10(S_1f), '--r', label='1/f Noise (Input PSD)')
plt.semilogx(f, 10 * np.log10(S_1f_filtered), 'b', label='Filtered PSD (1/f × |H(f)|²)')
plt.axvline(fc, color='gray', linestyle='--', label=f'fc = {fc/1e3:.1f} kHz')

plt.title('RC Filtering Effect on 1/f Noise')
plt.xlabel('Frequency (Hz)')
plt.ylabel('PSD (dB/Hz)')
plt.legend()
plt.grid(True, which='both')
plt.tight_layout()
plt.show()

加入信号通带、噪声积分计算、抽取效果

import numpy as np
import matplotlib.pyplot as plt

# -----------------------------
# System parameters
# -----------------------------
fs = 100e3              # Sampling frequency
fc = 2.5e3              # RC cutoff frequency
RC = 1 / (2 * np.pi * fc)
alpha = 1.0             # 1/f noise exponent
K = 1e-4                # 1/f noise power coefficient
f_signal_max = 5e3      # Maximum signal frequency (passband edge)

# Frequency axis
f = np.logspace(1, 5, 2000)  # 10 Hz to 100 kHz
w = 2 * np.pi * f

# -----------------------------
# Define 1/f noise PSD
# -----------------------------
S_1f = K / (f**alpha)

# RC filter transfer function magnitude squared
H_squared = 1 / (1 + (f / fc)**2)

# Filtered PSD
S_filtered = S_1f * H_squared

# -----------------------------
# Noise Power Integration
# -----------------------------
def integrate_psd(f, psd, f_low, f_high):
    """Integrate PSD over a specific frequency band using trapezoidal rule"""
    mask = (f >= f_low) & (f <= f_high)
    return np.trapz(psd[mask], f[mask])

# Total input noise (before filtering)
P_input_total = integrate_psd(f, S_1f, f[0], fs/2)

# Total output noise (after filtering)
P_output_total = integrate_psd(f, S_filtered, f[0], fs/2)

SAR ADC 对带内噪声频谱的处理特性.理论&仿真
# Signal band noise power (after filtering)
P_output_signal_band = integrate_psd(f, S_filtered, f[0], f_signal_max)

# -----------------------------
# Decimation effect
# -----------------------------
OSR = 8
fs_decimated = fs / OSR
f_decimated_Nyquist = fs_decimated / 2
P_decimated_band = integrate_psd(f, S_filtered, f[0], f_decimated_Nyquist)

# -----------------------------
# Plot PSD and integration bands
# -----------------------------
plt.figure(figsize=(12, 8))

plt.semilogx(f, 10 * np.log10(S_1f), '--r', label='Original 1/f PSD')
plt.semilogx(f, 10 * np.log10(S_filtered), 'b', label='Filtered PSD (1/f × |H(f)|²)')

plt.axvspan(f[0], f_signal_max, color='green', alpha=0.1, label='Signal Band (0–5 kHz)')
plt.axvspan(f[0], f_decimated_Nyquist, color='purple', alpha=0.1, label=f'Decimated Nyquist Band (0–{fs_decimated/2/1e3:.1f} kHz)')

plt.axvline(fc, color='gray', linestyle='--', label=f'fc = {fc/1e3:.1f} kHz')
plt.axvline(fs/2, color='black', linestyle=':', label='Nyquist freq (fs/2)')

plt.xlabel('Frequency (Hz)')
plt.ylabel('PSD (dB/Hz)')
plt.title('1/f Noise PSD with RC Filtering and Integration Bands')
plt.legend()
plt.grid(True, which='both')
plt.tight_layout()
plt.show()

# -----------------------------
# Display integrated powers
# -----------------------------
import pandas as pd
import ace_tools as tools

df = pd.DataFrame({
    "Noise Power (V²)": [
        P_input_total,
        P_output_total,
        P_output_signal_band,
        P_decimated_band
    ],
    "Description": [
        "Total 1/f noise (no filtering)",
        "Total filtered noise (0–fs/2)",
        "Filtered noise in signal band (0–5kHz)",
        f"Filtered noise in decimated band (0–{fs_decimated/2/1e3:.1f}kHz)"
    ]
})

tools.display_dataframe_to_user(name="Integrated Noise Power Summary", dataframe=df)
   Noise Power (V²)                                  Description
0          0.000851               Total 1/f noise (no filtering)
1          0.000552                Total filtered noise (0–fs/2)
2          0.000541       Filtered noise in signal band (0–5kHz)
3          0.000545  Filtered noise in decimated band (0–6.2kHz)

量化模拟后的 ENOB 估算

import numpy as np
import matplotlib.pyplot as plt

# -----------------------------
# System parameters
# -----------------------------
fs = 100e3                  # Sampling frequency
OSR = 8                     # Oversampling ratio
fs_dec = fs / OSR          # Decimated sampling rate
fc = 2.5e3                  # RC or filter cutoff
RC = 1 / (2 * np.pi * fc)

f = np.logspace(1, 5, 2000)
w = 2 * np.pi * f

# -----------------------------
# Mixed noise PSD model: 1/f + white
# -----------------------------
K_1f = 1e-4                 # 1/f noise coefficient
S_white = 1e-6              # White noise power spectral density (V^2/Hz)

S_1f = K_1f / f             # 1/f noise
S_total_input = S_1f + S_white  # Mixed noise PSD

# -----------------------------
# First-order RC filter
# -----------------------------
H1_sq = 1 / (1 + (f / fc)**2)

# -----------------------------
# Second-order Butterworth LPF (normalized)
# -----------------------------
# |H(jw)|^2 = 1 / (1 + (f/fc)^4 + 2*(f/fc)^2)
f_norm = f / fc
H2_sq = 1 / (1 + (f_norm)**4 + 2*(f_norm)**2)

# -----------------------------
# Filtered PSDs
# -----------------------------
S_filtered_1st = S_total_input * H1_sq
S_filtered_2nd = S_total_input * H2_sq

# -----------------------------
# Noise power integration
# -----------------------------
def integrate_psd(f, psd, f_low, f_high):
    mask = (f >= f_low) & (f <= f_high)
    return np.trapz(psd[mask], f[mask])

# Integration bounds
f_band = fs_dec / 2

# Integrated noise power (for ENOB calculation)
P1 = integrate_psd(f, S_filtered_1st, 0, f_band)
P2 = integrate_psd(f, S_filtered_2nd, 0, f_band)

# -----------------------------
# ENOB estimation (V_FS = 1 V assumed)
# -----------------------------
V_FS = 1.0
SNR1 = 10 * np.log10((V_FS**2 / 8) / P1)
SNR2 = 10 * np.log10((V_FS**2 / 8) / P2)

ENOB1 = (SNR1 - 1.76) / 6.02
ENOB2 = (SNR2 - 1.76) / 6.02

# -----------------------------
# Plot PSD comparisons
# -----------------------------
plt.figure(figsize=(12, 8))
plt.semilogx(f, 10 * np.log10(S_total_input), 'k--', label='Input PSD (1/f + white)')
plt.semilogx(f, 10 * np.log10(S_filtered_1st), 'b', label='1st-order RC filtered PSD')
plt.semilogx(f, 10 * np.log10(S_filtered_2nd), 'g', label='2nd-order Butterworth filtered PSD')

plt.axvline(fc, color='gray', linestyle='--', label=f'fc = {fc/1e3:.1f} kHz')
plt.axvline(f_band, color='purple', linestyle=':', label=f'Decimated Nyquist = {f_band/1e3:.1f} kHz')

plt.xlabel('Frequency (Hz)')
plt.ylabel('PSD (dB/Hz)')
plt.title('Mixed Noise PSD with 1st & 2nd Order Filtering')
plt.legend()
plt.grid(True, which='both')
plt.tight_layout()
plt.show()

# -----------------------------
# Display results
# -----------------------------
import pandas as pd
import ace_tools as tools

df = pd.DataFrame({
    "Filter Type": ["1st-Order RC""2nd-Order Butterworth"],
    "Noise Power in Decimated Band (V²)": [P1, P2],
    "SNR (dB)": [SNR1, SNR2],
    "ENOB (bits)": [ENOB1, ENOB2]
})

tools.display_dataframe_to_user(name="ENOB and Noise Comparison", dataframe=df)
             Filter Type  Noise Power in Decimated Band (V²)   SNR (dB)  
0           1st-Order RC                            0.003509  15.516666   
1  2nd-Order Butterworth                            0.002410  17.148220   

   ENOB (bits)  
0     2.285161  
1     2.556183  
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import firwin, lfilter, freqz, decimate

# -----------------------------
# Signal parameters
# -----------------------------
fs = 100e3                   # Original sampling frequency
OSR = 8                      # Oversampling ratio
fs_dec = fs // OSR           # Decimated frequency
T = 1                        # Duration (1 second)
N = int(fs * T)
t = np.linspace(0, T, N, endpoint=False)

# -----------------------------
# Generate noisy input (same as before)
# -----------------------------
np.random.seed(0)

white_noise = np.random.normal(0, 1, N)
def generate_1f_noise(N, alpha=1.0):
    freqs = np.fft.rfftfreq(N, 1/fs)
    freqs[0] = freqs[1]
    magnitude = 1 / freqs**(alpha / 2)
    phase = np.exp(1j * 2 * np.pi * np.random.rand(len(freqs)))
    spectrum = magnitude * phase
    noise = np.fft.irfft(spectrum, n=N)
    return (noise - np.mean(noise)) / np.std(noise)

pink_noise = generate_1f_noise(N) * 0.05
x = 0.01 * white_noise + pink_noise  # total input noise

# -----------------------------
# FIR Decimation Filter Design
# -----------------------------
numtaps = 64
cutoff_hz = fs_dec / 2  # Nyquist of decimated system
fir_coeff = firwin(numtaps, cutoff_hz / (fs / 2))  # normalize cutoff

# Frequency response
w_fir, h_fir = freqz(fir_coeff, worN=1024, fs=fs)

# Filtered signal
x_filt = lfilter(fir_coeff, 1.0, x)

# Decimation
x_dec = x_filt[::OSR]

# Time vector for decimated signal
t_dec = t[::OSR]

# -----------------------------
# Plot FIR filter frequency response
# -----------------------------
plt.figure(figsize=(10, 4))
plt.plot(w_fir, 20 * np.log10(np.abs(h_fir)), label='FIR Magnitude Response')
plt.axvline(fs_dec / 2, color='red', linestyle='--', label=f'Decimated Nyquist = {fs_dec/2/1e3:.1f} kHz')
plt.title('FIR Decimation Filter Frequency Response')
plt.xlabel('Frequency (Hz)')
plt.ylabel('Magnitude (dB)')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()

# -----------------------------
# Plot time-domain signal before and after decimation
# -----------------------------
plt.figure(figsize=(10, 4))
plt.plot(t[:2000], x[:2000], alpha=0.5, label='Original Oversampled')
plt.plot(t_dec[:250], x_dec[:250], label='After FIR + Decimation')
plt.title('Time-Domain Signal Before and After FIR Decimation')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

# -----------------------------
# Return FIR coefficients and basic decimation result
# -----------------------------
import pandas as pd
import ace_tools as tools

df = pd.DataFrame({
    "FIR Coefficients": fir_coeff
})
tools.display_dataframe_to_user(name="FIR Filter Coefficients", dataframe=df)
   FIR Coefficients
0         -0.000158
1         -0.000478
2         -0.000802
3         -0.001103
4         -0.001322

https://www./cn/resources/technical-books/data-conversion-handbook.html

https://www./media/en/training-seminars/design-handbooks/Data-Conversion-Handbook/Chapter3.pdf

https://www./cn/parametricsearch/11249#/

https://www./cn/products/ad7768-4.html

https://www./media/en/technical-documentation/data-sheets/250032fb.pdf

https://blog.csdn.net/Gou_Hailong/article/details/105761432