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 实际电路设计要点

做张弛振荡器电路时,有几个坑我踩过,分享给你:

  1. 寄生电容:PCB 走线、芯片引脚都有寄生电容,可能几皮法到十几皮法。这些寄生电容会叠加到测量结果中,而且随温度变化。我习惯在软件中做校准,减去基准值。
  2. 电源噪声:比较器的阈值电压受电源影响。如果电源有纹波,频率就会抖动。建议用 LDO 单独给振荡器供电,或者用基准电压源。
  3. 温度漂移:电阻和电容都有温度系数。普通贴片电阻温度系数约 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 知识体系总结

为了让你更直观地理解张弛振荡器法的全貌,我画了一张流程图:

张弛振荡器法知识体系 张弛振荡器 充电回路 比较器(带迟滞) 放电开关 直接计数法 周期测量法 电容值计算 核心公式:f = 1 / (2 × R × C × ln(2))

从这张图你可以看到,张弛振荡器法的核心就是通过充放电产生频率信号,然后测量频率,最后反推出电容值。每一步都有需要注意的细节,比如比较器要加迟滞、测量方法要根据频率范围选择、计算时要考虑寄生电容等。

好了,这一章的内容就到这里。张弛振荡器法虽然经典,但用好了效果非常好。我在多个量产项目中都用过这个方法,稳定性和精度都经得起考验。