51单片机实现按键、键盘的功能

实现按键、键盘的功能

写在前面

按钮开关

轻触开关是一种电子开关,使用时,轻轻按开关按钮就可使开关接通,当松开手时,开关断开。我们使用的开关如下图:

        

LED连接P0.0口,独立按键连接p1.0口,当按键按下时,P1.0口为低电平,led灯输出为高电平,led灯点亮。

矩阵键盘

     

1.键盘的工作原理: 按键设置在行、列线交点上,行、列线分别连接到按键开关的两端。行线通过上拉电阻接到+5V电源上。无按键按下时,行线处于高电平的状态,而当有按键按下时,行线电平与此行线相连的列线电平决定。

2.行列扫描法原理:

第一步, 使行线为编程的输入线,列线是输出线,拉低所有的列线,判断行线的变化,如果有按键按下,按键按下的对应行线被拉低,否则所有的行线都为高电平。

第二步,在第一步判断有键按下后, 延时10ms消除机械抖动,再次读取行值,如果此行线还处于低电平状态则进入下 一步,否则返回第一步重新判断。

第三步,开始扫描按键位置,采用逐 行扫描,每间隔1ms的时间,分别拉低第一列,第二列,第三列,第四 列,无论拉低哪一列其他三列都为高电平,读取行值找到按键的位置,分别把行值和列值储存在寄存器里。

第四步,从寄存器中找到行值和列 值并把其合并,得到按键值,对此按键值进行编码,按照从第一行第一个一直到第四行第四个逐行进行编码,编码值从“0000” 至“1111” , 再进行译码,最后显示按键号码。数码管动态扫描原理。数码管动态扫描原理:数码管的 7 个段及小数点都是由 LED 块组成的,显示方式分为静 态显示和动态显示两种。数码管在静态显示方式时,其共阳管的位选 信号均为低电平,四个数码管的共用段选线 a、b、c、d、e、f、g、dp 分别与 CPLD 的 8 根 I/O 口线相连,显示数字时只要给相应的段选线送 低电平。数码管在动态显示方式时,在某一时刻只能有一个数码管被点亮显示数字,其余的处于非选通状态,位选码端口的信号改变时, 段选码端口的信号也要做相应的改变 ,每位显示字符停留显示的时间 一般为 1-5ms,利用人眼睛的视觉惯性,在数码管上就能看到相当稳定的数字显示。

独立按键代码

/**************************************************************************************
*                      独立按键实验                                                  *
实现现象:下载程序后按下K1按键可以对D11小灯状态取反。
注意事项:无                                                                                  
***************************************************************************************/

#include "reg52.h"             //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16;      //对数据类型进行声明定义
typedef unsigned char u8;

sbit k1=P1^0;     //定义P10口是k1
sbit led=P0^0;     //定义P00口是led

/*******************************************************************************
* 函 数 名         : delay
* 函数功能           : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
    while(i--);    
}

/*******************************************************************************
* 函 数 名         : keypros
* 函数功能           : 按键处理函数,判断按键K1是否按下
*******************************************************************************/
void keypros()
{
    if(k1==0)          //检测按键K1是否按下
    {    
        delay(1000);   //消除抖动 一般大约10ms
        if(k1==0)     //再次判断按键是否按下
        {
            led=~led;      //led状态取反
        }
        while(!k1);     //检测按键是否松开
    }        
}

/*******************************************************************************
* 函 数 名       : main
* 函数功能         : 主函数
* 输    入       : 无
* 输    出         : 无
*******************************************************************************/
void main()
{    
    led=0;
    while(1)
    {    
        keypros();  //按键处理函数    
    }        
}

 

矩阵键盘代码

/**************************************************************************************
*                      矩阵按键实验                                                  *
实现现象:下载程序后数码管显示0,按下矩阵按键上的按键显示对应的数字
            S1-S4:0-3
            S5-S8:4-7
            S9-S12:8-B
            S13-S16:C-F。
注意事项:                                                                                  
***************************************************************************************/

#include "reg52.h"             //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16;      //对数据类型进行声明定义
typedef unsigned char u8;

#define GPIO_DIG P0
#define GPIO_KEY P1


u8 KeyValue;    //用来存放读取到的键值


u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                    0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

/*******************************************************************************
* 函 数 名         : delay
* 函数功能           : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
    while(i--);    
}

/*******************************************************************************
* 函 数 名         : KeyDown
* 函数功能           : 检测有按键按下并读取键值
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void KeyDown(void)
{
    char a=0;
    GPIO_KEY=0x0f;
    if(GPIO_KEY!=0x0f)//读取按键是否按下
    {
        delay(1000);//延时10ms进行消抖
        if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
        {    
            //测试列
            GPIO_KEY=0X0F;
            switch(GPIO_KEY)
            {
                case(0X07):    KeyValue=0;break;    // 第一列 有按键按下
                case(0X0b):    KeyValue=1;break;    // 第二列 有按键按下
                case(0X0d): KeyValue=2;break;    // 第三列 有按键按下
                case(0X0e):    KeyValue=3;break;    // 第四列 有按键按下
            }
            //测试行
            GPIO_KEY=0XF0;
            switch(GPIO_KEY)
            {
                case(0X70):    KeyValue=KeyValue;break;        // 第一行 有按键按下       
                case(0Xb0):    KeyValue=KeyValue+4;break;        // 第二行 有按键按下
                case(0Xd0): KeyValue=KeyValue+8;break;        // 第三行 有按键按下
                case(0Xe0):    KeyValue=KeyValue+12;break;        // 第四行 有按键按下
            }
            while((a<50)&&(GPIO_KEY!=0xf0))     //检测按键松手检测
            {
                delay(1000);
                a++;
            }
        }
    }
}


/*******************************************************************************
* 函 数 名       : main
* 函数功能         : 主函数
* 输    入       : 无
* 输    出         : 无
*******************************************************************************/
void main()
{    

    while(1)
    {    
        KeyDown();           //按键判断函数
        GPIO_DIG=~smgduan[KeyValue];      //
    }        
}

发布了118 篇原创文章 · 获赞 123 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_42776111/article/details/104431517