系统的信号输入中,键盘因其结构简单而被广泛使用。因此,对键盘的输入(逻辑0或1)进行准确采样,避免错误输入是非常有必要的。理想的键盘输入特性如图1所示:按键没有按下时,输入为逻辑1,一旦按下则输入立刻变为逻辑0,松开时输入则立刻变为逻辑1。
图 1理想键盘输入特性
然而实际的键盘受制造工艺等影响,其输入特性不可能如图1完美。当按键按下时,在触点即将接触到完全接触这段时间里,键盘的通断状态很可能已经改变了多次。即在这段时间里,键盘输入了多次逻辑0和1,也就是输入处于失控状态。如果这些输入被系统响应,则系统暂时也将处于失控状态,这是我们要尽量避免的。在触点即将分离到完全分离这段时间也是一样的。实际键盘的输入特性如图2所示:
图 2实际键盘输入特性
我们可以看到:键盘在输入逻辑转换时,实际上是产生了瞬时的高频干扰脉冲。按键消抖的目的在于消除此干扰,以达到接近图1所示的理想输入特性。有两个阶段可以设法消除此干扰:1.在键盘信号输入系统之前(系统外);2.键盘信号输入系统以后(系统内)。
在信号输入系统之前将抖动干扰消除,可以节省系统资源,提高系统对其他信号的响应能力,也就是硬件消抖。一种比较巧妙的硬件消抖电路结构如图3所示:
图 3用基本sr锁存器构成的消抖电路
该电路利用基本sr锁存器的记忆作用消除开关触点振动所产生的影响。开关s每切换一次,输出端只有一次翻转,不存在抖动波形(读者可以根据sr锁存器功能自行分析,此处略)。但是使用sr锁存器消抖只适用于单刀双掷开关,实际应用当中常用的键盘多是两个接线端的按键。对此类按键的常用硬件消抖电路如图4所示:
图 4常用键盘硬件消抖电路
此电路利用电容平波,再经过施密特反相器整形之后就得到了没有毛刺的脉冲波。
软件消抖要占用系统资源,在系统资源充足的情况下使用软件消抖更加简单。软件消抖的实质在于降低键盘输入端口的采样频率,将高频抖动略去。实际应用中通常采用延时跳过高频抖动区间,然后再检测输入做出相应处理。一般程序代码如下:
if(value == 0)//一旦检测到键值
{
delay();//延时20ms,有效滤除按键的抖动
if(value == 0)//再次确定键值是否有效
{
……//执行相应处理
}
}
这段软消抖程序从机理上看不会有什么问题,通常在软件程序不太繁忙的情况下也能够很好的消抖并做相应处理。但是如果在延时期间产生了中断,则此中断可能无法得到响应。
对于硬件资源丰富的fpga系统,可以使用硬件来减轻软件工作量,通常称之为硬件加速。在按键信号输入到软件系统前用逻辑对其进行一下简单的处理即可实现所谓的硬件消抖,verilog代码如下:
//对输入信号inpio硬件滤波,每20ms采样一次当前值
reg[18:0] cnt; //20ms计数器
always @(posedge clk_25m or negedge rst_n)
if(!rst_n) cnt <= 19'd0;
else if(cnt < 19'd500000) cnt <= cnt+1'b1;
else cnt <= 19'd0;
reg[1:0] inpior;//当前inpio信号锁存,每20ms锁存一拍
always @(posedge clk_25m or negedge rst_n)
if(!rst_n) inpior <= 2'b11;
else if(cnt == 19'h7ffff) inpior <= {inpior[0],inpior};
wire inpio_swin =inpior[0] | inpior[1];//前后20ms两次锁存值都为0时才为0
该程序中设置了一个20ms计数器,通过间隔20ms对输入信号inpio采样两次,两次相同则认为键盘输入稳定,得到用硬件逻辑处理后的inpio_swin信号则是消抖处理过的信号。软件程序就不再需要delay()来滤波了,也不会出现使用纯软件处理出现的中断失去响应的情况了,这就是硬件加速的效果。
上述verilog代码采用间隔采样来达到消抖的目的,对于不同物理特性的键盘,最佳的间隔时间采样时间也不同,因此还存在一些不稳定因素。下面介绍一种更好的软消抖程序,同样采用硬件加速,不同之处在于使用了有限状态机来实现,其vhdl代码如下:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity xiaod is
//端口描述:clk输入检测时钟;reset复位信号;din原始按键信号输入;dout去抖动输出信号
port
(
clk : in std_logic ;
reset : in std_logic ;
din : in std_logic ;
dout : out std_logic
);
end entity;
architecture rtl of xiaod is
type state is( s0,s1,s2,s3);
signal pre_s, next_s: state;
begin
p0:process( reset, clk )
begin
if reset = '0' then
pre_s <= s0;
elsif rising_edge( clk ) then
pre_s
dout <= '1';
if din = '1' then
next_s <= s0;
else
next_s
dout <= '1';
if din = '1' then
next_s <= s0;
else
next_s
dout <= '1';
if din = '1' then
next_s <= s0;
else
next_s
dout <= '0';
if din = '1' then
next_s <= s0;
else
next_s <= s1;
end if;
end case;
end process p1;
end rtl;
该vhdl代码描述了一个状态机,其状态转换图如图所示:
图 5状态转换图
该状态机有4个状态:s0、s1、s2、s3,其中前3个状态输出高电平,最后一个状态输出低电平。初始状态为s0,设按键未按下时为高电平,按下则为低电平。在按键按下到完全生效期间有一系列的抖动,对于持续时间为1-2个时钟周期的低电平抖动将被消除,对于持续时间为3个或以上时钟周期的低电平则认为按键有效,输出一个时钟周期的低电平脉冲(读者可以根据状态转换图画出相应的时序图进行分析)。如果持续输入为低电平,则每隔两个时钟周期输出一个低电平,此时认为按键处于长按输入状态,可以编程设置相应功能。在按键松开阶段其抖动也可以一样被消除。
适用于fpga的按键消抖方法还有一些,如计数器型、d触发器型等,在此就不作介绍了。
通过上面一些按键消抖方法的介绍分析,我们可以看到,传统单片机等系统大多是串行处理,即顺序执行,只能并行处理一些中断程序。对于这样的系统,只能采用单纯软件或硬件消抖,但都不那么完美。而对于fpga等并行处理的系统,其优势就很明显,只要片内逻辑资源够用,通过硬件加速软件消抖的处理,完全可以做到按键消抖并行化,不影响系统的实时性。
诺基亚9迭代版曝光 搭载骁龙855或在2019年8月发布
高容量嵌入式存储将与手机插槽展开竞争
浅谈微型扬声器粘接应用中无影胶逐渐取代溶剂胶水的原因
通过网络搭建零信任架构的方法
土壤测试仪能测试哪些项目
系统的信号输入中,键盘因其结构简单而被广泛使用
凯米斯低功耗在线浊度传感器的解决方案
OceanBase的简介,它与MySQL的比较
区块链技术将如何改变我们的生活?
未来Micro LED将走向混合式转移
IDRS分布式网络远程监控系统的特点性能及应用设计
动力电池激光焊接技术应用解决方案
基于以太网技术的智能电机管理单元在化工行业的应用
Linux 内存管理:进程的内存申请与分配
光纤链路在数据中心中的应用
智行者立足自动驾驶自动车中央决策系统开发及大系统集成
2019年物联网时代具有附加值的4大行业
苹果自研5G芯片什么时候才能推出?
善用微处理器简化电源供应器设计
浅谈可再生能源