打印
[经验分享]

矩阵键盘

[复制链接]
146|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Jiangxiaopi|  楼主 | 2025-4-13 21:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、矩阵键盘的工作原理
(1)矩阵键盘概述
矩阵键盘是单片机外部设备中所使用的排布类似于矩阵的键盘组。(内部实际走线为矩阵,外形一般表现为矩阵)
(2)组成结构
在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。
这样,一个端口(如P1口)就可以构成4*4=16个按键,比直接将端口线用于键盘多出了一杯,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的
内部实际走线为矩阵,外形一般表现为矩阵
(3)识别方法
当按键没有按下时,所有的输入端都是高电平,代表无按键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了;
“行扫描法”
又成逐行(列)扫描查询法,是一种最常用的按键识别方法:依次将行线置为低电平。在确定某根线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
“高低电平翻转法”
首先让P口高四位为1,低四位为0,若有按键按下,则高思维中会有一个1翻转为0,低四位不会变,此时即可确定备案下的键的行的位置。然后让P口高四位为0,低四位为1,若有按键按下,则低四位中会有一个1翻转为01,高四位不会变,此时即可确定被按下的键的列位置。最后将上述两者进行或运算即可确定被按下的键的位置。
二、矩阵键盘电路原理图
示例:假设只想编写一列,可以将P44输出为0(低电平)
三、单片机I/O口快速输入/输出
(1)例程1:以独立键盘程序为基础将]5跳线帽切换为矩阵键盘模式后先写出其中一列矩阵按键的程序。以S7、S6、S5、S4为例。
只在原来的KeyScan函数的第一行加上P44 = 0;即可实现在矩阵键盘中使用一列键盘;
//头文件声明区域
#include <STC15F2K60S2.H>
#include<intrins.h>

//变量声明区域

unsigned char S7_Flag = 0,S6_Flag = 0,S5_Flag = 0,S4_Flag = 0;

//函数声明区域

//毫秒级延时函数
void Delay(unsigned int ms);


//按键扫描函数
void KeyScan(void);

//程序主体
void main()
{
        P2 = 0XA0;P0 = 0X00;P2 = 0X80;P0 = 0XFF;//初始化程序
while(1)
{
        KeyScan();
       
        if(S7_Flag == 1) {S7_Flag = 0; P00 = 0;}
        if(S6_Flag == 1) {S6_Flag = 0; P00 = 1;}
        if(S5_Flag == 1) {S5_Flag = 0; P06 = 0;}
        if(S4_Flag == 1) {S4_Flag = 0; P06 = 1;}
}       
       
       
}
//毫秒级延时函数
void Delay(unsigned int ms)                //@11.0592MHz
{
        unsigned char i, j;
        while(ms--)
        {
        _nop_();
        _nop_();
        _nop_();
        i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);
        }
       
}
//按键扫描函数
void KeyScan(void)
{
        P44 = 0;
        if(P30 == 0)
        {
                Delay(10);
                if(P30 == 0)
                {
                        S7_Flag = 1;
                        while(!P30);
                }
        }
                if(P31 == 0)
                {
                        Delay(10);
                        if(P31 == 0)
                        {
                                S6_Flag = 1;
                                while(!P31);
                        }
                }
               
                if(P32 == 0)
                {
                        Delay(10);
                        if(P32 == 0)
                        {
                                S5_Flag =1;
                                while(!P32);
                        }
                }
               
                if(P33 == 0)
                {
                        Delay(10);
                        if(P33 == 0)
                        {
                                S4_Flag = 1;
                                while(!P33);
                        }
                }
}

(2)例程2:根据例程1可以编写多列矩阵键盘程序。本例以写出第一列、第二列矩阵键盘程序按下S7、56、S5、S4、S11、510、59、S8按键,依次用第一位数码管依次显示1、2、3、4、5、6、7、8数值。
假设只写出第一列,将P44置为0时候,按下按键后,只要判断P30 P31 P32 P33谁为0即可;只写第二列,将P42置为0,仍是只要判断P30 P31 P32 P33谁为即可;
但是如果现在要同时写两列,应该如何写,思路:因为单片机程序执行的非常快,所以可以先讲P44置为0,然后对第一列进行扫描,如果有按键被按下,即可知道哪个按键被按下;如果没有按键被按下,那么将接下来P44置为1,将P42置为0,再对第二列进行扫描,不停地进行扫描,循环进行,即可知道哪个按键被按下。
//头文件声明区域
#include <STC15F2K60S2.H>
#include<intrins.h>

//变量声明区域

unsigned char S7_Flag = 0,S6_Flag = 0,S5_Flag = 0,S4_Flag = 0,S11_Flag = 0,S10_Flag = 0,S9_Flag = 0,S8_Flag = 0;
unsigned char code SEG[] = {0XF0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};

//函数声明区域

//毫秒级延时函数
void Delay(unsigned int ms);


//按键扫描函数
void KeyScan(void);

