51单片机之矩阵键盘

51单片机之矩阵键盘独立键盘与单片机连接时,每一个按键都需要单片机的一个I/O口若某单片机系统需较多按键,如果用独立按键便会占用过多的I/O口资源。单片机系统中I/O口资源往往比较宝贵,当用到多个按键时为了节省I/O口口线,我们引入矩阵键盘。我们以4X4矩阵键盘为例讲解其工作原理和检测方法。将16个按键排成4行4列,第一行将每个按键的一端连接在一起构成行线,第一列将每个按键的另一端连接在一…

      独立键盘与单片机连接时,每一个按键都需要单片机的一个I/O口若某单片机系统需较多按键,如果用独立按键便会占用过多的I/O口资源。单片机系统中I/O口资源往往比较宝贵,当用到多个按键时为了节省I/O口口线,我们引入矩阵键盘。

      我们以4X4矩阵键盘为例讲解其工作原理和检测方法。将16个按键排成4行4列,第一行将每个按键的一端连接在一起构成行线,第一列将每个按键的另一端连接在一起构成列线,这样便一共有4行4列共8根线,我们将这8根线连接到单片机的8个I/O口上,通过程序扫描键盘就可检测16个键。用这种方法我们也可实现3行3列9个键、5行5列25个键、6行6列36个键等。

     无论是独立键盘还是矩阵键盘,单片机检测其是否被按下的依据都是一样的,也就是检测与该键对应的I/O口是否为低电平。独立键盘有一端固定为低电平,单片机写程序检测时比较方便。而矩阵键盘两端都与单片机I/O口相连,因此在检测时需人为通过单片机I/O口送出低电平。检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的,用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。当然我们也可以将行线置低电平,扫描列是否有低电平。这就是矩阵键盘检测的原理和方法。

    首先看一下电路图

   51单片机之矩阵键盘 

      上图是一个4X4 的矩阵键盘,一共是16 个按键。我们照习惯称横为“行”,“竖”为列。那么5、6、7、8 我们称之为“行线”,则1、2、3、4 称为“列线”。要正确记住各个行列线各自对应的IO。注意看,每一个按键的两端,都分别接在某一个列线和行线上,即:“行线和列线是通过某个按键的按下和抬起实现联通和断开的”,和“导线两端上的信号是经过“与”的关系再体现到导线上的。”这两句话便构成了矩阵键盘扫描的全部。要理解好,理解不了就背下来。

现在详细讲述一下矩阵键盘扫描的原理和步骤:

    

矩阵键盘扫描原理
方法一:
             逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
方法二:
             行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
 

   接下来举一个矩阵键盘的程序例子,该例子使用了P0、P1两组IO口,P1用来检测矩阵键盘中是否有按键按下,P0用来驱动静态数码管的显示。

   以下是示例程序:

 

#include "reg52.h"

   typedef unsigned char u8;
   typedef unsigned int u16;

   #define GPIO_DIG P0
   #define GPIO_KEY P1

   u8 code smgduan[16]= {0x3f, 0x06, 0x5b, 0x4f,
                    0x66, 0x6d, 0x7d, 0x07,
					0x7f, 0x6f, 0x77, 0x7c,
					0x39, 0x5e, 0x79, 0x71};//静态数码管码值

  u8 KeyColValue;
  u8 KeyLineValue;

  void delay(u16 i) //延时函数
  {
   while(i --);
  }

  void KeyDown() //键盘按键扫描函数
  {

  char a;

  GPIO_KEY = 0x0f;
  if(GPIO_KEY != 0x0f)//检测4行中哪一行按键是否按下
  {
   delay(1000); //延时消抖
   if(GPIO_KEY != 0x0f) //再次检测4行中哪一行按键是否按下
   {
   switch(GPIO_KEY) //根据IO的值来确定哪一行按键按下
   {
   case(0x07): KeyColValue = 0; break;
   case(0x0b): KeyColValue = 1; break;
   case(0x0d): KeyColValue = 2; break;
   case(0x0e): KeyColValue = 3; break;
   }
   }
  }

  GPIO_KEY = 0xf0;
  if(GPIO_KEY != 0xf0) //检测4行中哪一列按键是否按下
  {
   delay(1000);  //延时消抖
   if(GPIO_KEY != 0xf0) //再次检测4行中哪一列按键是否按下
   {
   switch(GPIO_KEY) //根据IO的值来确定哪一列按键按下
   {
   case(0x70): KeyLineValue = 0; break;
   case(0xb0): KeyLineValue = 1; break;
   case(0xd0): KeyLineValue = 2; break;
   case(0xe0): KeyLineValue = 3; break;
   }
   }

   while((a < 50) && (GPIO_KEY != 0xf0))  //延时,确保没有按键再按下
  {
   delay(1000);
   a ++;
  }

  }

  

  }

   void main()
   {
   while(1)
   {
   KeyDown();//检测按键是否按下
   GPIO_DIG = ~smgduan[KeyLineValue*4 + KeyColValue];//根据按键的行列值,静态数码管显示相应的值
   }
   }

     

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/38572.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注