电容去耦半径怎么算?我写了个工具

电容去耦半径怎么算?我写了个工具

上一篇文章讲了去耦电容为什么要靠近芯片放,根本原因是电磁波在 FR4 里传播速度不够快。

那问题来了:到底放多远算"近"?有没有一个量化的标准?

有,叫去耦半径。这篇文章不讲原理(上一期讲过了),直接给计算方法和一个能跑的工具。

去耦半径怎么算?

核心就四步:

第一步:自谐振频率

电容不是在所有频率下都表现为电容。超过自谐振频率(SRF)后它就变成电感了,不再去耦。

SRF = 1 / (2π√(L·C))

  • L— 寄生电感(芯片ESL + 安装电感)
  • C— 电容容值

第二步:波长

我们知道电磁波在 FR4 中的速度大约是 6 英寸/纳秒。有了频率就能算波长:

波长 = 速度 / 频率

在 FR4 中:波长 = 6×10⁹ (inch/s) / SRF (Hz)

第三步:去耦半径

电容的有效去耦距离大约为波长的 1/50。这个系数是工程经验值。

去耦半径 = 波长 / 50

第四步:修正系数

实际设计中还需要考虑两个因素:

  1. 安装电感— 过孔和走线会额外增加 ESL(2 个过孔约 +1.0nH,每 mm 走线 +0.04nH),这会降低 SRF,拉长波长,最终半径反而变大——但不要高兴太早
  2. 芯片瞬态需求— 芯片的 dI/dt(电流变化率)和允许纹波决定了有效时间窗口。dI/dt 越大纹波要求越严,有效半径越小

所以最终推荐半径要除以一个安全系数,通常是 2~10 倍。

我写了个计算工具

为了让这个计算可重复,我写了个 C 语言工具。这是我的日常工作习惯——与其每次估算,不如写个程序跑。

快速估算(模式 1)

只输入容值和 ESL,出理论值和建议设计值:

选择模式:1 输入电容容值 (uF): 0.1 芯片ESL (nH, 如 0402 约 0.4): 0.4 电容值: 0.100 uF 芯片ESL: 0.40 nH SRF: 25.2 MHz 理论值: 121 mm 建议设计值: 36 mm

也就是说,0.1uF 的 0402 电容,建议设计时放在离 IC 引脚 36mm 以内。

精确计算(模式 2)

如果还想更准,输入安装参数和芯片瞬态参数:

选择模式:2 电容容值 (uF): 0.1 ESL (nH): 0.4 过孔数量: 2 走线长度 (mm): 0.5 dI/dt (A/ns): 1.0 允许纹波 (mV): 50 芯片ESL: 0.40 nH 安装电感: 1.02 nH = 总寄生电感: 1.42 nH dI/dt安全系数: 2.0 x SRF: 25.2 MHz 理论值: 121 mm 实际值: 228 mm 建议设计值: 114 mm

注意实际值虽然变成了 228mm,但安全系数把它压到了 114mm。如果你的芯片 dI/dt 更大纹波要求更严,这个数值还会进一步缩小。

对照表(模式 3)

直接看 0.1uF 到 100uF 九种常用电容的推荐半径:

容值SRF推荐半径适合场景
0.1uF25.2 MHz48 mm高频去耦
0.47uF11.6 MHz105 mmIO/核供电
1uF8.0 MHz153 mm核供电
2.2uF5.4 MHz227 mm中频去耦
4.7uF3.7 MHz332 mm中频储能
10uF2.5 MHz484 mmDDR VTT
22uF1.7 MHz712 mm低频平滑
47uF1.2 MHz1045 mmBulk
100uF0.8 MHz1532 mmBulk

代码实现

核心计算逻辑其实很短,就是 SRF 和波长的公式套用:

// 自谐振频率 double SRF = 1.0 / (2 * PI * sqrt(L_total * C)); // 波长 (FR4中) double lambda = LIGHT_SPEED_INCH / SRF; // 去耦半径 double R_mm = (lambda / RADIUS_FACTOR) * INCH_TO_CM * 10; // 安全系数 (dI/dt修正) double factor = (didt / 0.5) * (50.0 / v_ripple); // 推荐半径 double R_rec = R_mm / factor;

几个实际结论

做完这个工具,几个值得记住的数字:

电容建议设计半径意味着什么
0.1uF 0402~36 mm必须紧贴 IC 引脚,通常不超过一个手指宽
1uF 0603~115 mm可以放稍远,但最好在同一侧
10uF 0805~290 mm中频去耦,板级范围内基本都行
100uF~920 mmBulk 电容,放板子哪里都行

这些数值已经包含了安装电感和安全系数。如果芯片是高速器件(CPU/DDR/SerDes),建议打五折。

写在最后

工具不复杂,但能用。每次画板放去耦电容的时候,跑一下这个程序,心里就有数了——是不是真的在有效半径内,还是 "差不多就行" 然后等着改板。

