名称:51单片机之按键实验

/*
名称:51单片机之按键实验
说明:键盘是计算机最基础、最重要的输入设备之一。对于键盘来说,其工作任务大体可以分为以下三项:
(1)、按键识别。即判断有无按键按下。
(2)、求键值。判断哪个键被按下。
(3)、执行相应的操作。
在这里,实验所用到的键盘为独立键盘和矩阵键盘。

对于独立键盘,它的每个按键需要占用一个IO口。一般来说,按键一端接地,另一端接IO口。当按键按下时,线路被导通,IO口被拉低,即状态为‘0’。所以在使用是我们一般把对应IO口置成高电平,然后不断检测此IO口是否被拉低,从而判断按键是否按下。
对于矩阵键盘来说,它用较少的IO口完成较多个按键的功能。但软件设计的复杂度相应增加些。一般来说,矩阵键盘是由多个行线和列线交叉在一起组成,每个单独的键盘仍是独立键盘。由于每个按键的两段都不接地,所以使用时需要人为的将对应的IO口置低。具体来说,是使用扫描的方式,先固定一行或者一列的按键公共端为低,然后在按列检测每一个按键的另一端。如此往复,直到完成整个键盘的扫描。

The last but not least, 对于按键实验来说,消抖一般来说是避免不了的。对于机械按键,在一次按下按键的过程中,会产生前沿抖动(按下)和后沿抖动(释放)。在具体使用时,一般有两种方式可以消抖,一个是硬件电路进行消抖,另一个则是使用软件消抖。在本实验中使用的软件消抖的方式。

软件消抖:说白了就是延时一段时间(一般为5-10ms),看是否确实还是原来的电平。一般来说,没有经过硬件消抖的情况下,最好都进行软件消抖。(虽然对于某些具体应用来说,不进行软件消抖也能达到相同的效果,如本实验中矩阵键盘实验,不涉及到对同一个数字的连续操作,所以不消抖也是可以的。但是独立按键实验则必须要进行消抖,否则num会变化的不稳定)。

哦,还有一点,对于51单片机IO口来说,复位之后IO默认输出的都是高电平。举个P0的例子说明问题,P0在复位之后输出的是FF。如果在程序中不进行主动赋值(即P0不出现在=的左边),那么P0口将一直保持高电平。即使在过程中被某些电路拉成低电平,之后P0也会被自动拉回高电平。这就解释了独立按键实验中,后沿消抖用的是while(keyboard1 != 0xFF) ; 对于具体的原因,我也不是很清楚,大概和IO口内部的逻辑电路有关。当然,如果在程序中把对应端口进行人为的赋值了,那么那将保持赋值后的电平了。

*/

#include <reg52.h>


#define keyboard P0
#define digitaltube P2      
#define keyboard1  P1

#define uchar unsigned char


//共阳极段码(a在低位,dp在高位)
uchar code _data1[16] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,
                                                0x83,0xC6,0xA1,0x86,0x8E
                                                };                                              

//延时函数
void delay_ms(unsigned int n)
{
    unsigned int i=0,j=0;
    for(i=0;i<n;i++)
        for(j=0;j<123;j++);
}


//一位数码管显示数字
void DisplayNum(char num)
{

        digitaltube = _data1[num];
}


//消除抖动,判断按键是否按下
int Debounce()
{
    uchar temp = keyboard1;
    int res = -1;                       //初始化

    delay_ms(10);                       //延时10ms
    if(temp == keyboard1)
        res = 0;

    return res;                 //返回结果
}


//独立按键实验:通过两个独立按键实现数字加1减1,然后用数码管显示
void IndButton()
{
    char num = 0;
    while(1)
    {
        if(Debounce() >= 0)                 //通过软件消抖判断是否按下按键
        {
                switch(keyboard1)
                {
                    case 0xFE:          //+1按键
                            ++num;
                        if(10 == num)
                            num = 0;


                    break;
                    case 0xEF:          //-1按键

                            --num;
                        if(-1 == num)
                            num = 9;

                    break;
                }


                while(keyboard1 != 0xFF)    ;               //等待按键释放

        }


        DisplayNum(num);        //数码管显示数字
    }
}



//矩阵键盘扫描
int KeyScan()
{
    uchar i = 0,temp = 0,temp1 = 0;
    uchar res = 0;              //返回最终的结果

    for(i = 0;i < 4;++i)
    {   
        //选定行,即对应行输出低电平
        if(0 == i)
            temp = 0x80;                        
            //temp = 0x40;
        else
            temp = temp>>1;


        temp1 = (~temp)&0x0F;      //保留低四位,用作判断列  

        keyboard = ~temp;        //选中第i行  


        if(temp1 !=(keyboard & 0x0F))       //判断是否按下按键,比较判断列
        {
            delay_ms(10);                       //消除前沿抖动

            if(temp1 != keyboard & 0x0F)
            {
                //判断是哪一列
                    switch(keyboard & 0x0F)
                    {
                        case 0x07:
                            res = i*4+0;                    //计算返回结果,i行0列

                        while(temp1 != 0x0F)            //消除后沿抖动
                        {
                            temp1 = keyboard & 0x0F;
                        }

                            break;
                        case 0x0B:
                            res = i*4+1;

                        while(temp1 != 0x0F)            //消除后沿抖动
                        {
                            temp1 = keyboard & 0x0F;
                        }

                            break;
                        case 0x0D:
                            res = i*4+2;

                        while(temp1 != 0x0F)            //消除后沿抖动
                        {
                            temp1 = keyboard & 0x0F;
                        }

                            break;
                        case 0x0E:
                            res = i*4+3;

                        while(temp1 != 0x0F)            //消除后沿抖动
                        {
                            temp1 = keyboard & 0x0F;
                        }

                            break;      


                    }

                    return res;

            }

        }

    }

    return res;

}

//矩阵键盘实验:4*4的矩阵,数码管显示所按的按键键值
void MatrixButton()
{

    uchar res = 0;
    while(1)
    {

        res = KeyScan();
        DisplayNum(res);

    }


}

int main()
{

//      IndButton();

//      MatrixButton();

        while(1)
        {
            P0 = keyboard1;
        }



    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值