2kHz 方波滤成正弦波要先算清源阻抗
方波频率对了,接上带通滤波器却只剩很小的输出,调电位器时又只有很窄的一段能用。遇到这种情况,先把输入网络算进去,往往比继续追着运放增益改阻值更有效。
下面以一组 555+TL072 电路参数为例,把从 Vo1 到 Vo2 的整条通道重新建模。实际完成的工作是节点求解、独立公式交叉检查、调谐反算和谐波预算;没有上板测量,也没有把理想模型的曲线当作示波器波形。
先沿着信号走一遍

图1 工程 SCH Rev1.0 的实际 EDA 导出,保留 EDAmake、立创EDA 署名。左侧是可调方波发生器,右侧是带通滤波器。本文只验证右侧线性通道,不承诺按整板 BOM 直接装配即可达到指标。
Vo1 经 C2、R4 进入 R4/R5/R6 的交点,再经 R5 进入滤波器。RP3、C3、C8 也接在 R5 后面的节点上;R8 从运放输出反馈到反相输入。输出经 C4 耦合到 Vo2,R7 是输出侧的 1kΩ 负载。

图2 滤波器局部。RP3 图面仍显示 10kΩ,这是原图标注,不能把它理解为本文计算采用的有效电阻。
采用的数值为 R4=20kΩ、R5=8.2kΩ、R6=100kΩ、R8=16kΩ,C3=C8=100nF,C2=C4=10µF,R7=1kΩ。C3/C8 图面的“104”对应 100nF。
这里需要先处理一个会改变结论的冲突。SCH 中 RP3 显示和 Resistance 属性都是 10k,但型号字段是 3296W-1-101;Sim 中 RX3 显示“100”,其 Resistance 属性却是 100K。它们不能相互证明实物到底装了什么阻值。
所以,下文 Rp 一律指 RP3 接地端与接入节点之间的有效电阻,不是电位器铭牌总阻值,也不从“80%”推断实物电阻。准备复现时应断电测量,必要时隔离并联支路;采购前重新核对型号和量程。未经这个步骤,旋钮位置没有可比较的意义。
8.2kΩ 并不是滤波器看到的全部源阻抗
在 2kHz,10µF 的容抗约 7.96Ω。先将 C2 近似短路,Vo1 侧网络可以做戴维南等效。
开路等效电压系数为 k=R6/(R4+R6)=0.833333,R5 前面的等效电阻为 R4∥R6=16.667kΩ。因此,滤波器输入支路实际面对的是 Ra=R5+(R4∥R6)=24.867kΩ,同时输入电压先乘了 k。
只看 R5、R8 和两个相等电容,容易得到接近 1 的局部峰值增益。把源网络接回来,Vo2/Vo1 的峰值才是我们真正要比较的量。
令 s=j·2πf,理想运放的反相输入在交流小信号中跟随参考电压。R2/R3 的中点在本模型中视为交流地;这不等于把芯片 2 脚在实物上接到 GND。
忽略 C2/C4 的容抗时,从等效源到运放输出的传递函数为:
Hlocal(s)=−(R8·C3/Ra)·s / [R8·C3·C8·s²+(C3+C8)·s+1/Ra+1/Rp]
Vo1 到输出还需乘 k。由分母可得到:
f0=sqrt[(1/Ra+1/Rp)/(R8·C3·C8)]/(2π)
Q=2πf0·R8·C3·C8/(C3+C8)
|Hpeak|=k·R8·C3/[Ra·(C3+C8)]
代入这组数值,若希望中心频率约为 2kHz,反算得到 Rp≈39.64Ω、Q≈10.05、峰值增益约 0.2681,对应约 199Hz 的理想带宽。电位器调到“100Ω”本身并不代表中心频率已经对准 2kHz。
调频与加增益要分开处理
为了检查近似有没有掩盖问题,程序保留了 C2、C4 的复数阻抗,直接求解三个未知量:R4/R5/R6 交点 A、R5/RP3/C3/C8 交点 X、运放输出 O。
再用含 C2 的复数戴维南等效独立计算一次,在 1Hz~1MHz 的 151 个频率、5 个有效电阻上对比,共 755 点,最大相对差约 3.3×10⁻¹⁵。这个检查验证了两种实现的一致性,不代表真实 TL072 已被完整模拟。

