按键消抖在单片机和FPGA实验教学中的应用
2018-08-11徐能谋张海峰通讯作者
徐能谋 张海峰( 通讯作者)
引言:按键作为当今许多智能设备、计算机和工业控制领域的人机接口,为了能让按键稳定有效的工作,按键消抖一直是在使用按键时必须解决的。在长期的科研与教学实践过程中,按键消抖往往是高校学生在刚开始学习按键时比较难处理的问题。初学者即使掌握一些延时等按键消抖方法,但在实际应用的过程中还是经常会出现消抖不完全等问题,特别是利用单片机做一些大项目的时候,往往会出现不同的模块之间相互干扰,进而导致整个系统不正常工作;在进入到EDA课程的学习中,在面对FPGA的按键消抖时,很多学生又会不知所措,无法用硬件描述语言去生成一个合适的消抖电路。因此,在单片机和FPGA实验教学中,让学生掌握好按键消抖对提升学生的学习能力和思维方式有着重要意义。
无论是矩阵按键还是独立按键,在实际使用时,必须经过消抖处理。在单片机中,按键消抖可以通过延时、定时器等实现;在FPGA中可以则使用边沿检测的方法实现按键消抖,就按键消抖原理而言,和单片机的延时消抖没有区别。但是,在单片机与FPGA中,按键消抖的具体实现方法有不同之处。除了本文中介绍的按键去抖动的方法之外,还有很多处理按键抖动的方法,例如使用状态机来写按键消抖,在单片机和FPGA中都有着很好的消抖效果。
1 按键消抖原理
在单片机和FPGA实验教学中,按键是经常需要使用的重要模块。按键通常有机械触点,当按键在闭合或者断开的瞬间,都会出现抖动。抖动的时间在5~10ms内,为了确保抖动完全被消除,本文采用消抖时间为20ms。在按键按下和放开时,按键的前沿抖动和后沿抖动如图1所示。
图1
按键消抖可以分为硬件消抖和软件消抖两大类。去抖动的原理基本相似,都是通过一定的方式,记录下最开始按键按下时的状态,然后经过一定的延时,渡过按键的抖动时间之后,再比较此时按键的状态是否与延时之前的状态相同,如果是相同的,那么就可以确定按键的确被按下;如果不同,则说明是抖动。在单片机中,通过与按键连接的I/O口电平来判断状态,延时则可以使用延时子程序实现,也可以通过计时器实现;在FPGA中,延时可以通过编写硬件描述语言,例如Verilog HDL等,生成一个硬件去抖动电路。
2 单片机按键消抖
2.1 单片机按键硬件消抖
在单片机的教学实践中,常用的硬件去抖动的方法是在按键两端并联小电容,可以起到一定的去抖动的作用。利用电容的充放电特性来对抖动过程中产生电压毛刺进行平滑处理,从而实现按键消抖。但是同样也存在明显的缺点,这种消抖方式的效果往往不是很好,而且还增加了成本和电路复杂度,所以,在实际应用中使用的并不多。
2.2 单片机按键软件消抖
软件延时函数延时去抖动方式在程序较小、程序规模不大、单片机连接的外设不多时,去抖动的效果很好。但是,在使用单片机开发程序规模和单片机连接多个外设时,采用延时函数去抖动有着很明显的缺陷。首先,单片机的CPU资源非常少,延时消抖与等待释放需要消耗 CPU 运行时间,执行效率低下;其次,当按键按下的时候,CPU相当于一直在等待延时和释放,执行空语句,从而会导致单片机系统中的其他外设由于得不到CPU资源无法正常工作。
软件延时函数延时去抖动在面对规模较大的单片机开发时,缺点太突出,使得CPU使用效率下降。因此,当在进行较大规模单片机开发时,可以采用定时中断来实现按键的去抖动,从而解决CPU利用率低的问题。不过,随之出现的问题是,单片机的中断源相对较少,因此,在单片机中采用软件消抖时应考虑实际情况选择合适的按键去抖动方案。
2.2.1 延时消抖
软件延时消抖的原理,就是当检测到按键状态变化之后,先延时等待20ms,让抖动消失之后再进行一次按键状态检测,如果与刚才检测到的状态相同,就可以确认按键已经稳定的动作了。下面是软件延时消抖的参考程序:
//按键软件延时消抖
void key_deal(keyin)
{
if(keyin==0)//按键刚刚按下
{
delay(20);// 延时 20ms
if(keyin==0)//确认按键被按下
{
while(keyin==0) ;//等待按键释放
keyout=0;//此时按键抖动已去除
}
else keyout=1;
}
else keyout=1;
}
上面的程序是一个简单的按键延时消抖程序,作为一个简单延时消抖例程。但是,在实际的单片机做项目开发时,程序往往很大,状态值也很多,主程序要不停的进行扫描,判断各种状态值是否发生变化,及时的进行任务调度,但是,delay语句会导致CPU被占用,主程序得不到执行,如果外部时间恰好在程序执行delay语句中发生,这样很容易使的单片机丢失部分数据,最终导致系统不正常工作。
2.2.2 定时中断消抖
为了解决软件延时消抖带来的弊端,同时又要完成按键去抖动,此时,可以采用定时中断方式实现按键消抖。定时中断消抖很好的避免了延时消抖中占用单片机的执行时间,当主程序检测到按键被按下时,开启定时器,定时时间设置为20ms,当到达定时时间之后将定时标志位置1。在主程序中,检测到定时标志为置1之后停止定时器,同时判断按键是否仍然被按下,如果是,那么按键消抖完成并且按键已经稳定,否则按键没有被成功按下。
虽然定时中断消抖可以解决延时消抖的弊端,但是在实际应用过程中,单片机的中断源相对少,当工程项目很大时,中断源将会不够用,此时,定时中断消抖显然不太合适。为了解决定时中断消抖在面对中断源较少时的情况,还可以采用状态机的方法实现按键消抖。
3 FPGA按键消抖
在FPGA开发中,硬件去抖动电路时十分常用,利用硬件描述语言,可以直接生成硬件去抖动的电路。与单片机中的按键消抖相比,FPGA最大的优势在与电路的可靠性高,而不像单片机十分依赖于软件,并且,生成的所有硬件都可以并行运行,没有单片机串行运行的限制。因此,在FPGA中做硬件去抖动电路比在单片机上做要更简单。
采用与单片机软件消抖的原理,FPGA中按键消抖的基本思想是:首先,外部需要提供一个时钟,然后每个时钟上升沿都来的时候都去检查看按键状态是否发生变化,如果变化,则相应的计数器启动,当计数器记满一定时间并且期间按键值没有变化时,说明此时的按键值是稳定的,可以读取。然后根据去抖动之后的按键值的变化做相应的功能处理。
在FPGA中,采用延时消抖有两种方法,一种是将抖动时间计算在延时时间内,从按键按下开始,计时器工作,当计数满足20ms之后,判断按键是否仍然被按下,从而实现按键消抖。下面是使用Verilog HDL编写的按键消抖参考程序:
always @(posedge CLK_1kHz)
begin
if(keyin==0 & KL==0)
KL<=1;
else if(KL>0 & KL<20)
KL<=KL+1;
else if(KL==20 & keyin==0)
begin keyout<=1`b0;KL<=0;end
else
keyout<=1`b1;
end
同时,利用Maxplus II对程序进行波形仿真,在输入上手动加上一些抖动,观察输出。波形仿真如图2所示。
图2
从仿真波形图可以看出,这种方法可以消除按键的抖动。另一种方法就是不计算抖动时间,读取按键当前值并且按键值在20ms内一直保持不变后,就可以确定按键进入了稳定状态,此时再读取该按键的值,实现按键去抖动。下面是使用Verilog HDL编写的按键消抖参考程序:
//按键去抖动处理 key是按键 CLK频率是1kHz keyout是去抖动之后的按键值
always @(posedge CLK_1kHz)//记录按键在高电平下稳定持续时间
begin
if(!keyin) KL<=KL+1;
else KL<=0;
end
always @(posedge CLK_1kHz)//记录按键在低电平下稳定持续时间
begin
if(keyin) KH<=KH+1;
else KH<=0;
end
always @(posedge CLK_1kHz)//判断按键稳定持续时间是否达到20ms
begin
if(KH>20) keyout<=1`b1;
else if(KL>20) keyout<=1`b0;
end
同时,利用Maxplus II对程序进行波形仿真,在输入上手动加上一些抖动,观察输出。波形仿真如图3所示。
图3
经过波形仿真可以看出,第二种方法显然可以很好的解决按键抖动,消除了前沿和后沿抖动,实现了按键消抖。
上面两种方法都可以实现FPGA按键消抖。然而,相比于第一种消抖方式,第二种消抖方式更为常用和有效。首先,第二种方式具有前沿和后沿消抖;其次,在按键按下或者放开的过程中,如果按键存在毛刺,那么该电路也可以有效的消除这些毛刺,使得电路更加稳定可靠。
4 结束语
在单片机和FPGA实验教学中,利用本文介绍的按键消抖方法可以有效的处理按键在动作时的抖动问题。除了上述介绍的一些按键去抖动的方法之外,还有很多按键消抖的方法,像利用状态机实现去消抖、累乘消抖[4]等,这些去抖动的方法也具有很强的实用性。在众多的按键消抖方式中,每种方法各有利弊,在实际的实验或者项目开发时,需要根据实际的软件资源、硬件资源、成本等综合考虑,从中选出合适的按键消抖方式。