硬件消抖原理:RC滤波电路消抖、RS触发器消抖、硬件消抖的优缺点

各位同学,咱们接着聊按键消抖。

上一章我讲了软件消抖,说白了就是用延时去“躲”抖动。但有些场景下,软件消抖并不好用。比如你的系统里CPU忙得要死,或者你压根儿不想让代码去处理这种“脏活”。这时候,就该硬件消抖上场了。

硬件消抖,就是用电路本身把抖动“吃掉”。你按下去,电路直接给你一个干净的电平。FPGA这边读到的,就是稳稳当当的0或1。

我个人习惯是:能硬件消抖,尽量硬件消抖。为什么?因为省心,不占CPU资源,而且响应快。你想想看,一个RC滤波电路才几个元件?成本低,效果好。

RC滤波电路消抖

这是最经典的硬件消抖方案。原理很简单——利用电容的充放电特性,把快速变化的抖动信号“抹平”。

抖动是什么?是高频的毛刺。电容对高频信号阻抗低,对低频信号阻抗高。所以高频抖动会被电容吸收掉,剩下的就是低频的按键动作。

具体电路长这样:

VCC
  |
  R1
  |
  +-----> 输出到FPGA
  |
  C1
  |
 GND

按键接在VCC和R1之间。按下时,VCC通过R1给C1充电。松开时,C1通过R1放电。R1和C1组成一个低通滤波器,时间常数τ = R1 × C1。

这个τ值很关键。我一般选τ在10ms到20ms之间。为什么是这个范围?因为机械按键的抖动时间通常在5ms到10ms,τ选大一点,就能把抖动完全滤掉。

举个例子:R1取10kΩ,C1取1μF,τ = 10ms。这个组合我用了很多年,效果很稳。

关键参数计算

  • 时间常数 τ = R × C
  • 一般取 τ = 10ms ~ 20ms
  • R 常用 1kΩ ~ 100kΩ
  • C 常用 0.1μF ~ 10μF

嗯,这里要注意:RC滤波后的信号是模拟信号,不是数字信号。FPGA的IO口读到的电平,可能会在阈值附近“犹豫”。所以建议在FPGA内部再加一级施密特触发器,或者用FPGA的IO口自带的施密特触发功能。

我的小技巧

如果FPGA的IO口支持施密特触发,直接开启就行。如果不支持,可以在RC后面加一个74HC14施密特反相器。我在一个工业控制项目里就这么干过,效果非常好,再也没有误触发过。

RS触发器消抖

RC滤波虽然好用,但有个缺点——它需要电容,电容体积大,而且精度不高。在一些对体积敏感或者对时序要求高的场合,RS触发器消抖更合适。

RS触发器消抖的原理,说白了就是利用触发器的“记忆”功能。按键按下时,触发器锁住一个状态;松开时,锁住另一个状态。抖动期间,触发器不会翻转,因为触发器的输出只取决于输入信号的边沿,而不是电平的毛刺。

电路图是这样的:

按键A ——|S   Q|—— 输出
         |    |
按键B ——|R   Q'|
         |____|

按键A和B是同一个按键的两个触点,一个常开,一个常闭。按下时,A闭合,B断开,S端为高电平,Q输出高。松开时,A断开,B闭合,R端为高电平,Q输出低。抖动期间,A和B会同时抖动,但触发器只认第一个有效的边沿,后面的抖动都被“无视”了。

我记得有一次做手持设备,空间特别小,放不下RC的电容。我就用了RS触发器方案,用两个与非门搭了一个。效果出奇的好,而且几乎不占PCB面积。

注意

RS触发器消抖要求按键必须有常开和常闭两个触点。普通的轻触开关只有一对触点,用不了这个方案。只有那种三脚或四脚的按键开关才支持。买元件的时候一定要看清楚规格书。

硬件消抖的优缺点

聊了这么多,咱们来总结一下硬件消抖的优缺点。我直接列个表,一目了然。

对比项 RC滤波消抖 RS触发器消抖
元件数量 2个(电阻+电容) 1个芯片(或2个门电路)
PCB面积 较大(电容体积大) 较小(芯片体积小)
响应速度 较慢(有充放电时间) 快(边沿触发)
抗干扰能力 一般(电容易受温度影响) 强(数字电路稳定)
适用场景 对成本敏感、空间充裕 对体积敏感、要求快速响应

硬件消抖的总体优点

  • 不占用CPU/FPGA逻辑资源
  • 响应速度快,没有软件延时
  • 可靠性高,不受程序跑飞影响
  • 适合多按键场景(每个按键独立消抖)

硬件消抖的总体缺点

  • 增加BOM成本和PCB面积
  • RC滤波的电容值受温度影响,精度不高
  • RS触发器需要特殊按键(双触点)
  • 一旦焊接好,参数无法修改(不如软件灵活)

我曾经在一个项目中,一开始用了软件消抖,后来发现CPU太忙,按键响应延迟很大。改成RC硬件消抖后,问题立刻解决。但后来产品升级,需要增加按键数量,PCB空间不够了,我又换成了RS触发器方案。你看,没有绝对的好方案,只有适合的方案。

最后说一句:硬件消抖和软件消抖不是互斥的。我经常在项目中两者结合使用——硬件做粗消抖,软件做细消抖。比如RC滤波把大部分抖动滤掉,FPGA内部再用一个简单的状态机做边沿检测。这样既省资源,又可靠。

嗯,这一章就到这里。下一章咱们聊聊FPGA内部怎么实现消抖,以及怎么用Verilog写一个通用的消抖模块。到时候我会分享一个我用了好几年的代码模板,直接复制就能用。