C51 按键消抖两种逻辑(51单片机)
前提:按键按下拉低IO,松开为高电平,消抖原理:机械按键通断瞬间有10ms左右抖动毛刺
方式1:检测到低电平 → 延时消抖(按下触发,最常用)
逻辑:读到IO为低,先延时10ms过滤抖动,再次判断IO是否还是低,确认是真按下,再执行功能。
sbit key = P3^2;
void Delay10ms(void) //粗略延时
{
unsigned char i,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);
}
void KeyScan1(void)
{
if(key == 0) //检测到低电平(疑似按下)
{
Delay10ms(); //等待抖动消失
if(key == 0) //二次确认,确实按下
{
// 执行按键功能
}
}
}
✅特点:按下一瞬间就触发;缺点:阻塞式delay,延时期间CPU啥事不能干。
方式2:检测低电平后,while等待直到松开(松开触发,等待释放)
逻辑:检测到按键按下(低)→延时消抖确认按下 →while循环卡死,一直等到按键变回高电平(松开),再执行功能
void KeyScan2(void)
{
if(key == 0)
{
Delay10ms();
if(key == 0)
{
while(key == 0); //阻塞等待:按键保持低就一直卡在这里,直到松手变高
Delay10ms(); //松开也要消抖
// 执行按键功能
}
}
}
✅特点:松手那一刻才执行函数;适合防止长按重复触发;同样是阻塞代码。
核心区别
| 方式1(按下触发) | 方式2(等待松开再执行) | |
|---|---|---|
| 执行时机 | 确认按下立刻执行 | 按键松开之后才执行 |
| 长按行为 | 长按会反复扫描多次触发 | 长按只会等松手执行1次 |
| 阻塞点 | 仅delay短暂阻塞 | while会长期阻塞,按住不放代码停住 |
补充:上面两个都是阻塞式消抖,项目高级写法是定时器中断做非阻塞消抖,不用delay和while死等。