一、先前知识
使用到的74HC138译码器、74HC573锁存器和数码管模块等,在前面的基础模块的介绍中都有简单介绍,这里就不再介绍了。
按键之矩阵键盘模块
蓝桥杯板子上按键部分的右下角有个J5模块,用跳帽来进行独立按键和矩阵键盘之间的切换。此次使用矩阵键盘的时候需要把跳帽接到1~2引脚。
矩阵键盘就是4×4,一共16个按键。其工作原理是,用跳帽将四行按键的左边都与单片机的引脚相连,那么电平就为单片机引脚输出电平。按键在没有按下的时候按键下方的两个触点是没有接在一起的,也就是说原理图上按键的左边脚始终是与单片机引脚输出的电平相同。当按键按下,按键下方的金属垫片接触时,两个触点接通,那么按键右边的脚(也是单片机其他的引脚)就会检测到与按键左边引脚相同的电平。就是依据此特征来判断按键是否被按下。
我们看到蓝桥杯板子上的按键是有四个脚的,而上篇文章中的独立按键和此次的矩阵键盘,似乎都只用到了两个脚,那么是不是错误的呢?
其实不是,按键虽然有四个端口,但是按键内部有两个脚是短接的,另外两个脚是引出脚,一个作为输入,一个作为输出。