图3 同一组元件、同一理想模型的扫频结果。纵轴是 Vo2/Vo1,不是运放局部增益。
| Rp 有效电阻 | 近似中心频率 | 2kHz 时的幅度比 |
|---|---|---|
| 100Ω | 1260.76Hz | 0.04366 |
| 39.64Ω | 2000Hz | 0.26809 |
在这个模型里,先调中心频率,2kHz 的输出幅度就能明显恢复。若输入已经对准通带而幅度仍不够,再讨论前级缓冲或后级增益;改 R8 会同时改变中心频率、Q 和增益,不能把它当作独立音量旋钮。
0.268 还是“同一频率分量”的传递比,不是方波峰峰值直接乘出来的正弦峰峰值。理想 0~V 的 50% 方波,基波峰值是 2V/π;应先算基波,再乘通道响应。
高 Q 也意味着不能只计算一次标称值。另作一组明确假设的容差预算:R4/R5/R6/R8 各±1%,C3/C8 各±5%,有效 Rp±5%,保持标称调谐值不重调。128 个端点组合的近似中心频率落在 1.850~2.171kHz;这些角点在固定 2kHz 的幅度比为 0.134~0.266。
这组范围来自人为设定的公差,不是原 BOM 的标称精度,也不是统计良率或连续参数域的严格最坏值证明。它说明逐板扫频和重新调谐有必要,直接复制旋钮位置并不可靠。
波形变圆以后还剩多少谐波
将输入定义为理想 0~1 脉冲,占空比 D 的第 n 次谐波幅度与 |sin(nπD)|/n 成正比。输出每次谐波还要乘 |H(nf)|,再用基波归一化。
本文计算 THD=sqrt(A2²+…+A99²)/A1,不包括噪声、运放非线性、555 边沿毛刺和电源串扰。

图4 Rp≈39.64Ω、输入频率 2kHz 时的线性谐波预算。50% 理想方波的偶次谐波为零,图中低于 −100dBc 的数值项按显示下限处理。
| 输入占空比 | Rp≈39.64Ω | Rp=100Ω |
|---|---|---|
| 50% | 1.338% | 7.699% |
| 60% | 2.313% | 12.213% |
| 70% | 3.996% | 20.626% |
这些是 2~99 次谐波的线性模型结果,不是整机实测 THD。把上限扩到 999 次,调谐且占空比 50% 的结果约为 1.33808%,与 99 次结果差约 0.000006 个百分点。对本模型而言,尾部截断已不是主要误差;对实物而言,削顶、共模越界和供电噪声仍可能完全改变结果。
先用这段代码复算自己的阻值
把下面完整代码保存为 mfb_audit.py,使用 Python 3.11 或更新版本,无第三方依赖。它与图2的位号对应,输入为 Vo1,输出为 Vo2;只修改实际量得的元件参数,不需要烧录固件。
默认运行 python mfb_audit.py。检查 100Ω 与 60% 占空比时运行 python mfb_audit.py --f 2000 --rp 100 --duty 0.6。更换电容或固定电阻时修改 BASE 后重新计算。
"""555/TL072 MFB small-signal audit, v1.0.0. Python 3.11+, stdlib only.
Independent analysis code. MIT License, Copyright (c) 2026.
The EDA reference circuit remains under its upstream GPL-3.0 license.
This ideal-op-amp calculation is not a measurement or a complete device model.
"""
import argparse
import cmath
import math
BASE = dict(r4=20000.0, r5=8200.0, r6=100000.0, r8=16000.0,
c2=10e-6, c3=100e-9, c8=100e-9, c4=10e-6, r7=1000.0)
def linear_solve(matrix, rhs):
"""Complex Gaussian elimination with partial pivoting."""
a = [list(row) + [b] for row, b in zip(matrix, rhs)]
n = len(a)
for k in range(n):
pivot = max(range(k, n), key=lambda j: abs(a[j][k]))
a[k], a[pivot] = a[pivot], a[k]
if abs(a[k][k]) < 1e-30:
raise ValueError("singular circuit")
scale = a[k][k]
a[k] = [v / scale for v in a[k]]
for j in range(n):
if j != k:
scale = a[j][k]
a[j] = [x - scale * y for x, y in zip(a[j], a[k])]
return [row[-1] for row in a]
def response(f, rp, p=None):
"""Vo2 / Vo1; RP3 is its effective resistance to ground in ohms.
A = R4/R5/R6 junction; X = R5/RP3/C3/C8 junction.
Inverting input is AC ground. Unknowns are A, X, op-amp output.
"""
if f <= 0 or rp <= 0:
raise ValueError("frequency and resistance must be positive")
p = BASE if p is None else p
s = 2j * math.pi * f
y = 1 / (p['r4'] + 1 / (s * p['c2']))
g5, g8 = 1 / p['r5'], 1 / p['r8']
c3, c8 = s * p['c3'], s * p['c8']
rows = [[y + 1 / p['r6'] + g5, -g5, 0],
[-g5, g5 + 1 / rp + c3 + c8, -c8],
[0, c3, g8]]
vo = linear_solve(rows, [y, 0, 0])[2]
return vo * s * p['c4'] * p['r7'] / (1 + s * p['c4'] * p['r7'])
def tuning(f, p=None):
"""Approximate target RP3, Q and peak gain; C2/C4 treated as shorts."""
p = BASE if p is None else p
if f <= 0:
raise ValueError("frequency must be positive")
ra = p['r5'] + p['r4'] * p['r6'] / (p['r4'] + p['r6'])
w = 2 * math.pi * f
g = w * w * p['r8'] * p['c3'] * p['c8'] - 1 / ra
if g <= 0:
raise ValueError("target below the topology's tuning range")
q = w * p['r8'] * p['c3'] * p['c8'] / (p['c3'] + p['c8'])
gain = (p['r6'] / (p['r4'] + p['r6']) * p['r8'] * p['c3']
/ (ra * (p['c3'] + p['c8'])))
return 1 / g, q, gain
def harmonic_thd(f, duty, rp, harmonics=99):
"""Linear-filter output THD, harmonic 2..99; excludes device distortion."""
if not 0 < duty < 1:
raise ValueError("duty must lie between 0 and 1")
amps = [abs(math.sin(math.pi * n * duty) / n * response(n * f, rp))
for n in range(1, harmonics + 1)]
return math.sqrt(sum(a * a for a in amps[1:])) / amps[0]
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--f', type=float, default=2000.0)
parser.add_argument('--rp', type=float)
parser.add_argument('--duty', type=float, default=0.5)
args = parser.parse_args()
target, q, peak = tuning(args.f)
rp = target if args.rp is None else args.rp
h = response(args.f, rp)
print(f'target_RP3={target:.4f} ohm Q={q:.4f} peak_gain={peak:.6f}')
print(f'RP3={rp:.4f} ohm |Vo2/Vo1|={abs(h):.6f} phase={math.degrees(cmath.phase(h)):.3f} deg')
print(f'linear_THD_h2_to_h99={100 * harmonic_thd(args.f, args.duty, rp):.4f}%')
默认运行的关键结果是 target_RP3=39.6417 ohm、Q=10.0531、|Vo2/Vo1|=0.268087、linear_THD_h2_to_h99=1.3381%。参数名中的 linear 是结果的一部分,记录数据时也应保留这个限定。
上板之前还要补齐哪些检查

