两个很经典的单片机按键扫描C语言程序

时间:2024-03-04 08:44:46

[转自:http://www.52rd.com/Blog/Detail_RD.Blog_cambrain_24794.html]

程序一:

unsigned char Trg;           //全局变量

unsigned char Cont;        //全局变量

void   KeyRead(void)        //判断按键状态的子程序

{

     unsigned char ReadData=P0^0xFF;

     Trg=ReadData&(ReadData^Cont);

     Cont=ReadData;

}

P0口上拉电阻连接,并且通过一个开关接到地,按键检测即检测低电平。

分析:由于在按位与、或、非逻辑运算中单独的某一位的运算与其他各位无关,所以分析时只取P00,那么上面的程序就可以变成下面的形式:

程序二:

bit  Trg;           //全局位变量

bit  Cont;        //全局位变量

void   KeyRead(void)        //判断按键状态的子程序

{

     bit  ReadData=P00^1;

     Trg=ReadData&(ReadData^Cont);

     Cont=ReadData;

}

①按键未被按下,P00=1,经分析得: 

ReadData=0;Trg=0;Cont=0。

②按键第一次被按下,P00=0,经分析得:

ReadData=1;Trg=1;Cont=1。

③按键被按住不放,P00=0,经分析得:   

 ReadData=1;Trg=0;Cont=1。

④按键被松开,P00=1,经分析得:

ReadData=0;Trg=0;Cont=0。(和按键未被按下时一样)

可以看到,按键被按下的不同状态即阶段就对应不同的Trg和Cont,这样处理按键就简单了。

如果希望按键短按一下有效,长按无效,则检测Trg的值;如果希望按键长按有效,则检测Cont的值,如果Cont一直为1,则说明按键被一直按下。

如果是检测多个按键的话就采用程序一的形式。比如:要检测P0口的8个按键,如果P01被第一次按下,那么ReadData=0x02;Trg=0x02;Cont=0x02。如果P07被长按下,那么ReadData=0x80;Trg=0x00;Cont=0x80。这样只要知道Trg和Cont的值就可以知道哪个键被按下以及被按下的状态和阶段。

另外还有一个按键消抖的问题,我采用的是定时器中断,每隔20ms进入中断检测按键,如果这一次的检测结果和上一次的一样的话,就进入上面的程序一判断按键状态。如下:(检测P01)

unsigned char Trg;

unsigned char Cont;

void main (void0

{

  //初始化//

   if(Trg&0x02)          ///按键被第一次按下

   {

      //程序处理//

    }

}

void Timer1(void)  interrupt 1

{

    unsigned char ReadData;

    unsigned char P0value_present;

    static unsigned char  P0value_last=0;

    //关中断等//

    P0value_present=P0;                                 //端口当前值

    if(P0value_present&P0value_last)

    {

        ReadData=P0value_present^0xFF;

        Trg=ReadData&(ReadData^Cont);

        Cont=ReadData;

     }

     P0value_last=P0;                                       //端口上一次的值

    //开中断等//

}