文章目录
1、前言
在前面的文章中介绍了51单片机之模块化编程及LCD1602调试,今天介绍单片机的矩阵键盘。
2、矩阵键盘
2-1、矩阵键盘介绍
矩阵键盘(Matrix Keyboard)是一种在单片机外部设备中广泛使用的键盘组,其结构类似于矩阵。与独立按键相比,矩阵键盘能够以更少的I/O端口实现更多的按键功能。这种键盘通过行列线交叉连连接的方式实现,按键位于行与列的交叉点。例如,一个4x4的矩阵键盘只需要8(4+4)个I/O口,就可以读取16个按键的状态。
2-2、结构
矩阵键盘的结构主要包括以下几个部分:
- 按键:矩阵键盘中的每个键位由一个开关组成,负责在开关打开或关闭时的传导作用。
- 电路板:矩阵键盘中的行线和列线通过电路板上的连接点相互交叉又,每个交叉点对应一个按键。
- 控制芯片:控制芯片负责扫描键盘矩阵,识别按键信息,并转偷出给主控芯片或设备。
2-3、工作原理
矩阵键盘的工作原理基于行列扫描技术,通过逐行或逐列扫描的方式检测按键状态。以4×4矩阵键盘为例,设有4条行线和4条列线,共16个交叉点,每个交叉点对应一个按键。扫描过程分为两个步骤:
- 判断键盘中有无键按下:首先,将所有行线置为低电平,然后检测列线的状态。只要有一列的电平为低,就表示键盘中有键建被按下,且闭合的键位于低电平行线与所有行线相交叉的按键之中。若所有列线均为高电平,则键盘中无键按下。
- 判断闭合键所在的位置:在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平,其他行线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
3、扫描的概念
- 数码管扫描(输出扫描),其原理:显示第1位→显示第2位→显示第3位→…然后快速循环这个过程,最终实现所有数码管同时显示的效果。
- 矩阵键盘扫描(输入扫描),其原理:读取第1行(列)→读取第2行(列)→读取第3行(列)→…然后快速循环这个过程,最终实现所有按键同时检测的效果。
- 以上两种扫描方式的共性:节省l/O口资源。
4、独立按键VS矩阵按键原理图
注意:按行扫描:首先是给第一行(P17)低电平,然后其余三行(P16、P15、P14)都是高电平;读取每列的电平状态。若是P13为电平,则是S1按键被按下;若是P12为电平,则是S2按键被按下;P11为电平,则是S3按键被按下;P10为电平,则是S4按键被按下。以此类推到其余三行进行扫描。按列扫描:由于单片机的I/O是属于弱上拉模式(准双向口),属于高电平驱动能力弱,低电平驱动能力更强点。首先是给第一列(P13)低电平,然后其余三行(P12、P11、P10)都是高电平;读取每行的电平状态。
5、I/O口各种不同的工作模式及配置介绍(扩展)
5-1、I/O口配置
- STC89C52系列单片机所有I/O口均(新增P4口)有3种工作类梦型:准双向口/弱上拉(标准8051输出模式)、仅为输入(高阻)或开漏输出功能。
- STC89C52系列单片机的P1/P2/P3/P4上电复位后为准双向口/弱上拉(传统8051的I/O口)模式,I/O口上电复位后是开漏输出。P0口作为总线扩展用时,不用加上拉电阻,作为I/O口用时,需加10K-4.7K上拉电阻。STC89C52的5V单片机的P0口的灌电流最大为12mA,其他I/O口的溶建电流最大为6mA。STC89LE52系列的3V单片机的P0口的灌电流最大为8mA,其他I/O口的灌电流最大为4mA。
5-2、准双向口输出配置
- 准双向口输出类型可用作输出和输入功能而不需重新配置口线输出状态。这是因为当口线输出为1时驱动能力很弱,允许外部装置将其拉低。当引脚输出为低时,它的驱动能力很强,可吸收相当大的电流。准双向口有3个上拉晶体管适应不同的需要。
- 在3个上拉晶体管中,有1个上拉晶体管称为**“弱上拉”**,当口线寄存器为1且引脚本身也为1时打开。此上拉提供基本驱动电流使准双向口输出为1。如果一个引脚输出为1而由外部装置下拉到低时,弱上拉关闭而"极弱上拉"维持开状态,为了把这个引脚强拉为低,外部装置必须有足够的灌电流能力使引脚上的电压降到门槛电压以下。
- 第2个上拉晶体管,称为**“极弱上拉”**,当口线锁存为1时打开。当引脚悬空时,这个极弱的上拉源产生很弱的上拉电流将引脚上拉为高电平。
- 第3个上拉晶体管称为**“强上拉”**。当口线锁存器由0到1跳变时,这个上拉用来加快准双向口由逻辑0到逻辑1转换。当发生这种情况时,强上拉打开约2个时钟以使引脚能够迅速地上拉到高电平。准双向口输出如Figure2. 准双口输出所示。
- 准双向口带有一个干扰抑制电路。准双向口读外部状态前,要先锁存为’1’,才可读到外部正确的状态。
5-3、开漏输出配置(P0口上电复位后处于开漏模式)
- P0口上电复位后处于开漏模式,当P0管脚作I/O口时,需久外加10K-4.7K的上拉电阻,当P0管脚作为地址/数据复用总线使用时,不用外加上拉电阻。
- 当口线锁存器为0时,开漏输出关闭所有上拉晶体管。当作为一个逻辑输出时,这种配置方式必须有外部上拉,一般通过电阻外接到Vcc。如果外部那有上拉电阻,开漏的I/O口还可读外部状态,即此时被配置为开漏模式的I/O口还可作为输入I/O口。这种方式的下拉与准双向口相同。输出口线配置如Figure3. 开漏输出配置(P0口上电复位后处于开漏模式)所示。开漏端口带有一个干扰抑制电路。
6、程序编码
6-1、工程文件
#include <REGX52.H>
#include "MatrixKeyboard.h"
#include "Delay.h"
/***
* @brief Matrix Keyboard read key number
* @param None
* @retval KeyNumber press button key number
***/
unsigned char MatrixKeyboard()
{
unsigned char KeyNumber = 0;
P1 = 0xFF;
P1_3 = 0; // First cloum is low level.
if(0 == P1_7)
{
DelayMs(20);
while(0 == P1_7)
DelayMs(20);
KeyNumber = 1;
} // S1
if(0 == P1_6)
{
DelayMs(20);
while(0 == P1_6)
DelayMs(20);
KeyNumber = 5;
} // S5
if(0 == P1_5)
{
DelayMs(20);
while(0 == P1_5)
DelayMs(20);
KeyNumber = 9;
} // S9
if(0 == P1_4)
{
DelayMs(20);
while(0 == P1_4)
DelayMs(20);
KeyNumber = 13;
} // S13
P1 = 0xFF;
P1_2 = 0; // second cloum is low level.
if(0 == P1_7)
{
DelayMs(20);
while(0 == P1_7)
DelayMs(20);
KeyNumber = 2;
} // S2
if(0 == P1_6)
{
DelayMs(20);
while(0 == P1_6)
DelayMs(20);
KeyNumber = 6;
} // S6
if(0 == P1_5)
{
DelayMs(20);
while(0 == P1_5)
DelayMs(20);
KeyNumber = 10;
} // S10
if(0 == P1_4)
{
DelayMs(20);
while(0 == P1_4)
DelayMs(20);
KeyNumber = 14;
} // S14
P1 = 0xFF;
P1_1 = 0; // thirst cloum is low level.
if(0 == P1_7)
{
DelayMs(20);
while(0 == P1_7)
DelayMs(20);
KeyNumber = 3;
} // S3
if(0 == P1_6)
{
DelayMs(20);
while(0 == P1_6)
DelayMs(20);
KeyNumber = 7;
} // S7
if(0 == P1_5)
{
DelayMs(20);
while(0 == P1_5)
DelayMs(20);
KeyNumber = 11;
} // S11
if(0 == P1_4)
{
DelayMs(20);
while(0 == P1_4)
DelayMs(20);
KeyNumber = 15;
} // S15
P1 = 0xFF;
P1_0 = 0; // fourst cloum is low level.
if(0 == P1_7)
{
DelayMs(20);
while(0 == P1_7)
DelayMs(20);
KeyNumber = 4;
} // S4
if(0 == P1_6)
{
DelayMs(20);
while(0 == P1_6)
DelayMs(20);
KeyNumber = 8;
} // S8
if(0 == P1_5)
{
DelayMs(20);
while(0 == P1_5)
DelayMs(20);
KeyNumber = 12;
} // S12
if(0 == P1_4)
{
DelayMs(20);
while(0 == P1_4)
DelayMs(20);
KeyNumber = 16;
} // S16
return KeyNumber;
}
6-2、工程测试结果
6-3、电子密码锁
前提:把S1~S9当作数字1 ~ 9,S10当作0,S11当作确认键,S12当作取消键。
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "MatrixKeyboard.h"
void main()
{
unsigned char KeyNumber = 0;
unsigned int Password = 0;
unsigned int Count = 0;
LCD_Init();
LCD_ShowString(1,1,"Password: ");
while(1)
{
KeyNumber = MatrixKeyboard();
if(KeyNumber != 0)
{
/* If S1~S10 key is pressed, please input password. */
if(KeyNumber <= 10)
{
if(Count < 4)
{
/* Password left move one bit. */
Password *= 10;
/* Get one bit Password. */
Password += KeyNumber%10;
Count++;
}
/* Update show number. */
LCD_ShowNum(2,1,Password,4);
}
if(KeyNumber == 11) // OK key
{
if(Password == 2345)
{
LCD_ShowString(1,11,"Ok!Ok!!");
Password = 0;
Count = 0;
LCD_ShowNum(2,1,Password,4);
}
else
{
LCD_ShowString(1,11,"Eeror!");
Password = 0;
Count = 0;
LCD_ShowNum(2,1,Password,4);
}
}
if(KeyNumber == 12) // Cancel Key
{
LCD_ShowString(1,11,"Cancel");
Password = 0;
Count = 0;
LCD_ShowNum(2,1,Password,4);
}
}
}
}