图5 同一工程的 PCB 顶面导出。主要走线位于底层,顶面的“跳线”标记需要结合网表逐根核对,不能因为底层覆铜看起来连成一片就省掉它。

图6 从底面观察的底层铜。镜像的顶层丝印仅用于位置对照,不代表底面实际印有这些文字;此图不是打样文件。
先断电核对 TL072IP 的供电脚 8、4,以及本级信号脚 1、2、3。上电后检查二极管后的 VCC、R2/R3 中点和运放输出直流电位,再用小幅正弦扫频确定峰值位置;最后接入方波,分别记录频率、占空比、输入幅度和输出频谱。比较不同板子时,条件必须一致。
供电边界尤其不能由理想运放模型代替。TI SLOS080 Rev.W 的推荐条件对相应传统器件列出输入电压下限为 VCC−+4V;原图在 9~12V 输入后还串有二极管,低端供电时,VCC/2 与这个下限之间的裕量应按真实 VCC 检查。
数据手册传统 TL07xI 的直流、交流特性表大多以±15V、25℃等条件给出;不能把这些条件下的输出摆幅、失真数字直接搬到本板单电源、1kΩ 负载的场景。还要检查去耦、未用运放的处理、输出电流及高 Q 下有限开环增益造成的偏差。本文没有完成这些实体测试,也没有给出整板 ERC/DRC 或硬件达标结论。
工程与验证范围
参考工程入口及原始工程文件 https://oshwhub.com/course-examples/bo-xing-chan-sheng-yu-bian-huan-she-ji-555-yun-fang
工程页标示 GPL 3.0;原理图署名 EDAmake/立创EDA,SCH Rev1.0,2021-11-23。原理图、PCB 来自同一工程的实际 EDA 导出,保留源文件和署名;原理图仅作字体兼容处理及局部裁切,PCB 标明观察方向,未修改线网。
器件资料 TI TL07xx 数据手册 SLOS080 Rev.W https://www.ti.com/document-viewer/TL072/datasheet
本文独立完成理想小信号建模、调谐反算、代码与数值交叉核验;独立代码按 MIT 许可提供,原工程继续遵循 GPL 3.0。计算不含有限带宽、输出限流、器件非线性和电源噪声,硬件未改版、未上板。
平台的 CC BY 选项仅适用于本文独立文字;独立代码采用 MIT 许可,第三方工程与 EDA 图继续遵循上游 GPL 3.0,均不因平台选项改变许可。
技术交流,欢迎关注微信公众号:美男子玩编程。



