51单片机教程:按键的定时器消抖(有延时的程序不是好程序)

51单片机教程:按键的定时器消抖(有延时的程序不是好程序)

按键消抖原理

一、首先来回顾一下按键延时消抖

按键由于是机械结构,按下的时候难免产生抖动,一般抖动会在按下的时候与松开的时候产生,抖动时间大概是10ms

于是针对按键抖动就有了延时消抖的一种简单的解决方法:

二、按键消抖代码

方法一: 按下按键损耗的时间取决于按下按键到松开的时间,至少10ms,按下按键后CPU不再执行其他指令,直到按键松开,应用能力弱

代码作用:按下按键led状态取反,按下按键需要等待松开

#include

sbit key=P1^0; //定义key为P1.0

sbit led=P2^0; //定义LED为P2.0

void delay_ms(unsigned int t) //ms延时

{

unsigned int i,j;

for(i=0; i

for(j=0; j<120; j++);

}

void main(void)

{

while(1)

{

if(key==0) //读P1.0引脚,如果引脚为低电平,则进入if

{

delay_ms(10); //延时10ms消抖

if(key==0) //再次判断按键是否按下,防止干扰,增强稳定

{

led = !led;//led状态改变

while(key==0);//等待按键松开,防止往下执行

}

}

}

}

方法二: (无while)按下按键损耗的时间大约10ms,无需等待,按下按键期间可以进行其他操作,应用能力较强

代码作用:按下按键led状态取反,按下按键不需要等待松开

#include

sbit key=P1^0; //定义key为P1.0

sbit led=P2^0; //定义LED为P2.0

void delay_ms(unsigned int t) //ms延时

{

unsigned int i,j;

for(i=0; 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) //再次判断,排除是松开状态或外界杂波干扰

{

led1=!led1;

}

}

else if(key==1) key_up=1;//无按键按下改为松开状态

}

}

可以看到,延时消抖最大的弊端就是有延时,至少要消耗10ms~20ms的时间,对于我们来说10ms或许很短,但对于一些高性能的MCU来说,那就是能执行几万条指令的时间

按键定时器消抖

一、按键消抖

按键消抖一般分为4步:

1、判断按键是否按下

2、消抖

3、再次判断按键是否按下

4、等待按键松开

二、定时器消抖原理

1、判断按键是否按下,

2、若检测到有按键按下,则开启定时器,开启定时中断,定时时间为10ms 左右,使得按键按下10ms后进入定时中断,进入中断的时候按键抖动时间已过

3、在定时器中断中再次判断按键是否按下

4、关闭定时器,等待按键松开

代码:

#include

sbit key=P1^0; //定义key为P1.0

sbit led=P2^0; //定义LED为P2.0

void main(void)

{

TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

TH0=(65536-10000)/256; //给定时器赋初值,定时10ms

TL0=(65536-10000)%256;

ET0=1;//打开定时器0中断允许

EA=1;//打开总中断

TR0=0;//关闭定时器

while(1)

{

if(key==0) //读P1.0引脚,如果引脚为低电平,则进入if

{

TR0=1;//打开定时器

}

}

}

/*定时器中断*/

void Timer0() interrupt 1

{

TH0=(65536-10000)/256; //给定时器赋初值,定时10ms

TL0=(65536-10000)%256;

TR0=0;//关闭定时器

if(key==0) //再次判断按键是否按下

{

led=!led;

while(key==0); //等待按键松开

}

}

可以看到,上面的代码依然有"while(key==0); //等待按键松开"这句代码,会让程序等待

程序升级!最终代码

更改电路,加入外部中断:

代码:

#include

sbit key=P3^2; //定义key为P1.0

sbit led=P2^0; //定义LED为P2.0

void main(void)

{

TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

TH0=(65536-10000)/256; //给定时器赋初值,定时10ms

TL0=(65536-10000)%256;

ET0=1;//打开定时器0中断允许

TR0=0;//关闭定时器

IT0=1;//跳变沿出发方式(下降沿)

EX0=1;//打开INT0的中断允许。

EA=1;//打开总中断

while(1)

{

}

}

/*定时器中断*/

void Timer0() interrupt 1

{

TH0=(65536-10000)/256; //给定时器赋初值,定时10ms

TL0=(65536-10000)%256;

TR0=0;//关闭定时器

if(key==0) //再次判断按键是否按下

{

led=!led; //控制led状态取反

}

}

/*外部中断0*/

void Int0() interrupt 0 //外部中断0的中断函数

{

TR0=1;//打开定时器

}

可以看到整个程序没有延时,也没用等待,实现了按键功能。

END。

相关推荐

查理九世有哪几部 分别叫啥
365bet体育滚球

查理九世有哪几部 分别叫啥

08-04 👁️‍🗨️ 8971
中国影视投资公司50排名
365bet信誉怎么样

中国影视投资公司50排名

08-29 👁️‍🗨️ 202
用Windows11的收件箱来关联163邮箱
365bet体育滚球

用Windows11的收件箱来关联163邮箱

07-07 👁️‍🗨️ 8291
Category:台灣女歌手
365bet体育滚球

Category:台灣女歌手

07-19 👁️‍🗨️ 9681
女朋友约不出来正常吗
mobile.365-588

女朋友约不出来正常吗

08-20 👁️‍🗨️ 4962
开传世SF难学吗对于新手玩家的难度如何判断(开传世SF难学吗如何选择特殊字符让昵称更独特)
挪威国家足球队
mobile.365-588

挪威国家足球队

08-20 👁️‍🗨️ 815
有朋友问怎么修改后台发货时间,这里提供2种方法:亚马逊自发货修改发货时间,附带批量表格
为什么逢赌必输?看完这个后我终于顿悟了
365bet体育滚球

为什么逢赌必输?看完这个后我终于顿悟了

07-14 👁️‍🗨️ 4910