电子常识
要解决单片机按键抖动问题,首先要了解被键的类型,按键有触点式和非触点式两种,单片机中应用的- 一般是由机械触点构成的。在下图中,当开关未被按下时,P口输人为高电平。开关闭合后,P口输人为低电平。由于按键是机械触点,当机械触点断开,闭合时,会有抖动,P口输人端的波形如图2所示。这种抖动对于人来说是感觉不到的,但对单片机来说,则是完全可以感应到的,因为单片机处理的速度是在微秒级,近机械抖动的时间至少是毫秒级,这已是个“漫长”的时间了。为使CPU能正确地读出P口的状态,对每一次按健只作- 一次响应,就必须考虑如何去除抖动,常用的去抖动的方法有两种: 硬件方法和软件方法。
硬件方法
1、电容滤诐法
利用其充放电特性,使整流后i的脉动直流电压变成相对比较稳定的直流电压。在实际中。为了防止电路各部分供电电压因负载变化而产生变化,所以在电源的输出端及负载的电源输人端一般接有数十至数百微法的电解电容由于大容量的电解电容一般具有一定的电感,对高频及脉冲干扰情号不能有效地姥除,故在其两端并联了一只容量为0.001- -0.1PF的电容,以速除高频及脉冲干扰。这样就能把图2中的崩沿抖动和后沿抖动去除。
2、RS触发器法
两个“与非”门构成一个RS触发器。当按键未按下时,输出为1当键按下时,输出为0。此时即使用按键的机被性能,使按键弹性料动而产生瞬时断开(抖动跳开B),中要按键不返回原始状态A,双稳态电路的状态不改变,输出保持为0,不会产生抖动的被形。也就是说,即使B点的电压波形是抖动的,但经双稳态电路之后,其输出为正规的矩形波。这一点通过分析RS触发器的C作过程很容易得到验证。
3、中断法
各个按键都接到外部中断口上,当有任何一。个按键按下时,从而引起单片机的中断,它的好处是不用在主程序中不断地循环查询,如果有键按下,单片机再去做相应的处理。此方法可行,但单片机的中断源是宝贵的几个功能。所以很少有人去采用这样的方法。
2 软件设计
软件法其实很简单,就是在单片机获得P口为低的信息后,不是立即认定开关已被按下,而是延时10ms或更长一-些时间后再次检剩P口,如果仍为低,说明开关的确按下了,这实际上是避开了按键按下时的料动时间。而在检测到按键释放后再延时S- -10个ms,消除后沿的抖动,然后再对键值处理。不过一般情况下,我们通常不对按键释放的后沿进行处理,实践证明;也能满足定的要求。当然,实际应用中,对按键的要求也是千差万别,要根据不同的需要来编制处理程序,但以上是消除键抖动的原则。
1:不使用INTn中断功能,按键接在普通IO上
2:由定时器T/C2每隔一段时间检测按键一次, 并具有防抖动功能
3:每点击按键一次,在按键松开后,变量A=A+1
4:如果按键按下后不放,则每隔 n ms 就做A=A+1运算一次
5:在按键按下期间,CPU除了处理按键外,还必须能正常运行主程序
6:本程序的系统时钟是1MHz
#include
#include
#include
unsigned char A,B;
unsigned char n;
bit step1, step2, step3,step4; //使用几个位变量记忆按键状态
interrupt [10] void TC2_OVF(void)
{
if(n《255) n++;
if(PIND.2==1 && n》8) step1=1; //按键松开一定时间后开始进入可用状态
if(PIND.2==0 && step1) {step1=0; step2=1; n=0;} //按键由可用状态进入到按下状态
if(PIND.2==1 && step2) {step2=0; step3=1; n=0;} //按键由按下状态进入到松开状态
//按键按下后。。。
if(step2)
{
n++;
if(n》60) //如果按下超过一定时间
{
A+=1;
n=40;
step4=1;
}
}
if(step3) //按键松开后。。。
{
step3=0;
if(step4) step4=0; else A+=1;
}
}
//www.avrdiy.com panxiaoyi
void main(void)
{
PORTB&=209;
DDRB|=46; //设置单片机的4个LCD引脚输出0
lcd_init(); //lcd初始化
lcd_cls(); //清屏,光标回位
DDRD.2=0;
PORTD.2=1; //PD2设置为输入,上拉电阻有效(接按键)
TCCR2B|=4; //T/C2采用系统时钟的64分频
#asm(“sei”); //全局中断使能
TIMSK2|=1; //T/C2计数溢出中断使能
while (1)
{
B+=1;
lcd_gotoxy(12,1);
lcd_putsf(“AVRDIY.COM”,10);
lcd_gotoxy(15,3);
lcd_putchar(B/100+48); //显示变量B
lcd_putchar(B/10%10+48);
lcd_putchar(B%10+48);
lcd_gotoxy(52,3);
lcd_putchar(A/100+48); //显示变量A
lcd_putchar(A/10%10+48);
lcd_putchar(A%10+48);
};
}
全部0条评论
快来发表一下你的评论吧 !