精华内容
下载资源
问答
  • 以金沙滩工作室的STC89C52单片机开发板为例,记录学习51单片机的笔记,本文章主要讲解了4×4矩阵按键扫描,教材是金沙滩工作室(www.kingst.org )宋雪松老师编著的《手把手教你学51单片机-C语言版》,所用的...

    以金沙滩工作室的STC89C52单片机开发板为例,记录学习51单片机的笔记,本文章主要讲解了4×4矩阵按键的扫描,教材是金沙滩工作室(www.kingst.org )宋雪松老师编著的《手把手教你学51单片机-C语言版》,所用的开发板是教材配套开发板。在这里推荐一下宋老师的这套教材,感觉还是蛮不错的。下面是该文章的目录:

    1.矩阵按键及其原理

    2.矩阵按键的消抖

    1.矩阵按键及其原理

    图1是单片机开发板上的矩阵按键的实物图,图2是矩阵按键的电路原理图。以4×4矩阵按键为例,总共包含了16个按键,包括数字0~9、四个方向键(上下左右)、ESC键和回车键,当然在使用过程中可以定义这些按键为其他功能,灵活多变。

    95b37785ca79cc1b611ecd9c06700567.png
    图2 4×4矩阵按键的电路图

    16个按键占用P2的8个IO口,见上图2,KeyOut1~KeyOut4为输出引脚,KeyIn1~KeyIn4为读取引脚。KeyOut1~KeyOut4均输出高电平时,由于全部KeyIn引脚最上面与+5V接通,故无论某个按键是否按下,KeyIn1~KeyIn4读取到的均为高电平(逻辑1),无法判断是否有按键按下/弹起,当其中的某个KeyOut引脚输出低电平(逻辑0)时,按下该行的某个按键,那么这个按键对应的keyIn引脚将读取到低电平,从而可以在程序中判断某个按键是否被按下。

    例如,现在使KeyOut3引脚为0,其余KeyOut引脚为1,那么当按键K12按下时,KeyIn4引脚直接与KeyOut3引脚连通,将其电平拉低,P2.7就可以读取到0,那么就可以判断K12(右键)被按下了。

    2.矩阵按键的消抖和扫描

    由于按键的机械特性,按键存在“抖动”的情况,比如,当按下某个键的瞬间,这个键可能还会来回抖动几次,当然这种抖动是手指感觉不出来的,但它确实会影响读取到的电平的高低,相反,按键弹起的瞬间,也会存在抖动的情况。如图3,按键抖动通常只持续不到10ms,按下到弹起的整个过程通常持续100ms以上,所以需要进行消抖处理。

    e34b2782648ccb545d2c5e107f315cdd.png
    图3 按键的抖动

    在这里,按键消抖的思路定义一个4X4的二维数组 keybuf[4][4]和keysta[4][4]

    unsigned char keybuff[4][4] = {
    	{0xFF, 0xFF, 0xFF, 0xFF}, 
    	{0xFF, 0xFF, 0xFF, 0xFF}, 
    	{0xFF, 0xFF, 0xFF, 0xFF}, 
    	{0xFF, 0xFF, 0xFF, 0xFF}
    }; //定义在中断函数内
    
    unsigned char KeySta[4][4] = {
    	{1, 1, 1, 1},
    	{1, 1, 1, 1},
    	{1, 1, 1, 1},
    	{1, 1, 1, 1},
    }; //定义为全局变量

    keybuf[4][4]中每一个元素代表了对应按键在某个瞬间的状态,初始化为0xFF(0b11111111),就意味着开始每个按键均为弹起状态。

    设置定时/计数器T0的定时时长为1ms,每次中断,就选中keybuff其中一行,依次将该行的四个元素左移一位,并将对应的KeyInx(x = 1, 2, 3, 4)的值写入数组元素的最低位,如此就需要4ms完成四行按键的扫描,但是,通常抖动的时间在10ms左右,那么干脆就在16ms内判断某个按键是否被稳定的按下或者弹起,若在16ms中读取到的某个按键的状态均为0或者1,那么就可以判断这个按键已经被稳定地按下或者弹起了,这时,就将存储按键状态的二维数组KeySta[4][4]中对应的按键的状态置为0或者1。

    下面是部分示例代码(定义KeyScan函数专门用于按键的扫描,它在T0的中断函数内被调用)。

    #include<reg52.h>
    
    sbit KeyOut4 = P2^0;
    sbit KeyOut3 = P2^1;
    sbit KeyOut2 = P2^2;
    sbit KeyOut1 = P2^3;
    sbit KeyIn1 = P2^4;
    sbit KeyIn2 = P2^5;
    sbit KeyIn3 = P2^6;
    sbit KeyIn4 = P2^7;
    
    unsigned char KeySta[4][4] = {
         {1, 1, 1, 1},
         {1, 1, 1, 1}, 
         {1, 1, 1, 1}, 
         {1, 1, 1, 1}
     };
    unsigned char code KeyCodeMap[4][4] = {
    	{ 0x31, 0x32, 0x33, 0x26 }, //数字键 1、数字键 2、数字键 3、向上键
        { 0x34, 0x35, 0x36, 0x25 }, //数字键 4、数字键 5、数字键 6、向左键
        { 0x37, 0x38, 0x39, 0x28 }, //数字键 7、数字键 8、数字键 9、向下键
        { 0x30, 0x1B, 0x0D, 0x27 } //数字键 0、ESC 键、 回车键、 向右键;
    };
    
    void KeyScan()
    {
    	static unsigned char KeyBuff[4][4] = {
    		{0xFF, 0xFF, 0xFF, 0xFF}, 
    	    {0xFF, 0xFF, 0xFF, 0xFF}, 
    	    {0xFF, 0xFF, 0xFF, 0xFF}, 
    	    {0xFF, 0xFF, 0xFF, 0xFF}
    	};
    	static unsigned char row = 0;
    	unsigned char col;
    	KeyBuff[row][0] = (KeyBuff[row][0] << 1) | KeyIn1;
    	KeyBuff[row][1] = (KeyBuff[row][1] << 1) | KeyIn2;
    	KeyBuff[row][2] = (KeyBuff[row][2] << 1) | KeyIn3;
    	KeyBuff[row][3] = (KeyBuff[row][3] << 1) | KeyIn4;
    	for (col = 0; col < 4; col++)
    	{
    		if ((KeyBuff[row][col]) & 0x0F == 0x0F)
    		{
    			KeySta[row][col] = 1;
    		}
    		else if ((KeyBuff[row][col] & 0x0F) == 0x00)
    		{
    			KeySta[row][col] = 0;
    		}
    	}
    	row++;
    	row  = row & 0x03;
    	switch (row)
    	{
    		case 0: KeyOut4 = 1; KeyOut1 = 0; break;
    		case 1: KeyOut1 = 1; KeyOut2 = 0; break;
    		case 2: KeyOut2 = 1; KeyOut3 = 0; break;
    		case 3: KeyOut3 = 1; KeyOut4 = 0; break;
    		default: break;
    	}
    }
    展开全文
  • 单片机扫描键盘按键板 Protel99se设计硬件原理图PCB文件,包括完整的原理图PCB文件,板子大小为175x80mm,2层板。可用Protel或 Altium Designer(AD)软件打开或修改,已经制板验证使用,可作为你产品设计的参考。
  • 矩阵键盘扫描原理详解 根据原理图 键盘扫描方法是:行线P10~P13为输出线,列线P14~P17为输入线。 一开始单片机将行线(P10~P13)全部输出低电平,此时读入列线数据,若列线全为高电平则没有键按下,当列线有出现...

    矩阵键盘扫描原理详解


    根据原理图
    键盘扫描方法是:行线P10~P13为输出线,列线P14~P17为输入线。

    一开始单片机将行线(P10~P13)全部输出低电平,此时读入列线数据,若列线全为高电平则没有键按下,当列线有出现低电平时调用延时程序以此来去除按键抖动。延时完成后再判断是否有低电平,如果此时读入列线数据还是有低电平,则说明确实有键按下。最后一步确定键值。

    现在我们以第二行的S5键为例,若按下S5后我们应该怎么得到这个键值呢?

    当判断确实有键按下之后,行线轮流输出低电平,根据读入列线的数据可以确定键值。

    首先,单片机将P10输出为低电平,其它P11~P13输出高电平,此时读取列线的数据全为高电平,说明没有在第一行有键按下;

    其次,单片机将P11输出低电平,其它P10、P12、P13仍为高电平,此时再来读取列线数据,发现列线读到的数据有低电平,数值为1011(0x0B),如果我们的键盘布局已经确定,那么0x0B就代表S5的值了。转到S5键功能处理子程序就可以达到目的。

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

    PS:同时按住S5,S6也是可以识别的。

    首先,单片机将P10输出为低电平,其它P11~P13输出高电平,此时读取列线的数据全为高电平,说明没有在第一行有键按下;

    其次,单片机将P11输出低电平,其它P10、P12、P13仍为高电平,此时再来读取列线数据,发现列线读到的数据有低电平,数值为1001(0x09),如果我们的键盘布局已经确定,那么0x09就代表S5,S6的值了。

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

    /*  
        功能:矩阵键盘扫面,按键显示键值程序 
        作者:siriuszxn
                                      */
    #include "reg51.h"                                                                                                                
    #define KEYPORT = P1                                                                                                   

    unsigned char i;                                                                                                                                         
    unsigned char Keynum;                                                                                                        
    unsigned char Line;                                       //行                                                                 
    unsigned char Mask;                                                                                                         
    unsigned char Col;                                        //列                                                                      
    unsigned char ScanCode;                                                                                              

    unsigned char code psegs_table[] =                                                                                            {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};                                                                //共阳极数码管0-F                                                                                                                                            

    void delay_ms(unsigned int t)                      //ms延时程序                                                                      
    {                                                                                                                                       
        unsigned char i;                                                                                                                 
         unsigned int x;                                                                                                                  
         x=t;                                                                                                                              
         while(x--)                                                                                                                        
         {                                                                                                                                          
                 for(i=0;i<113;i++);                                                                                                              
         }                                                                                                                                           
    }                                                                                                                                        
    /* 键盘扫描程序 */                                                                                                                                        
    void keyscan()                                                                                                           
    {                                                                                                                                   
        while (1)              //循环扫描键盘       
        {                                                                                                                            
           P1 = 0xff;          //开始                                                         
            Line = 1;                                                                                         
            Mask = 0x01;                                                                                         

            for(i = 0; i < 4; i++)                                                                                   
            {                                                                                                                                                                                    
                P1 = ~Mask;                                                                                    

                ScanCode = P1 & 0xf0;                                                                                          

                if (ScanCode != 0xf0)                                                                                         
                {                                                                                                                                                                                    
                    delay_ms(5);                                                                               
                }                                                                                                                                                                                    

                ScanCode = P1 & 0xf0;                                                                                          

                switch(ScanCode)                                                
                {                                                                                                                                                                                    
                    case 0xe0:Col=1;break;                                                                                          
                    case 0xd0:Col=2;break;                                                                   
                    case 0xb0:Col=3;break;                                                                          
                    case 0x70:Col=4;break;                                                                  
                    default  :Col=0;break;                                                                                          
                }                                                                                                                                                                                    

                if (Col > 0)                                                                                                                                           
                {   
                    //根据行列计算键值                                                                                                                                                         
                    Keynum = (Line - 1) * 4 + Col;                                                                  
                    //通过P0口接数码管显示                                                                                                          
                    P0 = psegs_table[Keynum-1];                                                                                          

                    while(1)                                                                                           
                    {                                                                                
                        ScanCode = P1 & 0xf0;                                                                                
                        if(ScanCode == 0xf0)                                                               
                        {                                                                                                                                              
                            break;                                                    
                        }                                                                                                                       
                    }                                                                                
                    Mask <<= 1;                                                                                                      
                    Line++;                                                                                                 
                }                                                                                                                        
            }                                                                                                                                      
        }  
    }                                                                                                                                   

    void main()                                                                                         
    {                                                                                                                                     
        while(1)                                                                                                                      
        {                                                                                                                                 
            keyscan();                                                                                         
        }                                                                                                                                 
    }                                                
    ————————————————
    版权声明:本文为CSDN博主「zxnsirius」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zxnsirius/article/details/51088946

    展开全文
  • 1.按键分类与输入原理按键按照结构原理科分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关灯;另一类是无触点式开关按键,如电气式按键,磁感应按键等。前者造价低,后者寿命长。目前,微机系统中最...

    1.按键分类与输入原理

    按键按照结构原理科分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关灯;另一类是无触点式开关按键,如电气式按键,磁感应按键等。前者造价低,后者寿命长。目前,微机系统中最常见的是触点式开关按键。

    单片机应用系统中,除了复位按键有专门的复位电路及专一的复位功能外,其他按键都是以开关状态来设置控制功能或输入数据的。当所设置的功能键或数字键按下时,计算机应用系统应完成该按键所设定的功能,键信息输入时与软件结构密切相关的过程。

    对于一组键或一个键盘,总有一个接口电路与CPU相连。CPU可以采用查询或中断方式了解有无将按键输入,并检查是哪一个按键按下,将该键号送人累加器,然后通过跳转指令转入执行该键的功能程序,执行完成后再返回主程序。

    2.按键结构与特点

    微机键盘通常使用机械触点式按键开关,其主要功能式把机械上的通断转换为电气上的逻辑关系。也就是说,它能提供标准的TTL逻辑电平,以便于通用数字系统的逻辑电平相容。机械式按键再按下或释放时,由于机械弹性作用的影响,通常伴随有一定的时间触点机械抖动,然后其触点才稳定下来。其抖动过程如下图1所示,抖动时间的长短与开关的机械特性有关,一般为5-10ms。在触点抖动期间检测按键的通与断,可能导致判断出错,即按键一次按下或释放错误的被认为是多次操作,这种情况是不允许出现的。为了克服你、按键触点机械抖动所致的检测误判,必须采取消抖措施。按键较少时,可采用硬件消抖;按键较多式,采用软件消抖。

    c6711422e3d7b32199e4b217cde090b9.png

    图1 按键触点机械抖动

    (1)按键编码

    一组按键或键盘都要通过I/O口线查询按键的开关状态。根据键盘结构的不同,采用不同的编码。无论有无编码,以及采用什么编码,最后都要转换成为与累加器中数值相对应的键值,以实现按键功能程序的跳转。

    (2)键盘程序

    一个完整的键盘控制程序应具备以下功能:

    a.检测有无按键按下,并采取硬件或软件措施消抖。

    b.有可靠的逻辑处理办法。每次只处理一个按键,期间对任何按键的操作对系统不产生影响,且无论一次按键时间有多长,系统仅执行一次按键功能程序。

    c.准确输出按键值(或键号),以满足跳转指令要求。

    3.独立按键矩阵键盘

    (1)独立按键

    单片机控制系统中,如果只需要几个功能键,此时,可采用独立式按键结构。

    独立按键式直接用I/O口线构成的单个按键电路,其特点式每个按键单独占用一根I/O口线,每个按键的工作不会影响其他I/O口线的状态。独立按键的典型应用如图所示。独立式按键电路配置灵活,软件结构简单,但每个按键必须占用一个I/O口线,因此,在按键较多时,I/O口线浪费较大,不宜采用。独立按键如图2所示。

    fcc69a360e55410f96092ad3bd0014c2.png

    图2 独立键盘

    独立按键的软件常采用查询式结构。先逐位查询没跟I/O口线的输入状态,如某一根I/O口线输入为低电平,则可确认该I/O口线所对应的按键已按下,然后,再转向该键的功能处理程序。

    (2)矩阵键盘

    单片机系统中,若使用按键较多时如电子密码锁、电话机键盘等一般都至少有12到16个按键,通常采用矩阵键盘。

    矩阵键盘又称行列键盘,它是用四条I/O线作为行线,四条I/O线作为列线组成的键盘。在行线和列线的每个交叉点上设置一个按键。这样键盘上按键的个数就为4*4个。这种行列式键盘结构能有效地提高单片机系统中I/O口的利用率。

    矩阵键盘的工作原理

    最常见的键盘布局如图3所示。一般由16个按键组成,在单片机中正好可以用一个P口实现16个按键功能,这也是在单片机系统中最常用的形式,4*4矩阵键盘的内部电路如图4所示。

    6d79f86b29f91c99653da8e57f7c88e8.png

    图3 矩阵键盘布局图

    d2d8082494c75cf6cda763d5051db298.png

    图4 矩阵键盘内部电路图

    当无按键闭合时,P3.0~P3.3与P3.4~P3.7之间开路。当有键闭合时,与闭合键相连的两条I/O口线之间短路。判断有无按键按下的方法是:第一步,置列线P3.4~P3.7为输入状态,从行线P3.0~P3.3输出低电平,读入列线数据,若某一列线为低电平,则该列线上有键闭合。第二步,行线轮流输出低电平,从列线P3.4~P3.7读入数据,若有某一列为低电平,则对应行线上有键按下。综合一二两步的结果,可确定按键编号。但是键闭合一次只能进行一次键功能操作,因此须等到按键释放后,再进行键功能操作,否则按一次键,有可能会连续多次进行同样的键操作。

    识别按键的方法很多其中,最常见的方法是扫描法

    按键按下时,与此键相连的行线与列线导通,行线在无按键按下时处在高电平。如果所有的列线都处在高电平,则按键按下与否不会引起行线电平的变化,因此必须使所有列线处在电平。这样,当有按键按下时,改键所在的行电平才回由高变低。才能判断相应的行有键按下。

    独立按键数量少,可根据实际需要灵活编码。矩阵键盘,按键的位置由行号和列号唯一确定,因此可以分别对行号和列号进行二进制编码,然后两值合成一个字节,高4位是行号,低4位是列号。

    4.键盘的工作方式

    对键盘的响应取决于键盘的工作方式,键盘的工作方式应根据实际应用系统中的CPU的工作状况而定,其选取的原则是既要保证CPU能及时响应按键操作,又不要过多占用CPU的工作时间。通常键盘的工作方式有三种,编程扫描、定时扫描和中断扫描。

    (1)编程扫描方式

    编程扫描方式是利用CPU完成其它工作的空余时间,调用键盘扫描子程序来响应键盘输入的要求。在执行键功能程序时,CPU不再响应键输入要求,直到CPU重新扫描键盘为止。

    (2)定时扫描方式

    定时扫描方式就是每隔一段时间对键盘扫描一次,它利用单片机内部的定时器产生一定时间(例如10ms)的定时,当定时时间到就产生定时器溢出中断。CPU响应中断后对键盘进行扫描,并在有按键按下时识别出该键,再执行该键的功能程序。

    (3)中断扫描方式

    上述两种键盘扫描方式,无论是否按键,CPU都要定时扫描键盘,而单片机应用系统工作时,并非经常需要键盘输入,因此,CPU经常处于空扫描状态。

    为提高CPU工作效率,可采用中断扫描工作方式。其工作过程如下:当无按键按下时,CPU处理自己的工作,当有按键按下时,产生中断请求,CPU转去执行键盘扫描子程序,并识别键号。

    展开全文
  • 独立按键实验 按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时, 开关断开。我们开发板上使用的按键及内部简易图如下图所示 管脚与管脚之间(注意是距离)距离长的是导通状态,短的是接通状态。...

    独立按键实验

    按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时, 开关断开。我们开发板上使用的按键及内部简易图如下图所示

    17ef1c275ecdf95e43b946f1073d8caa.png

    管脚与管脚之间(注意是距离)距离长的是导通状态,短的是接通状态。 通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号 如下图所示:

    16cb70e59c954f8b27b1f48f7f4583ee.png

    如图所示,按键闭合式不会立刻稳定的接通,断开时也不会一下子断开,会伴随一些抖动。抖动的时间长短有按键特性决定,一般为5Ms到10ms.按键抖动会引起按键被误读多次。为了确保 CPU 对按键的一次闭合仅作一次处理,必须进行消抖

    • 消抖 消抖可分为硬件消抖和软件消抖。为了使电路更加简单,通常采用软件消抖。 一般来说一个简单的按键消抖就是先读取按键的状态, 如果得到按键按下之后, 延时 10ms, 再次读取按键的状态,如果按键还是按下状态,那么说明按键已经按下。 其中延时 10ms 就是软件消抖处理。 消抖过程(软件) 1,先设置 IO 口为高电平(由于开发板 IO 都有上拉电阻,所以默认 IO 为高电平)。 2,读取 IO 口电平确认是否有按键按下。 3,如有 IO 电平为低电平后,延时几个毫秒。 4,再读取该 IO 电平,如果任然为低电平,说明对应按键按下。 5,执行相应按键的程序。
    • 键盘 键盘分为编码键盘和非编码键盘。键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘。而靠软件编程来识别的键盘称为非编码键盘,在单片机组成的各种系统中,用的较多的是非编码键盘。非编码键盘又分为独立键盘和行列式键盘(常说的矩阵键盘)。独立按键用的就是独立键盘。
    • 实现原理 原理图:

    12523516da8e4e5d7ebdb568b0980694.png

    独立按键电路构成是由各个按键的一个管脚连接在一起接地,按键其他引脚分别接到单片机 IO 口。 单片机的 IO 口既可作为输出也可作为输入使用,当检测按键时用的是它的输入功能,独立按键的一端接地,另一端与单片机的某个 I/O 口相连,开始时先给该 IO 口赋一高电平,然后让单片机不断地检测该 I/O 口是否变为低电平,当按键闭合时,即相当于该 I/O 口通过按键与地相连,变成低电平,程序一旦检测到 I/O 口变为低电平则说明按键被按下,然后执行相应的指令。

    e964b91172f5474946ce39f29549c7c9.png

    由图可以看出,单片机的管脚(p1,p3,等管脚)都接有上拉电阻,上拉电阻接高电平。因此我们在消抖检测时,若按键以已经按下,则管脚接地,变为低电平,若管脚为低电平,则说明按键已经按下,执行LED灯点亮的步骤。

    • 代码实现
    #include <reg52.h>
    #include <intrins.h>
    typedef unsigned char u8; //重定义全局字符型变量
    typedef unsigned int u16; //重定义全局整型变量
    sbit LED=P2^0 ;  //LED接P2口
    sbit K1=P3^1; //按键k1接p3口,也可以是其他管脚
    
    /*延时函数*/
    void dealy(u16 i)
    {
    while(i--);
    }
    
    /*独立按键执行函数
    */
    void KeyProcess()
    {  
       if(K1==0){
         dealy(1000);
             //一个int型的所占的时间大约为10微妙,所以乘1000大约为10ms.
             if(K1==0){  //消抖后仍为低电平,则执行点亮进程
              LED=~LED;    //为了让LED产生明暗变化
             }
             while(!K1);  //判断按键是否松开,假如松开,则K1为真,加!为假,则循环结束跳出循环
       }
       
    }
    
    void main()
    { 
      LED=0;  //初始时灯位熄灭状态(LED原理),
      while(1)
      {
            KeyProcess();
      }      
    }
     

    矩阵按键实验

    • 前面我们讲到独立按键,接下来我们引入独立按键。为什么引入矩阵按键?
      独立键盘与单片机连接时,每一个按键都需要单片机的一个 I/O 口,若某单片机系统需较多按键,如果用独立按键便会占用过多的 I/O 口资源。单片机系统中 I/O 口资源往往比较宝贵,多个按键时为了减少 I/O 口引脚。
    • 4 * 4键盘的工作原理
      矩阵按键原理图

    6c2cad51cfa3be07e9c9b70a1a9fa429.png

    开发板上将 16 个按
    键排成 4 行 4 列,第一行将每个按键的一端连接在一起构成行线,第一列将每
    个按键的另一端连接在一起构成列线,这样便一共有 4 行 4 列共 8 根线,我们将
    这 8 根线连接到单片机的 8 个 I/O 口上,通过程序扫描键盘就可检测 16 个
    键。

    • 矩阵按键的消抖
      1.检查按键是否按下

    e964b91172f5474946ce39f29549c7c9.png


    由原理图可知,独立按键和矩阵按键是有所不同的。独立按键的各个按键一端接引脚,一端并联在一起接地。所以检测按键是否按下只需要看单片机的管脚是否为低电平即可。而矩阵按键,他们的两端分别并联在一起,
    每一行(共4行)并联在一起接高位管脚上(7~4),每一列(共4列)并联在一起接到低位管脚上(3~0)。
    所以检测方法有所不同。
    一般情况下有两种方法。
    方法一:
    逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。逐行扫描的时间是非常快的,肉眼难以观察。
    举个例子,假设此时p7管脚为低电平,那么第一行按键的一段都为低电平,另一端分别连接低4位的管脚,只有当某一个开关按下,低4位的管脚与其中一个低电平的管脚连接变为低电平,所以只要查看低4位那个管脚为低电平就可以确定那个按键以按下。其他三行同理,每一行依次不断进行。
    方法二:
    行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。相当于第一次确定列,第二次确定行,行列交叉形成点,这个点就是我们要找的已经闭合的按键。

    • 静态数码管显示按键

    5051d5b9a0e709145baa61098b08728e.png


    如图,每一个按键可用一个键值来代替,让对应的键值号来作为静态数码管的段选,从而实现按下按键显示数字的效果。

    • 代码实现
      采用第二种行列扫描的检测方法
    #include <reg52.h>                         //此文件中定义了单片机的一些特殊功能寄存器
    
    typedef unsigned int u16;         //对数据类型进行声明定义
    typedef unsigned char u8;
    
    #define GPIO_DIG P0        //宏定义p0口(静态显示数码管对应的管脚)
    #define GPIO_KEY P1       //矩阵按键对应管脚
    
    
    u8 KeyValue;    //用来存放读取到的键值
    
    
    u8 code smgduan[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
                                            0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//显示0~F的值
    
    /*延时·函数*/
    void delay(u16 i)
    {
            while(i--);     
    }
    
    /*检测按键是否按下,消抖,读取键值*/
    void KeyDown(void)
    {
            char a=0;
            GPIO_KEY=0x0f;    
            //0x0f转化为为二进制为0000 1111,即矩阵按键的八个管脚,高位为低电平(0),低位为高电平(1)
            if(GPIO_KEY!=0x0f)//读取按键是否按下
            {
                    delay(1000);//延时10ms进行消抖
                    if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
                    {       
                            /*对列进行测试(高位低电平,低位高电平)*/
                            GPIO_KEY=0X0F;
                            switch(GPIO_KEY)
                            {
                                    case(0X07): KeyValue=0;break; //对应管脚高低电平0000 0111,第0列
                                    case(0X0b): KeyValue=1;break; //对应管脚高低电平0000 1011,第1列
                                    case(0X0d): KeyValue=2;break; //对应管脚高低电平0000 1101,第2列
                                    case(0X0e): KeyValue=3;break;//对应管脚高低电平0000 1110,第3列
                            }
                            /*对行进行测试(低位高电平,高位低电平)*/
                            GPIO_KEY=0XF0;
                            switch(GPIO_KEY)
                            {        /*上一行对应的列号加上相应有规律的字号就等于按键号,可由原理图查看*/
                                    case(0X70): KeyValue=KeyValue;break; //对应管脚高低电平0111 0000,第0行
                                    case(0Xb0): KeyValue=KeyValue+4;break; //对应管脚高低电平1011 0000,第1行
                                    case(0Xd0): KeyValue=KeyValue+8;break;//对应管脚高低电平1101 0000,第2行
                                    case(0Xe0): KeyValue=KeyValue+12;break;     //对应管脚高低电平1110 0000,第0行
                            }
                            
                    }
            }
            while((a<50)&&(GPIO_KEY!=0xf0))
        //检测按键松手检测(只有当按键松开时矩阵连接的管脚高位和低位才会互换继续检测行。否则进行循环延迟)
            {
                    delay(100);
                    a++;
            }
    }
    
    /*主函数*/
    void main()
    {	
    
    	while(1)
    	{	
    		KeyDown();		   //按键判断函数
    		GPIO_DIG=~smgduan[KeyValue];	  //
    	}		
    }
    展开全文
  • 原理搞清楚了,那么下面我们就先编写一个独立按键的程序,把最基本的功能验证一下。 #include &lt;reg52.h&gt; sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED =...
  • 矩阵键盘扫描原理详解——单片机

    千次阅读 2019-04-23 10:50:26
    矩阵键盘扫描原理详解 根据原理图 键盘扫描方法是:行线P10~P13为输出线,列线P14~P17为输入线。一开始单片机将行线(P10~P13)全部输出低电平,此时读入列线数据,若列线全为高电平则没有键按下,当列线有出现低...
  •  先附上矩阵键盘的原理图: 在使用据矩阵键盘时,J5 排针处的跳帽连接 1 脚和 2 脚,使所有按键的有效端口全部连接至 I/O 口。 具体的扫描方式为: 先把P3^0~P3^7高四位和第四位赋不一样的电平值,当确定有键按...
  • 按键是一种常开型按钮开关,与单片机的常见接法如图所示。按键未按下时两个触点断开,单片机I/O口输入高电平;当按键闭合时,I/O口输入低电平。一、按键讲解当I/O口为P0口时,由于没有内部上拉电阻,所以必须外接上...
  • 以金沙滩工作室的STC89C52单片机开发板为例,记录学习51单片机的笔记,本文章主要讲解了4×4矩阵按键扫描,教材是金沙滩工作室(www.kingst.org )宋雪松老师编著的《手把手教你学51单片机-C语言版》,所用的...
  • 1独立按键独立按键模块位置示意图硬件连接原理:图1.2独立按键原理图把对应的端口赋值高电平,即“1”,按键按下,端口被拉低至低电平,即“0”,通过检测该端口的电平即可判断按键是否按下。去抖分析:按键是机械...
  • 按键扫描

    千次阅读 2012-11-14 15:15:23
    按键作为人类向单片机传递指令的载体,在单片机控制系统中,占有重要的地位,按键失灵,如同人失聪一样不听使唤,使控制系统陷入失控状态。按结构原理来分,按键有机械按键、薄膜按键、电容式触摸按键和电阻式触摸...
  • 本系列文章讲述了基于proteus仿真的51单片机学习,内容全面,不仅讲解电路原理,还讲解了单片机c语言,实例丰富,内容全面。
  • 按键扫描原理及实现 在独立键盘模式时,要将J5跳在BTN模式。也就是J5中2,3短路。此时S7,S6,S5,S4一端直接接地,一端连接P30,P31,P32,P33。按键按下时P30,P31,P32,P33都为低电平。在程序中判断即可,为了防止抖动...
  • 在我们的实际产品开发过程中,为了节省成本,常常会...(上一讲已经讲过,我个人比较喜欢状态机编程,因此这里还是采用状态机编程的方法,来实现按键和LED复用扫描功能)。 一、按键和LED复用原理图如下: LED...
  • 要点 : 在扫描按键时运用了比较复杂的两个for()循环嵌套式扫描方案,大大减少了程序量,循环嵌套方案让我纠结了好久,键值有0~9,上,下,左,右,确认,清零;体会: 又一个里程碑,泪奔啊...我似乎成了 代码男神 啊...;实验...
  • 当按键按下时,相应的P30-33口输入为低电平,由此编写独立按键扫描函数。 矩阵按键 跳线帽需要短接J5口的1和2引脚,按键能使用16个(即上图中S4-S19)。矩阵按键的扫描方法可采用行列扫描法,分为两步: 将行的输出...
  • 51单片机入门教程(4)——按键控制

    万次阅读 多人点赞 2018-11-17 00:20:10
    按键输入一、独立按键1.1 独立按键的原理1.2 独立按键的仿真电路1.3 按键消抖二、矩阵键盘2.1 矩阵键盘原理2.2 矩阵键盘扫描原理矩阵键盘扫描程序 单片机与外界的信息交互主要有两大类,输入信息和输出信息。 之前的...
  • 51单片机之矩阵按键

    千次阅读 2019-07-20 13:57:14
    区别:矩阵按键为4*4即16个按键,如果都采用独立按键的解法,那么需要占用16个I/O接口,对于单片机而言是极大的浪费。 工作原理: 先见下图: 他有两种识别方式:逐行扫描、行列扫描。 (1)逐行扫描: 通俗...
  • 矩阵按键实验矩阵原理矩阵按键由来矩阵按键扫描原理代码实现 矩阵原理 矩阵按键由来 独立按键: 矩阵按键: 每一行管脚并联一起,每一列管脚并联一起,所以8个IO口就可以控制16个按键 P17到P10对应8个二进制位从高位...
  • 获得更多单片机以及c相关的资料以及源代码例程,请私信回复 “单片机”一,键盘接口的设计需要解决的问题需要判断是否有按键按下,如果有,那么进入下一个动作。识别是哪一个按键被按下?并求出相应的键值。根据键值...
  • 矩阵按键,顾名思义,就是形成矩阵的按键,一般由多行多列组成,如下图是一个4*4的矩阵按键;如果是独立按键,需要占用16个MCU引脚,而使用矩阵按键只需要8个 其原理图如下: 矩阵按照是如何检测哪个按下的呢? ...
  • 12.1 项目分析 矩阵键盘,是一种在节省端口的前提下控制大量按键的一种方法,对于传统的独立对地键盘,一个按键就需要占用一个单片机IO口,虽然有时候会加一些扩展芯片之类的用于一个端口控制多个按键,但是电路结构...
  • 这是一个基于普通51单片机和SIM800A模块的按键手机模拟的代码,附原理图,看完代码,你就可以掌握NOKIA5110屏幕的使用方法,矩阵按键在中断中扫描,检索字符串等等技能!
  • 矩阵按键扫描原理 方法一: 逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按...
  • 矩阵按键行列反转扫描

    千次阅读 2019-10-29 18:49:48
    51单片机 | 矩阵键盘行扫描 ———————————————————————————————————————————— 分类: 按结构原理分: 触点式开关按键 无触点开关按键 接入方式 独立式...
  • (1)单片机系统键盘原理  行列式键盘的接法比独立式键盘的接法复杂,编程实现上也会比较复杂。但是,在占用相同的I/O端口的情况下,行列式键盘的接法会比独立式接法允许的按键数量多,其原理图如图1所示。  ...
  • 51单片机LCD1602显示矩阵按键键值

    千次阅读 2019-02-11 18:24:16
    矩阵按键原理图 矩阵按键怎么变成独立按键 方法一: 逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 146
精华内容 58
关键字:

单片机按键扫描原理