3、张弛振荡器法:原理、频率测量与电容变化
张弛振荡器法,说白了就是利用电容的充放电特性,把电容值的变化转换成频率信号。我在做触控按键的早期项目时,这个方法帮我解决了不少难题。今天咱们就把它掰开揉碎了讲清楚。
3.1 张弛振荡器的基本原理
张弛振荡器的核心思想很简单:用一个恒流源给电容充电,充到某个阈值就放电,放完再充。这样反复循环,就产生了方波信号。你想想看,电容值变了,充放电时间自然就变了,频率也就跟着变了。
我习惯把张弛振荡器分成三个部分来看:
- 充电回路:恒流源或电阻给电容充电
- 比较器:检测电容电压是否达到阈值
- 放电开关:达到阈值后快速放电
嗯,这里要注意:实际电路中,比较器会有迟滞,防止在阈值附近来回跳变。我曾经在一个项目中忽略了这一点,结果频率读数乱跳,排查了半天才发现是比较器没有加迟滞。
核心公式:振荡频率 f = 1 / (2 × R × C × ln(2))
对于恒流源充电:f = I / (2 × C × Vth)
为什么会这样?因为电容充电遵循指数规律,时间常数 τ = RC。电容越大,充到同样电压需要的时间就越长,频率就越低。这个关系是线性的吗?其实不是,但我们可以通过电路设计让它近似线性。
3.2 频率测量方法
频率测量,说白了就是数脉冲。我常用的方法有两种:
| 测量方法 | 原理 | 适用场景 |
|---|---|---|
| 直接计数法 | 固定时间内数脉冲个数 | 频率较高时(>1kHz) |
| 周期测量法 | 测量单个脉冲的周期 | 频率较低时(<1kHz) |
我个人习惯在触摸应用中用周期测量法。为什么?因为触摸传感器的电容变化通常很小,只有几皮法到几十皮法。频率变化可能只有几十赫兹。直接计数法需要很长的测量时间,响应就慢了。
周期测量法的做法是:用高频时钟去数一个脉冲周期内有多少个时钟周期。比如系统时钟是 48MHz,振荡器输出 100kHz,那么一个周期内就有 480 个时钟周期。电容变化 1pF,周期可能变化 2-3 个时钟周期,分辨率足够了。
我的经验:测量时间要权衡。测量时间越长,分辨率越高,但响应越慢。触摸应用中,我通常把测量时间控制在 5-10ms 之间,既能保证分辨率,又不会让用户感觉到延迟。
3.3 电容变化与频率的关系
咱们来看一个实际例子。假设电路参数如下:
- 充电电阻 R = 10kΩ
- 阈值电压 Vth = 1.65V(电源电压 3.3V 的一半)
- 基准电容 C0 = 10pF
根据公式 f = 1 / (2 × R × C × ln(2)),计算得到:
| 电容值 (pF) | 频率 (kHz) | 频率变化 (Hz) |
|---|---|---|
| 10 | 72.13 | — |
| 11 | 65.57 | -6560 |
| 12 | 60.11 | -12020 |
| 13 | 55.48 | -16650 |
你看,电容从 10pF 变到 11pF,频率下降了 6.56kHz。这个变化量足够大,用普通的单片机定时器就能测出来。我曾经做过一个项目,手指触摸时电容变化只有 0.5pF,频率变化约 3kHz,用 16 位定时器测量,分辨率完全够用。
注意:频率与电容不是线性关系,而是反比关系。这意味着电容越大,频率变化越不敏感。所以张弛振荡器法更适合小电容范围(1pF - 100pF)的测量。如果电容太大,建议改用其他方法。
3.4 实际电路设计要点
做张弛振荡器电路时,有几个坑我踩过,分享给你:
- 寄生电容:PCB 走线、芯片引脚都有寄生电容,可能几皮法到十几皮法。这些寄生电容会叠加到测量结果中,而且随温度变化。我习惯在软件中做校准,减去基准值。
- 电源噪声:比较器的阈值电压受电源影响。如果电源有纹波,频率就会抖动。建议用 LDO 单独给振荡器供电,或者用基准电压源。
- 温度漂移:电阻和电容都有温度系数。普通贴片电阻温度系数约 100ppm/°C,电容更大。如果产品要在 -20°C 到 60°C 范围内工作,频率可能漂移 5% 以上。我一般用 NPO 电容和金属膜电阻,温度系数可以控制在 50ppm/°C 以内。
嗯,还有一个细节:放电开关要用 NMOS 管,导通电阻要小,否则放电不彻底,会影响下一次充电的起始点。我曾经用了一个导通电阻 10Ω 的 MOS 管,结果频率稳定性很差,换成 0.5Ω 的就好了。
3.5 软件实现示例
下面是一个简单的频率测量代码,用 STM32 的定时器实现周期测量:
// 定时器配置:输入捕获模式,上升沿触发
void TIM_Config(void) {
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
// 中断服务函数:计算周期
uint32_t capture1 = 0, capture2 = 0;
uint32_t period = 0;
void TIM2_IRQHandler(void) {
if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
capture1 = capture2;
capture2 = TIM_GetCapture1(TIM2);
period = capture2 - capture1; // 周期值,单位:时钟周期数
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
}
}
// 计算电容值
float Calculate_Capacitance(uint32_t period, uint32_t sys_clk) {
float freq = (float)sys_clk / period;
float capacitance = 1.0 / (2 * 10000 * freq * 0.693); // R=10kΩ
return capacitance * 1e12; // 返回 pF 单位
}
这段代码我实际用过,效果不错。注意 period 是 32 位无符号整数,如果系统时钟 48MHz,最大可测周期约 89 秒,完全够用。
3.6 知识体系总结
为了让你更直观地理解张弛振荡器法的全貌,我画了一张流程图:
从这张图你可以看到,张弛振荡器法的核心就是通过充放电产生频率信号,然后测量频率,最后反推出电容值。每一步都有需要注意的细节,比如比较器要加迟滞、测量方法要根据频率范围选择、计算时要考虑寄生电容等。
好了,这一章的内容就到这里。张弛振荡器法虽然经典,但用好了效果非常好。我在多个量产项目中都用过这个方法,稳定性和精度都经得起考验。