图一、按键模块
部分代码解释
就第一行按键部分的代码而言(其他行按键的代码类似):
在矩阵键盘中要判断哪一个按键按下需要用到扫描的思想,从上到下依次给每一行低电平,当某一列检测到低电平的时候,就可以用坐标的思想,找到是哪一个按键被按下。一次只能把一行给低电平,扫哪一行哪一行就是低电平。
R1 = 0; // 先检测第一行按键是否被按下,那么就给第一行低电平
R2 = R3 = R4 = 1; // 其他行给高电平
C1 = C2 = C3 = C4 = 1; // 先初始化默认每一列的按键都没有被按下
if( C1 == 0 ) // 第一行第一列被按下,S7
{
while( C1 == 0 );
Key_Num = 7;
}
else if( C2 == 0 ) // 第一行第二列被按下,S11
{
while( C2 == 0 );
Key_Num = 11;
}
else if( C3 == 0 ) // 第一行第三列被按下,S15
{
while( C3 == 0 );
Key_Num = 15;
}
else if( C4 == 0 ) // 第一行第四列被按下,S19
{
while( C4 == 0 );
Key_Num = 19;
}
二、模块控制实现过程简述
先把按键的跳帽接到1~2引脚上,然后定义输出行和输入行,再用扫描的方法控制矩阵键盘。
三、所要实现的功能
首先上电之后数码管的后两位显示00,然后根据板子上矩阵键盘的每个按键的名称,当按键被按下后在数码管上显示相应的数字。(也就是如果某个按键上标的数是S07,那么该按键按下后数码管的后两位就显示07,如果某个按键上标的数是S16,那么该按键按下后数码管的后两位就显示16)程序循环实现上述功能。
四、代码实现
①引脚以及参数定义
// 矩阵键盘定义输入行
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;
// 矩阵键盘定义输出列
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;
// 参数定义
unsigned char Key_Num; // 按键角标
②数码管段码
// 数码管段码
unsigned char code SMG_Duanma[18] =
{
0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 , 0x92 , 0x82 , 0xf8 , 0x80 ,
0x90 , 0x88 , 0x80 , 0xc6 , 0xc0 , 0x86 , 0x8e , 0xbf , 0x7f
}; // 0~F - .
③138译码器通道选择函数
// 通道选择
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = (P2 & 0x1f) | 0x00; // 0
break;
case 4:
P2 = (P2 & 0x1f) | 0x80; // Y4C
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; // Y5C
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; // Y6C
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; // Y7C
break;
}
}
④初始化系统-关闭目前不需要的蜂鸣器和继电器
// 初始化系统
void Init_System(void)
{
// 关闭LED灯
HC138_Init( 4 );
P0 = 0xff
// 关闭蜂鸣器和继电器
HC138_Init( 5 );
P0 = 0xaf; // 1010 1111
HC138_Init( 0 ); // 关闭通道选择
}
⑤单个数码管点亮函数
// 单个数码管点亮
void SMG_Light( unsigned char pos , unsigned char dat )
{
HC138_Init( 6 );
P0 = 0x01 << pos; // 某个数码管处于准备阶段
HC138_Init( 7 );
P0 = dat; // 显示数值
}
⑥数码管显示函数
// 数码管显示
void SMG_Show( unsigned char num )
{
SMG_Light( 0 , 0xff ); // 不用的数码管就关闭
Delay_tms( 10 );
SMG_Light( 1 , 0xff );
Delay_tms( 10 );
SMG_Light( 2 , 0xff );
Delay_tms( 10 );
SMG_Light( 3 , 0xff );
Delay_tms( 10 );
SMG_Light( 4 , 0xff );
Delay_tms( 10 );
SMG_Light( 5 , 0xff );
Delay_tms( 10 );
SMG_Light( 6 , SMG_Duanma[ num / 10 ] );
Delay_tms( 10 );
SMG_Light( 7 , SMG_Duanma[ num % 10 ] );
Delay_tms( 10 );
}
⑦按键扫描函数
// 按键扫描
void Key_Scan(void)
{
// 第一行
R1 = 0;
R2 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if( C1 == 0 ) // S7
{
while( C1 == 0 );
Key_Num = 7;
}
else if( C2 == 0 ) // S11
{
while( C2 == 0 );
Key_Num = 11;
}
else if( C3 == 0 ) // S15
{
while( C3 == 0 );
Key_Num = 15;
}
else if( C4 == 0 ) // S19
{
while( C4 == 0 );
Key_Num = 19;
}
// 第二行
R2 = 0;
R1 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if( C1 == 0 ) // S6
{
while( C1 == 0 );
Key_Num = 6;
}
else if( C2 == 0 ) // S10
{
while( C2 == 0 );
Key_Num = 10;
}
else if( C3 == 0 ) // S14
{
while( C3 == 0 );
Key_Num = 14;
}
else if( C4 == 0 ) // S18
{
while( C4 == 0 );
Key_Num = 18;
}
// 第三行
R3 = 0;
R2 = R1 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if( C1 == 0 ) // S5
{
while( C1 == 0 );
Key_Num = 5;
}
else if( C2 == 0 ) // S9
{
while( C2 == 0 );
Key_Num = 9;
}
else if( C3 == 0 ) // S13
{
while( C3 == 0 );
Key_Num = 13;
}
else if( C4 == 0 ) // S17
{
while( C4 == 0 );
Key_Num = 17;
}
// 第四行
R4 = 0;
R2 = R3 = R1 = 1;
C1 = C2 = C3 = C4 = 1;
if( C1 == 0 ) // S4
{
while( C1 == 0 );
Key_Num = 4;
}
else if( C2 == 0 ) // S8
{
while( C2 == 0 );
Key_Num = 8;
}
else if( C3 == 0 ) // S12
{
while( C3 == 0 );
Key_Num = 12;
}
else if( C4 == 0 ) // S16
{
while( C4 == 0 );
Key_Num = 16;
}
}
⑧延时函数文章来源:https://www.toymoban.com/news/detail-775463.html
void Delay_tms( unsigned int t )
{
int i;
while( t-- )
{
for( i=115 ; i>0 ; i-- )
{
}
}
}
⑨整个函数展示文章来源地址https://www.toymoban.com/news/detail-775463.html
#include <STC15F2K60S2.H>
#include "Delay_ms.h"
// 矩阵键盘定义输入行
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;
// 矩阵键盘定义输出列
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;
// 参数定义
unsigned char Key_Num; // 按键角标
// 数码管段码
unsigned char code SMG_Duanma[18] =
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f
}; // 0~F - .
// 通道选择
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = (P2 & 0x1f) | 0x00; // 0
break;
case 4:
P2 = (P2 & 0x1f) | 0x80; // Y4C
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; // Y5C
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; // Y6C
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; // Y7C
break;
}
}
// 初始化系统
void Init_System(void)
{
// 关闭LED灯
HC138_Init( 4 );
P0 = 0xff
// 关闭蜂鸣器和继电器
HC138_Init( 5 );
P0 = 0xaf; // 1010 1111
HC138_Init( 0 ); // 关闭通道选择
}
// 单个数码管点亮
void SMG_Light( unsigned char pos , unsigned char dat )
{
HC138_Init( 6 );
P0 = 0x01 << pos; // 某个数码管处于准备阶段
HC138_Init( 7 );
P0 = dat; // 显示数值
}
// 数码管显示
void SMG_Show( unsigned char num )
{
SMG_Light( 0 , 0xff );
Delay_tms( 10 );
SMG_Light( 1 , 0xff );
Delay_tms( 10 );
SMG_Light( 2 , 0xff );
Delay_tms( 10 );
SMG_Light( 3 , 0xff );
Delay_tms( 10 );
SMG_Light( 4 , 0xff );
Delay_tms( 10 );
SMG_Light( 5 , 0xff );
Delay_tms( 10 );
SMG_Light( 6 , SMG_Duanma[ num / 10 ] );
Delay_tms( 10 );
SMG_Light( 7 , SMG_Duanma[ num % 10 ] );
Delay_tms( 10 );
}
// 按键扫描
void Key_Scan(void)
{
// 第一行
R1 = 0;
R2 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if( C1 == 0 ) // S7
{
while( C1 == 0 );
Key_Num = 7;
}
else if( C2 == 0 ) // S11
{
while( C2 == 0 );
Key_Num = 11;
}
else if( C3 == 0 ) // S15
{
while( C3 == 0 );
Key_Num = 15;
}
else if( C4 == 0 ) // S19
{
while( C4 == 0 );
Key_Num = 19;
}
// 第二行
R2 = 0;
R1 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if( C1 == 0 ) // S6
{
while( C1 == 0 );
Key_Num = 6;
}
else if( C2 == 0 ) // S10
{
while( C2 == 0 );
Key_Num = 10;
}
else if( C3 == 0 ) // S14
{
while( C3 == 0 );
Key_Num = 14;
}
else if( C4 == 0 ) // S18
{
while( C4 == 0 );
Key_Num = 18;
}
// 第三行
R3 = 0;
R2 = R1 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if( C1 == 0 ) // S5
{
while( C1 == 0 );
Key_Num = 5;
}
else if( C2 == 0 ) // S9
{
while( C2 == 0 );
Key_Num = 9;
}
else if( C3 == 0 ) // S13
{
while( C3 == 0 );
Key_Num = 13;
}
else if( C4 == 0 ) // S17
{
while( C4 == 0 );
Key_Num = 17;
}
// 第四行
R4 = 0;
R2 = R3 = R1 = 1;
C1 = C2 = C3 = C4 = 1;
if( C1 == 0 ) // S4
{
while( C1 == 0 );
Key_Num = 4;
}
else if( C2 == 0 ) // S8
{
while( C2 == 0 );
Key_Num = 8;
}
else if( C3 == 0 ) // S12
{
while( C3 == 0 );
Key_Num = 12;
}
else if( C4 == 0 ) // S16
{
while( C4 == 0 );
Key_Num = 16;
}
}
int main(void)
{
Init_System(); // 初始化系统
while(1)
{
Key_Scan(); // 按键扫描
SMG_Show( Key_Num ); // 数码管显示
}
}
五、运行图片

到了这里,关于蓝桥杯单片机开发及应用-基础模块06-矩阵键盘的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!