单片机按键检测

按键检测

说明

以理论来说是不需要按键检测的,按一下就执行一次。但是实际却不是这样,在你按下的瞬间间会出现大概10MS电平在上下乱跳,松开也是同理,这是因为你按下和松开的瞬间是有抖动的,人感觉不出来,但是机器却可以,因此我们在做按钮时需要进行消抖。下面一点亮一盏灯为例。

方法

1.等待按键释放 

程序卡在一个地方,没办法运行,只能先执行此处;

#include<reg52.h>
sbit d1=P1^0;
sbit dula=P2^6;
sbit wela=P2^7;
sbit key1=P3^4;
void main()
{
    P3=0xff;
    while(1)
    {
        while(!key1)//平时不执行,按下去卡着
        {
            d1=~d1;//LED灯翻转
        }
    }
}

2.10ms检测一次 

利用定时器计时,每10ms检测按键有无按下。下降沿触发。

#include <stc12c5a60s2>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x83,0xf8,
0x80,0x98};//code编码表
sbit key1=P3^4; 
sbit S1=P1^0;
uchar key1_1,key1_2,num,f,m,p;//定义前一状态和现有状态
void Timer0Init();//声明定时器0初始化
void main()
{
    num=0;//显示值
    S1=0;//第一个数码管
    Timer0Init();//定时器0开启初始化
    EA=1;       //开总中断
    while(1)
    {
        if(m-p>10)  //按键检测
        {
            p=m;//10ms记一次
            key1_2=key1_1; //按键前一个状态
            key1_1=key1;   //按键现在的状态
        }
        if((key1_2==1)&&(key1_1==0))//检测到下降沿触发
        {
            if(f==1)//标志位在10ms内只执行一次
            {
                num++;      //数码管+1
                if(num==10) //数码管显示到10清零
                    num=0;
                f=0;        //标志位置0,使让在符合条件时,只执行一次
            }
        }
        else
            f=1;            //恢复标志位
        P0=table[num];      //数码管显示
    }
}
void Timer0Init(void)       //100微秒秒@11.0592MHz
{
    TMOD= 0x01;     //设定定时器0为工作方式1
    TL0 = 0xAE;     //设置定时初值
    TH0 = 0xFB;     //设置定时初值
    ET0 = 1;        //开定时器0中断
    TR0 = 1;        //定时器0开始计时
}
void t0_1ms() interrupt 1//表示它是中断服务子程序
{
    TL0 = 0xAE;     //设置定时初值
    TH0 = 0xFB;     //高八位初值
    m++;
}

3.外部中断触发 

虽然要机器停顿10ms,但是只会在按钮触发时出现,去检测按键,平时不会执行

#include <stc12c5a60s2>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x83,0xf8,
0x80,0x98};//code编码表
sbit key1=P3^2; //外部中断0
sbit S1=P1^0;
uchar f,num;
void Delay10ms();
void main()
{
    IT0=1;//定义外部中断0为跳变触发
    EA=1;//开启总中断
    EX0=1;//开启外部中断0
    S1=0;//开启数码管第一位
    while(1)
    {
        P0=table[num];
    }
}
void s0() interrupt 0
{
    if(key1==0)  //判断是否按下键盘
    {
      Delay10ms(); //延时,软件去干扰
      if(key1==0)   //确认按键按下
       num++;
    }
    if(num==10)//大于10清零
        num=0;  
}
void Delay10ms()        //@11.0592MHz
{
    unsigned char i, j;
​
    i = 108;
    j = 145;
    do
    {
        while (--j);
    } while (--i);
}

4.Delay延时检测 

最好少用,增加程序运行时间

#include<stc12c5a60s2>
#define uchar unsigned char
#define uint  unsigned int
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x83,0xf8,
0x80,0x98};//code编码表
sbit key1=P3^2;
sbit S1=P1^0;
uchar f,num;
void main()
{
    S1=0;//开启数码管第一位
    while(1)
    {
        if(key1==0)  //判断是否按下键盘
        {
          Delay10ms(); //延时,软件去干扰
          if(key1==0)   //确认按键按下
            num++;
        }
        if(num==10)//大于10清零
            num=0;
        P0=table[num];
    }
}
void Delay10ms()        //@11.0592MHz
{
    unsigned char i, j;
​
    i = 108;
    j = 145;
    do
    {
        while (--j);
    } while (--i);
}
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值