基于单片机的矩阵键盘检测案例

描述

若单片机需要连接多个按键,每个按键与单片机的I/O端口单独连接的方式就不太适用了,因为单片机的I/O端口是单片机系统与外界设备交互的重要资源,如果采用按键与I/O端口独立连接的方式,就会占用过多的I/O端口资源,导致单片机与其它外部设备无法连接。在这种情况下,可以使用矩阵键盘,实现多个按键与单片机的连接,而且不浪费单片机的I/O端口资源。

矩阵键盘是一种很好地节约I/O端口资源的技术方法,矩阵键盘将多个按键排列成矩阵形式。例如:将16个按键排成4行4列,每行将按键的一端连接在一起构成行线,每列将按键的另一端连接在一起构成列线,这样一共有4行4列8根线,将这8根线连接到单片机的8个I/O端口上,通过检测程序扫描矩阵键盘就可以检测16个按键。通过这种连接方式,可以实现3行3列9个键,5行5列25个键,6行6列36个键等多个按键的检测。

端口

上图为设计的4 X 4矩阵键盘,每行4个按键,每列4个按键,可以检测16个按键。每列按键的右端连接在一起,分别连接P3.4 ~ P3.7,每行按键的左端连接在一起,分别连接P3.0~P3.3,这样可以使用8个I/O端口检测16个按键。

虽然矩阵键盘充分利用了I/O端口资源,但增加了检测程序的复杂性。因为独立按键有一端固定为低电平,编写单片机键盘检测程序比较方便,而矩阵键盘两端都与I/O端口相连,因此检测程序需要向I/O端口人为送出低电平。具体检测方法:先送一行低电平,其余各行为高电平,现在已经确定了行数(送入低电平的行),然后循环检测与该行相交的各列是否有低电平,若检测到某列有低电平,说明与该行相交的某列按键被按下,即确定了当前按下的按键属于哪一行哪一列。同理,使用同样的方法轮流送各行一次低电平,再轮流检测各列是否有低电平,即可完成所有按键的检测。当然也可以先送各列为低电平,然后再循环检测各行是否有低电平。

矩阵键盘应用案例:应用16个独立按键构成4行4列的矩阵键盘,行线接P3.0 ~ P3.3,列线接P3.4~P3.7。按键排列顺序为:1行1列为第1个按键,1行2列为第2个按键,……,2行1列为第5个按键,2行2列为第6个按键,……,4行4列为第16个按键。要求用户按下按键1后,数码管显示数字1,按下按键2后,数码管显示数字2,……,依次显示3,4,5,6,7,8,9,A,B,C,D,E,F。

下图是矩阵键盘案例电路设计图:

端口

数码管采用7SEG-MPX1-CA,为共阳极数码管,独立按键采用SPST Push Button,请同学们参考上图使用proteus绘制电路设计图。

单片机内运行的完整C程序如下:

#include
#include
unsigned char led[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8,0x3,0xc6,0x21,0x6,0xe};
unsigned char key[] = {0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};
unsigned char rowscan[] = {0xfe,0xfd,0xfb,0xf7};
void delay(unsigned int millisecond)
{
       unsigned int i,j;
       for(i=millisecond;i >0;i--)
              for(j=120;j >0;j--);
}
void show_keyvalue(int keynum)
{
              P0 = led[keynum];
         delay(100);
}
void marix_keyscan()
{
       unsigned int i,j;
       unsigned char temp;
       for( i = 0; i< 4; i++ )
       {
               P3 = rowscan[i];
               temp = P3;
               temp = temp & 0xf0;
               if( temp != 0xf0 )
               {
                        delay(10);
                       temp = P3;
                  temp = temp & 0xf0;
                       if( temp != 0xf0 )
                            {
                               temp = P3;
                                    for( j = 0; j < 16; j++ )
                                    {
                                           if( temp == key[j] )
                                                          break;
                                    }
                                    while(temp != 0xf0)
                                    {
                                            temp = P3;
                                            temp = temp & 0xf0;
                                    }
                                    show_keyvalue(j);
                            }
               }
    
       }
}
void main(void)
{
        while(1)
        {
                 marix_keyscan();
        }
 }

程序设计思路:

按矩阵键盘的行线和列线顺序对16个按键进行编码,编码值是矩阵键盘某按键被按下后P3端口的值。例如:行1列1按键被按下后,P3端口的值为0xee,行2列1按键被按下后,P3端口的值为0xed。对所有按键进行编码后,可以通过P3端口的值来确定哪个按键被按下。

扫描矩阵键盘需要对4条行线循环送出低电平,然后再判断列线是否有低电平。在电路设计中矩阵键盘的4条行线接P3口的低4位P3.0 ~ P3.3,因此在行线循环中为P3口赋不同的值,即可完成对4条行线循环送出低电平的操作,1~4条行线送入低电平P3口的值分别为0xfe、0xfd、0xfb、0xf7。

矩阵键盘扫描程序需要一个循环结构,循环次数为矩阵键盘的行线数量,在循环体内依次为4条行线送入低电平,然后读取P3口的值,将P3口与0xf0进行与运算,若运算结果不为0xf0,说明有按键被按下(有列线为低电平),延迟10ms后再次检测有按键是否被按下,若确认有按键被按下,使用for循环遍历已定义16个按键编码值的数组,定位被按下按键的索引,最后调用数码管显示函数将按键索引对应的字符显示出来。

代码说明:

数组led[]定义了数码管显示的字符编码值,数组长度为16。数组key[]定义了16个按键的编码值,数组长度为16。数组rowscan[]定义了4条行线送入低电平P3口的值,数组长度为4。

delay()函数为时间延迟函数,show_keyvalue()为数码管显示字符的函数,参数keynum为字符led数组元素的索引,该索引与key数组元素的索引对应。marix_keyscan()为矩阵键盘扫描函数,用于检测按键是否被按下。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分