//程序主体
void main()
{
        P2 = 0XA0;P0 = 0X00;P2 = 0X80;P0 = 0XFF;//初始化程序
        P2 = 0XC0;P0 = 0X01;P2 = 0XFF;P0 = 0XFF;//打开第一个数码管程序
while(1)
{
        KeyScan();
       
        if(S7_Flag == 1)  {S7_Flag = 0;  P0 = SEG[1];}
        if(S6_Flag == 1)  {S6_Flag = 0;  P0 = SEG[2];}
        if(S5_Flag == 1)  {S5_Flag = 0;  P0 = SEG[3];}
        if(S4_Flag == 1)  {S4_Flag = 0;  P0 = SEG[4];}
        if(S11_Flag == 1) {S11_Flag = 0; P0 = SEG[5];}
        if(S10_Flag == 1) {S10_Flag = 0; P0 = SEG[6];}
        if(S9_Flag == 1)  {S9_Flag = 0;  P0 = SEG[7];}
        if(S8_Flag == 1)  {S8_Flag = 0;  P0 = SEG[8];}
}       
       
       
}
//毫秒级延时函数
void Delay(unsigned int ms)                //@11.0592MHz
{
        unsigned char i, j;
        while(ms--)
        {
        _nop_();
        _nop_();
        _nop_();
        i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);
        }
       
}
//按键扫描函数
void KeyScan(void)
{
        P44 = 0;P42 = 1;
        if(P30 == 0)
        {
                Delay(10);
                if(P30 == 0)
                {
                        S7_Flag = 1;
                        while(!P30);
                }
        }
                if(P31 == 0)
                {
                        Delay(10);
                        if(P31 == 0)
                        {
                                S6_Flag = 1;
                                while(!P31);
                        }
                }
               
                if(P32 == 0)
                {
                        Delay(10);
                        if(P32 == 0)
                        {
                                S5_Flag =1;
                                while(!P32);
                        }
                }
               
                if(P33 == 0)
                {
                        Delay(10);
                        if(P33 == 0)
                        {
                                S4_Flag = 1;
                                while(!P33);
                        }
                }
                P44 = 1;P42 = 0;
        if(P30 == 0)
        {
                Delay(10);
                if(P30 == 0)
                {
                        S11_Flag = 1;
                        while(!P30);
                }
        }
                if(P31 == 0)
                {
                        Delay(10);
                        if(P31 == 0)
                        {
                                S10_Flag = 1;
                                while(!P31);
                        }
                }
               
                if(P32 == 0)
                {
                        Delay(10);
                        if(P32 == 0)
                        {
                                S9_Flag =1;
                                while(!P32);
                        }
                }
               
                if(P33 == 0)
                {
                        Delay(10);
                        if(P33 == 0)
                        {
                                S8_Flag = 1;
                                while(!P33);
                        }
                }
}

(3)例程3:根据例程1可以编写多列矩阵键盘程序。本例以写出第一列、第二列矩阵键盘程序按下57、56、S5、54、S11、S10、59、S8按键,依次用第一位数码管依次显示1、2、3、4、5、6、7、8数值。注:使用一个按键关键词来代替某一个按键被按下。
//头文件声明区域
#include <STC15F2K60S2.H>
#include<intrins.h>

//变量声明区域

unsigned char Key_Flag = 0;
unsigned char code SEG[] = {0XF0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};

//函数声明区域

//毫秒级延时函数
void Delay(unsigned int ms);


//按键扫描函数
void KeyScan(void);

//程序主体
void main()
{
        P2 = 0XA0;P0 = 0X00;P2 = 0X80;P0 = 0XFF;//初始化程序
        P2 = 0XC0;P0 = 0X01;P2 = 0XFF;P0 = 0XFF;//打开第一个数码管程序
while(1)
{
        KeyScan();
       
        switch(Key_Flag)
        {
                case 7:P0 = SEG[1];break;
                case 6:P0 = SEG[2];break;
                case 5:P0 = SEG[3];break;
                case 4:P0 = SEG[4];break;
                case 11:P0 = SEG[5];break;
                case 10:P0 = SEG[6];break;
                case 9:P0 = SEG[7];break;
                case 8:P0 = SEG[8];break;
                default:break;
        }
}       
       
       
}
//毫秒级延时函数
void Delay(unsigned int ms)                //@11.0592MHz
{
        unsigned char i, j;
        while(ms--)
        {
        _nop_();
        _nop_();
        _nop_();
        i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);
        }
       
}
//按键扫描函数
void KeyScan(void)
{
        P44 = 0;P42 = 1;
        if(P30 == 0)
        {
                Delay(10);
                if(P30 == 0)
                {
                        Key_Flag = 7;
                        while(!P30);
                }
        }
                if(P31 == 0)
                {
                        Delay(10);
                        if(P31 == 0)
                        {
                                Key_Flag = 6;
                                while(!P31);
                        }
                }
               
                if(P32 == 0)
                {
                        Delay(10);
                        if(P32 == 0)
                        {
                                Key_Flag = 5;
                                while(!P32);
                        }
                }
               
                if(P33 == 0)
                {
                        Delay(10);
                        if(P33 == 0)
                        {
                                Key_Flag = 4 ;
                                while(!P33);
                        }
                }
                P44 = 1;P42 = 0;
        if(P30 == 0)
        {
                Delay(10);
                if(P30 == 0)
                {
                        Key_Flag = 11;
                        while(!P30);
                }
        }
                if(P31 == 0)
                {
                        Delay(10);
                        if(P31 == 0)
                        {
                                Key_Flag = 10;
                                while(!P31);
                        }
                }
               
                if(P32 == 0)
                {
                        Delay(10);
                        if(P32 == 0)
                        {
                                Key_Flag = 9;
                                while(!P32);
                        }
                }
               
                if(P33 == 0)
                {
                        Delay(10);
                        if(P33 == 0)
                        {
                                Key_Flag = 8;
                                while(!P33);
                        }
                }
}


————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/La_gloire/article/details/136381789

使用特权

评论回复
沙发
yangxiaor520| | 2025-4-14 08:18 | 只看该作者
矩阵键盘主要是靠动态扫描来实现IO的复用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

115

帖子

0

粉丝