按键

来源:互联网 发布:列生成算法介绍 编辑:程序博客网 时间:2024/05/01 16:37
4
推荐

一.概述

按键作为人类向单片机传递指令的载体,在单片机控制系统中,占有重要的地位,按键失灵,如同人失聪一样不听使唤,使控制系统陷入失控状态。按结构原理来分,按键有机械按键、薄膜按键、电容式触摸按键和电阻式触摸按键。按接线方式来分,按键分为独立按键和矩阵按键(也叫矩阵键盘)。不同结构原理的按键其扫描过程都不一样。本文只对对机械按键的扫描进行探讨。

机械按键结构简单,价格低廉,使用方便,但是噪音大,特别是在按下和松开的瞬间,会有抖动现象(产生几微妙到几百微妙不等的锯齿脉冲)。抖动的存在使按键虽然只按一次,但在单片机快速的扫描的过程中就会检测到多次按下的信号,让单片机获得不正确的按键信息。所以,在按键扫描里,消抖处理成为按键扫描不可缺少的过程。没有消抖,按键就不听话。

按键消抖分软件消抖和硬件消抖。在单片机系统里,用的较多的是软件消抖。本文不对硬件消抖作讨论。

对于独立按键的扫描,消抖的处理是通过延时来实现;对于矩阵按键的扫描,抖动影响不大,一般不做消抖处理。

二.电路设计

在一个4*4的矩阵键盘里,可以取出任意四个按键作为独立按键使用,所以WSF-51D开发板只设有矩阵键盘,不再设独立按键。如在这个矩阵键盘里,只要把单片机的P3.7脚拉低,S1S2S3S4四个按键就可以作为独立按键使用,对应的按键扫描引脚分别是P3.0P3.1P3.2P3.3

 

 

 

三.程序设计

1.独立按键扫描程序:

 /*****************************************************************

*程序名称:独立按键扫描

*程序功能:按键被按下,相应的指示灯被点亮

*开发工具:WSF-51DB开发板

* MCU型号:AT89S52-24PU

*时钟频率:12MHZ

*程序作者:吴师傅

*版权说明:吴师傅版权所有。转载请注明来源和作者。

*****************************************************************/

#i nclude<reg52.h>

//将P3.7拉低,矩阵键盘上的S1S2S3S4便可作为4个独立按键使用

sbit s1=P3^0;//S1按键的扫描线

sbit s2=P3^1;//S2按键的扫描线

sbit s3=P3^2;//S3按键的扫描线

sbit s4=P3^3;//S4按键的扫描线

sbit com=P3^7;//四个独立按键的公共接地端

 

//延时ms函数:

void Delayms(unsigned int t)

{

    unsigned int i,j;

    for(i=t;i>0;i--)

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

}

 

//按键扫描函数:

unsigned char ScanSingleKey()

{

    if(s1==0)//如果s1键按下

    {

            Delayms(20);//延时消抖

            if(s1==0)

                  while(!s1);//等待松手

            return 1;//函数返回键值 

    }

 

       else if(s2==0)//如果s2键按下

    {

            Delayms(20);//延时消抖

            if(s2==0)

                   while(!s2);//等待松手

            return 2;//函数返回键值 

    }

 

    else if(s3==0)//如果s3键按下

    {

            Delayms(20);//延时消抖

            if(s3==0)

                   while(!s3);//等待松手

            return 3;//函数返回键值 

    }

 

    else if(s4==0)//如果s4键按下

    {

            Delayms(20);//延时消抖

            if(s4==0)

                    while(!s4);//等待松手

            return 4;//函数返回键值 

    }

    else return 0;//没有键按下返回

}

 

//主函数:

int main(void)

{

    unsigned char key;

    com=0;//P3.7拉低,S1S2S3S4作为独立按键使用

    while(1)

    {

            key=ScanSingleKey();//扫描按键,获得键值

            switch(key)

            {

                    case 1: P2=0xfe;break;//如果s1按下,P2口的第0位指示灯亮

                    case 2: P2=0xfd;break;//如果s2按下,P2口的第1位指示灯亮

                    case 3: P2=0xfb;break;//如果s3按下,P2口的第2位指示灯亮

                    case 4: P2=0xf7;break;//如果s4按下,P2口的第3位指示灯亮

                    default: ;

            }   

   }

  return 0;

}

 

2.矩阵键盘扫描程序:

/*****************************************************************

*程序名称:4*4矩阵键盘扫描

*程序功能:按键被按下,相应的键值在数码管上显示

*开发工具:WSF-51DB开发板

* MCU型号:AT89S52-24PU

*时钟频率:12MHZ

*程序作者:吴师傅

*版权说明:吴师傅版权所有。转载请注明来源和作者。

*****************************************************************/

#i nclude<reg52.h>

unsigned char code segmcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,

                               0x77,0x7C,0x39,0x5E,0x79,0x71};//共阴极数码管段码

unsigned char code bitcode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

                                                            //8位共阴极数码管位码

sbit ser=P2^0;//74HC595串行数据输入

sbit oe=P2^1;//74HC595使能

sbit rclk=P2^2;//74HC595数据锁存

sbit srclk=P2^3;//74HC595串行时钟

 

//延时ms函数:

void Delayms(unsigned int t)

{

         unsigned int i,j;

         for(i=t;i>0;i--)

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

}

 

//任意位数码管显示一个字符函数:

void DTDisplayChar(unsigned char segmd,unsigned char bitd )//数码管段码和数码管位码

{

        unsigned char i;

        unsigned int dat;

        oe=1;//74HC595禁止

        dat=bitd;

        dat=dat<<8|segmd;//位码段码合并为一个int型数据

        for(i=0;i<16;i++)//16位数据从高位依次移入74HC595

        {

                 ser=(dat&0x8000)?1:0; //判断最高位,为真取1,为假取0

                 srclk=1;//上升沿送数据

                 srclk=0;

                 dat<<=1;//左移取下一位

        }

        rclk=1;//74HC595锁存数据

        rclk=0;

        oe=0;//74HC595使能

}

 

//4*4矩阵键盘扫描函数:

unsigned char ScanArrayKey(void)//反转扫描法,效率高

{

        unsigned char list,line,x,y,keynum;

        P3=0x0f;//四行同时拉低,

        list=P3;//读回,取得四列的值

        P3=0xf0;//四列同时拉低

        line=P3;//读回,取得四行的值

        if(list==0x0e) x=1;//如果第一列为低电平,设列值为1(从左往右数)

        else if(list==0x0d) x=2;//如果第二列为低电平,设列值为2

        else if(list==0x0b) x=3;//如果第三列为低电平,设列值为3

        else if(list==0x07) x=4;//如果第四列为低电平,设列值为4

        else ;

 

        if(line==0x70) y=0;//如果第一行为低电平,设行值为0(从下往上数)

        else if(line==0xb0) y=4;//如果第二行为低电平,设行值为4

        else if(line==0xd0) y=8;//如果第三行为低电平,设行值为8

        else if(line==0xe0) y=12;//如果第四行为低电平,设行值为12

        else ;

        keynum=x+y;//键值=列值+行值

        return keynum;     

}

 

//主函数:

int main(void)

{

        unsigned char num;

        while(1)

        {

                num=ScanArrayKey();//扫描矩阵按键获得键值  

                DTDisplayChar(segmcode[num/10],0xfe);//显示键值的十位

                Delayms(1);

                DTDisplayChar(segmcode[num%10],0xfd);//显示键值的各位

                Delayms(1); 

        }

        return 0;

}

 
原创粉丝点击