按键抖动图
代码一:
#include <reg51.h>
sbit key=P1^0;
sbit led=P2^0;
void delay_ms(unsigned int t)
{
unsigned int i,j;
for(i=0; i<t; i++)
for(j=0; j<120; j++);
}
void main(void)
{
while(1)
{
if(key==0)
{
delay_ms(10);
if(key==0)
{
led = !led;
while(key==0);
}
}
}
}
代码二:
#include <reg51.h>
sbit key=P1^0;
sbit led=P2^0;
void delay_ms(unsigned int t)
{
unsigned int i,j;
for(i=0; i<t; i++)
for(j=0; j<120; j++);
}
void main(void)
{
int key_up=1;
while(1)
{
if(key==0 && key_up==1)
{
delay_ms(10);
key_up=0;
if(key==0)
{
led = !led;
}
} else if(key==1) key_up=1;
}
}
可以看到延时消抖最大弊端就是有延时,至少要消耗10ms~20ms的时间。
按键消抖一般分为4步:
- 判断按键是否按下
- 消抖
- 再次判断按键是否按下
- 等待按键松开
定时器消抖原理
- 判断按键是否按下
- 若检测到有按键按下,则开启定时器中断,定时时间为10ms左右,使得按键按下10ms后进入定时中断,进入中断的时候键抖动时间已过。
- 在定时器中断再次判断按键是否按下
- 关闭定时器
代码一:
#include <reg51.h>
sbit key=P1^0;
sbit led=P2^0;
void main(void)
{
TMOD |= 0x01;
TH0 = (65536-10000)/256;
TL0 = (65536-10000)%256;
ET0 = 1;
EA = 1;
TR0 = 0;
while(1)
{
if(key==0)
{
TR0 = 1; // 打开定时器
}
}
}
void Timer0() interrupt 1
{
TH0 = (65536-10000)/256;
TL0 = (65536-10000)%256;
TR0 = 0; // 关闭定时器
if(key==0)
{
led=!led;
while(key==0);
}
}
可以看到,上面的代码依然有while(key==0);
//等待按键松开这句代码,会让程序等待
程序升级!最终代码
更改电路,加入外部中断:
代码:
#include <reg51.h>
sbit key=P3^2;
sbit led=P2^0;
void main(void)
{
TMOD |= 0x01;
TH0 = (65536-10000)/256;
TL0 = (65536-10000)%256;
ET0 = 1;
TR0 = 0;
IT0=1;
EX0=1;
EA=1;
while(1)
{
}
}
void Timer0() interrupt 1
{
TH0 = (65536-10000)/256;
TL0 = (65536-10000)%256;
TR0 = 0; // 关闭定时器
if(key==0)
{
led=!led;
}
}
void Int0() interrupt 0
{
TR0=1;
}
流程:
按键外部中断 -> 开启定时器 -> 在定时函数中关闭定时器与读取按键电平 。