2. 消抖原理:硬件消抖(RC滤波)与软件消抖(延时采样)的对比
按键抖动,说白了就是机械触点闭合瞬间的「弹跳」。你按下去,它不会老老实实稳定住,而是会来回弹几下。我刚开始做FPGA时,就被这个现象坑过——明明只按了一次,系统却检测到了三四次触发。
为什么会这样?因为机械按键内部是金属弹片。按下时,弹片会振动,产生一连串的脉冲信号。这个抖动时间通常持续5-20ms。嗯,这里要注意,不同按键的抖动时间差异很大,便宜的按键可能抖得更久。
解决抖动,无非两条路:硬件上做RC滤波,或者软件上做延时采样。我两种方法都用过,今天跟你聊聊各自的优缺点。
2.1 硬件消抖:RC低通滤波
硬件消抖的原理很简单——用电容把高频抖动滤掉。你想想看,抖动信号频率高,电容对高频信号阻抗低,直接把它旁路到地了。剩下的就是稳定的电平变化。
典型的RC电路长这样:
VCC —— 按键 —— R1 —— 输出点 —— 到FPGA引脚
|
R2
|
GND
|
C1
|
GND
R1和R2构成分压,C1是滤波电容。时间常数τ = (R1//R2) × C1。我一般取τ在10ms左右,这样既能滤掉抖动,又不会让按键响应太迟钝。
参数选择建议:
- R1 = 10kΩ,R2 = 10kΩ,C1 = 1μF → τ ≈ 5ms
- R1 = 4.7kΩ,R2 = 4.7kΩ,C1 = 2.2μF → τ ≈ 10ms
- R1 = 1kΩ,R2 = 1kΩ,C1 = 10μF → τ ≈ 20ms
硬件消抖的好处是零CPU开销,信号进来就是干净的。但缺点也很明显——需要额外元件,而且一旦焊好,参数就固定了。如果你换了个抖动特性不同的按键,就得重新改电路。
2.2 软件消抖:延时采样
软件消抖,说白了就是「等它抖完再读」。FPGA里没有CPU那种延时函数,但我们有计数器。核心思路是:检测到电平变化后,启动一个计数器,等10-20ms后再采样一次。如果两次采样结果一致,就认为按键稳定了。
我常用的三段式状态机写法:
// 按键消抖模块 - 延时采样法
module debounce (
input wire clk, // 系统时钟,假设50MHz
input wire rst_n, // 复位
input wire key_in, // 按键输入
output reg key_out // 消抖后输出
);
// 20ms延时需要的计数次数
// 50MHz → 20ns周期,20ms = 1_000_000个时钟周期
localparam CNT_MAX = 20'd1_000_000;
reg [19:0] cnt;
reg key_sync; // 同步后的按键值
reg key_last; // 上一次的按键值
// 两级同步,消除亚稳态
reg key_sync_1, key_sync_2;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
key_sync_1 <= 1'b1;
key_sync_2 <= 1'b1;
end else begin
key_sync_1 <= key_in;
key_sync_2 <= key_sync_1;
end
end
assign key_sync = key_sync_2;
// 消抖逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 20'd0;
key_last <= 1'b1;
key_out <= 1'b1;
end else begin
key_last <= key_sync;
// 检测到电平变化,启动计数器
if (key_sync != key_last) begin
cnt <= 20'd0;
end
// 计数器未满,继续计数
else if (cnt < CNT_MAX) begin
cnt <= cnt + 1'b1;
end
// 计数器满,输出稳定值
else begin
key_out <= key_sync;
end
end
end
endmodule
软件消抖的好处是零成本,改参数也方便。想调延时?改一下CNT_MAX就行。但缺点也明显——占用FPGA逻辑资源,而且如果系统时钟变了,延时时间也会变。
2.3 两种方案的对比
| 对比项 | 硬件消抖(RC滤波) | 软件消抖(延时采样) |
|---|---|---|
| 成本 | 需要电阻电容,增加BOM | 零额外成本 |
| 灵活性 | 参数固定,改起来麻烦 | 改代码即可,非常灵活 |
| 资源占用 | 不占FPGA资源 | 需要计数器、状态机 |
| 可靠性 | 抗干扰能力强 | 受时钟抖动影响 |
| 响应速度 | 取决于RC时间常数 | 取决于采样延时 |
| 适用场景 | 工业环境、对可靠性要求高 | 消费电子、快速原型验证 |
2.4 我的选择建议
说实话,没有的好坏。我个人的习惯是:
- 做开发板、原型验证 → 用软件消抖。改起来快,不用动烙铁。
- 做产品、尤其是工业产品 → 用硬件消抖。RC滤波抗干扰能力强,电源噪声、电磁干扰都不容易误触发。
- 如果按键数量多 → 用软件消抖。一个模块可以复用,省PCB面积。
你想想看,一个产品上如果有8个按键,每个按键配两个电阻一个电容,那就是24个元件。而用FPGA软件消抖,一个模块例化8次就搞定了。但反过来,如果只有一个电源按键,加个RC滤波反而更省事。
下面这张图,是我总结的消抖方案选择逻辑:
最后说一句,不管选哪种方案,同步器一定要加。这是FPGA设计的铁律——任何外部信号进FPGA,必须先过两级同步。我见过太多人在这上面栽跟头了。
好了,消抖原理就聊到这儿。下一节我们会上板实战,把代码下载到FPGA里,看看实际效果。到时候你会发现,理论说得再好,不如动手调一次来得实在。