#include <stdio.h> #include <math.h> #define PI 3.1415926535 #define LIGHT_SPEED_INCH 6e9 // 电磁波在FR4中的速度 (inch/s) #define INCH_TO_CM 2.54 // 英寸转厘米 #define RADIUS_FACTOR 50.0 // 去耦半径 = 波长 / 50 // 常用电容封装的典型ESL (nH) struct cap_package { char name[10]; double esl_nh; }; // 安装电感估算:过孔数量 + 走线长度 -> 额外 ESL (nH) double calc_mounting_inductance(int via_count, double trace_length_mm) { double via_L = via_count * 0.5; // nH, 每个过孔 ~0.5nH double trace_L = trace_length_mm * 0.04; // nH, 每mm走线 ~0.04nH return via_L + trace_L; } // 计算dI/dt安全系数:也快越严,半径越小 double calc_safety_factor(double di_dt_A_per_ns, double v_ripple_mV) { // 基准:dI/dt = 0.5 A/ns, Vripple = 50mV -> 系数 = 1.0 // dI/dt 越大或 Vripple 越小 -> 系数越大 -> 半径越小 double base_didt = 0.5; double base_ripple = 50.0; double factor = (di_dt_A_per_ns / base_didt) * (base_ripple / v_ripple_mV); if (factor < 1.0) factor = 1.0; if (factor > 20.0) factor = 20.0; return factor; } int main() { struct cap_package packages[] = { {"0201", 0.3}, {"0402", 0.4}, {"0603", 0.6}, {"0805", 0.8}, {"1206", 1.2}, {"1210", 1.5} }; int pkg_count = sizeof(packages) / sizeof(packages[0]); int mode; printf("============================================\n"); printf(" 电容去耦半径计算工具 v2.0\n"); printf("============================================\n\n"); printf("选择模式:\n"); printf(" 1 - 快速估算\n"); printf(" 2 - 精确计算(含安装电感 + dI/dt修正)\n"); printf(" 3 - 常用电容对照表\n"); printf("请输入 (1/2/3): "); scanf("%d", &mode); double C, L_chip_nh, L_mount_nh = 0; double didt = 0.5, vripple = 50; if (mode == 1 || mode == 2) { double cap_val_nf, esl_nh; printf("\n输入电容容值 (uF, 如 0.1 = 0.1uF, 1 = 1uF): "); if (scanf("%lf", &cap_val_nf) != 1) { printf("输入无效,使用默认值 0.1uF\n"); cap_val_nf = 0.1; while(getchar() != '\n'); // 清空输入缓冲 } printf("芯片ESL (nH, 如 0402 约 0.4): "); if (scanf("%lf", &esl_nh) != 1) { printf("输入无效,使用默认值 0.4nH\n"); esl_nh = 0.4; while(getchar() != '\n'); } C = cap_val_nf * 1e-6; // uF -> F L_chip_nh = esl_nh; if (mode == 2) { int via_cnt = 2; double trace_len = 0.5; printf("\n--- 安装参数 ---\n"); printf("过孔数量 (Enter默认 2): "); if (scanf("%d", &via_cnt) != 1) { via_cnt = 2; while(getchar()!='\n'); } printf("焊盘到过孔走线 mm (Enter默认 0.5): "); if (scanf("%lf", &trace_len) != 1) { trace_len = 0.5; while(getchar()!='\n'); } L_mount_nh = calc_mounting_inductance(via_cnt, trace_len); printf("\n--- 芯片瞬态参数 ---\n"); printf("dI/dt A/ns (Enter默认 0.5): "); if (scanf("%lf", &didt) != 1) { didt = 0.5; while(getchar()!='\n'); } printf("允许纹波 mV (Enter默认 50): "); if (scanf("%lf", &vripple) != 1) { vripple = 50; while(getchar()!='\n'); } } double L_total_nh = L_chip_nh + L_mount_nh; double L_total = L_total_nh * 1e-9; // 理论半径:仅芯片ESL double f_chip = 1.0 / (2 * PI * sqrt(L_chip_nh * 1e-9 * C)); double lam_chip_inch = LIGHT_SPEED_INCH / f_chip; double R_chip_mm = (lam_chip_inch / RADIUS_FACTOR) * INCH_TO_CM * 10; // 实际应参考的半径:用总电感(芯片+安装) double f_total = 1.0 / (2 * PI * sqrt(L_total * C)); double lam_total_inch = LIGHT_SPEED_INCH / f_total; double R_total_mm = (lam_total_inch / RADIUS_FACTOR) * INCH_TO_CM * 10; // 推荐半径:受 dI/dt 限制进一步压缩 double factor = calc_safety_factor(didt, vripple); double R_rec_mm = R_total_mm / factor; printf("\n============================================\n"); printf(" 计算结果\n"); printf("============================================\n"); printf(" 电容值: %.3f uF (%.0f nF)\n", C * 1e6, C * 1e9); printf(" -----------------------------------------\n"); printf(" 芯片ESL: %.2f nH\n", L_chip_nh); if (mode == 2) { printf(" + 安装电感(过孔+走线): %.2f nH\n", L_mount_nh); printf(" = 总寄生电感: %.2f nH\n", L_total_nh); printf(" dI/dt: %.2f A/ns\n", didt); printf(" 允许纹波: %.0f mV\n", vripple); printf(" dI/dt安全系数: %.1f x\n", factor); } printf(" -----------------------------------------\n"); printf(" 自谐振频率(SRF): %.1f MHz\n", f_chip / 1e6); printf(" -----------------------------------------\n"); printf(" 去耦半径参考值:\n"); if (mode == 1) { double r_suggest = R_chip_mm * 0.3; printf(" 理论值: %5.0f mm (仅芯片ESL, 理想情况)\n", R_chip_mm); printf(" 估算实际值: %5.0f mm (含安装电感, 估算)\n", R_chip_mm * 0.5); printf(" ════════════════════════════════════════\n"); printf(" ▶ 建议设计值: %5.0f mm ✅\n", r_suggest); printf(" ════════════════════════════════════════\n"); printf(" (按理论值的30%%估算, 含安装电感+安全余量)\n"); if (r_suggest < 10) { printf(" ⚠️ 建议设计值 < 10mm!必须紧贴IC引脚放\n"); } } else { printf(" 理论值: %5.0f mm (仅芯片ESL)\n", R_chip_mm); printf(" 实际值: %5.0f mm (含安装电感)\n", R_total_mm); printf(" ════════════════════════════════════════\n"); printf(" ▶ 建议设计值: %5.0f mm ✅\n", R_rec_mm); prin