反跳(Bounce)处理,也常被称为“消抖”,在不少帖子里面被讨论。本帖力求更详尽更具体。
方法1:模拟电路滤波法
模拟滤波电路不用解释,人尽皆知。表面上看,只要时间常数选取合理模拟法就可以把信号处理得很“干净”,从根本上消除反跳。然而,当反跳现象比较严重时,滤波电路时间常数较大,这不可避免地带来了滤波后信号上升或下降缓慢的问题。缓慢变化的信号就使得信号在变化的过程中“长期”处于大于数字信号0电平而低于信号1电平的中间禁带区域,这带来了两个问题。一是信号在非0非1的状态时的电压波动,会使数字电路判决值在0和1之间翻转,即,此时反跳并未被消除而依然存在,只是在一定程度上减弱了反跳现象。另外一个,也是更重要的问题是从数字器件引脚电路来讲的。对于对管结构的CMOS输入来说,正常工作在1或0状态时总是一个管子导通另一个管子截止,输入引脚耗电很小。而处于中间电平时会导致上拉和下拉管同时导通,引脚耗电增大。这也是为什么FPGA的功耗和信号的toggle率有关系,信号0和1变化瞬间会有电流从电源到地。输入长时间停留在非0非1的状态,会导致输入亚稳态的产生和传递,轻则导致器件内部逻辑出错,重则导致引脚损坏。也许现在FPGA或CPU对输入的处理上应用了更加复杂的电路,不存在上述顾虑。如叙述不当,欢迎指正。
模拟滤波法更适合于滤除短时的毛刺干扰。
方法2:锁存器法
鉴于发帖贴图比较麻烦,这里用语言描述一个电路。一个单刀双掷开关K有两个触点R和S,刀K接地,触点R和S分别接上拉电阻。当K接R时,R=0且S=1;反之K接S时S=0且R=1。
当K由R转接到S时,R和S变化过程如下:起始R=0,S=1;接着K离开R导致R在0和1间反跳但S保持1不变;K完全离开R尚未到达S,此时R=S=1;K接触到S,R保持1不变,S在0和1之间反跳;最后稳定在R=1,S=0状态。
现在需求是用单刀双掷开关实现表决电路,K接R表示0,K接S表示1。那么用一个RS锁存器便实现了上述功能。根据RS锁存器的真值表可以看出,锁存器输出Q在K接触到S时由0跳变为1并锁存在1状态不受反跳的影响。或者等效地说,锁存器滤除了反跳。单刀双掷开关可以用两个按钮来代替,一个是S按钮一个是R按钮。锁存器法同样适用于多个S按钮公用一个R按钮的情形。
锁存器法的优点是电路轻巧,事件输出几乎无延时。其缺点是需要额外增加一个R复位按键,并且不适合于判断持续按下按键的状态。
方法3:多数判决法
多数判决法使用一个串入串出的移位寄存器reg,按照某一时钟节拍读取按键值依次移入reg。当reg中1的个数超过0的个数时判决输入为1,反之判决为0。或者采用迟滞判决的方法,当reg全1时判决输入为1,全0时判决输入为0,否则保持判决值不变。
多数判决法在滤除长时间反跳时需要消耗过多的资源,适合于滤除稀疏反跳。
方法4:限幅积分+迟滞比较法
方法4是更为通用的方法,也是本帖着力介绍的方法。
限幅积分和迟滞比较的概念来自于模拟电路,在数字电路中我们把这两个概念极限化。限幅积分使用一个积分器cn,在输入信号S=1时加一计数,当cn计数到全1时停止;在S=0时cn减一计数,直到全0时停止。加1和减1过程本质上等同于积分,而设置最大值全1和最小值全0等效于限幅,顾称限幅积分。在模拟电路的比较器中,使用两个判决电平VH和VL(VH > VL),当输入信号S>VH时输出翻转到高电平,而在S<VL后翻转到低电平,S在VL和VH之间时比较器输出保持不变。这种比较器在模电中被称为迟滞比较器。数字电路中我们采用同样的方法,当cn为全1时判决输入为1,当cn为全0时判决输入为0,其他情况判决值保持不变。
上述过程,用VHDL语言描述为:
Process(clock) begin
if rising_edge(clock)then
1. SI <= S;
2. LimIntegral(cn_bounce, SI, en);
3. SetReset(s_noBounce,b_and(cn_bounce), b_nor(cn_bounce));
end if;
End process;
行1:增加同步信号SI,其作用如011帖准则4所述。
行2:限幅积分,cn_bounce为积分计数器;en用于控制积分节拍,en恒1则每个时钟累加积分一次。
行3:迟滞比较,得到去除跳弹后的信号s_noBounce。
其中LimIntegral,SetReset,b_and和b_nor均已在ucx_2008.pkg中定义,不作赘述。
方法4的输出s_noBounce相对于输入信号S有较大时延,从滤波的因果关系来讲这是不可避免的。cn_bounce的位宽以及en共同作用影响了时延的大小,需要滤除的反跳越宽时延越大,使用时应当注意。
多输入反跳处理当存在多个带有反跳现象的输入时,如何处理呢?首先容易想到的是每个引脚分别独立按上述方法处理。各自处理的方法,对每条输入都消耗一个积分器和一个判决器,从而消耗了过多的资源。如果这些输入反跳统计特性相同且存在共同的无反跳无变化时间,那么可以把这些输入看作总线输入B。只使用一个积分计数器cn,在B的当前值与先前值不同时cn清零,否则累加积分cn直至全1,那么在cn全1状态并行读取所有输入即获得所有输入去抖后的信号。
|