注:本文所涉及的图片均来自于B站小蜜蜂老师的视频。
一、题目要求
二、题目分析
1.矩阵键盘的扫描
(1)独立键盘:
将J5处的跳帽接到2~3引脚,使按键S4~S7四个按键的另一端接地从而成为4个独立键盘,此时按下独立按键后,按键与地相连,为低电平,即按下按键为低电平,松开按键为高电平。
(2)矩阵键盘:
将J5处的跳帽接到1~2引脚,对4*4的矩阵键盘进行操作,按下按键后,左右两侧I/O同状态
在上面的矩阵键盘,我们逐行扫描,然后读取列的状态信号。如果R2行输出低电平,那么黄色按键如果有按下动作的话,那读取C3列信号也应该为低电平,而该行上其他没有按下动作的按键的列信号则为高电平。
因此我们可以得到矩阵键盘扫描的基本步骤:使R1(R2/R3/R4)行输出低电平,逐个读取判断列信号,如果都为高电平,则R1(R2/R3/R4)行没有按键按下;如果发现C1(C2/C3/C4)列信号为低电平,那么可以判断R1行的C1(C2/C3/C4)列的按键有按下动作。
2.点亮数码管
数码管的引脚可以划分为段码和公共端两个部分,由图可知段码引脚(a1~dp1)的输入与Y7C有关,公共端引脚(com1~com4)与Y6C有关
三、重要代码详解
1.定义P4内存地址
#include "reg52.h"
sfr P4=0xc0;
该型号单片机无P4 ,需自行定义P4的内存地址
2.定义变量
unsigned char key_num;
定义变量key_num,便于后续从数组中取出相应的要显示的数字
3.矩阵键盘扫描
R1=0;
R2=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
key_num=0;
DisplayKeyNum(SMG_duanma[key_num]);//如果C1没有松开,定义key_num为0
}
else if(C2==0)
{
while(C2==0);
key_num=1;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C3==0)
{
while(C3==0);
key_num=2;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C4==0)
{
while(C4==0);
key_num=3;
DisplayKeyNum(SMG_duanma[key_num]);
}
对R1行进行逐列扫描,此时R1为低电平,R2~R4为高电平,C1~C4初始化为高电平,如果C1为低电平,即按下R1行C1列对应的按键时,数码管显示数组中的第一位的值,在该题即为显示0,其余同理。
四、总体代码展示
#include "reg52.h"
sfr P4=0xc0;//该型号单片机无P4,需自行定义P4的内存地址
sbit R1=P3^0;
sbit R2=P3^1;
sbit R3=P3^2;
sbit R4=P3^3;
sbit C4=P3^4;
sbit C3=P3^5;
sbit C2=P4^2;
sbit C1=P4^4;
unsigned char code SMG_duanma[18]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0x7f};
void SelectHC573(unsigned char channel)
{
switch(channel)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
}
}
void DisplayKeyNum(unsigned char value)
{
SelectHC573(6);
P0=0x01;
SelectHC573(7);
P0=value;
}
unsigned char key_num;
void ScanKeysMulti()
{
R1=0;
R2=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
key_num=0;
DisplayKeyNum(SMG_duanma[key_num]);//如果C1没有松开,定义key_num为0
}
else if(C2==0)
{
while(C2==0);
key_num=1;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C3==0)
{
while(C3==0);
key_num=2;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C4==0)
{
while(C4==0);
key_num=3;
DisplayKeyNum(SMG_duanma[key_num]);
}
R2=0;
R1=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
key_num=4;
DisplayKeyNum(SMG_duanma[key_num]);//如果C1没有松开,定义key_num为0
}
else if(C2==0)
{
while(C2==0);
key_num=5;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C3==0)
{
while(C3==0);
key_num=6;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C4==0)
{
while(C4==0);
key_num=7;
DisplayKeyNum(SMG_duanma[key_num]);
}
R3=0;
R1=R2=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
key_num=8;
DisplayKeyNum(SMG_duanma[key_num]);//如果C1没有松开,定义key_num为0
}
else if(C2==0)
{
while(C2==0);
key_num=9;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C3==0)
{
while(C3==0);
key_num=10;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C4==0)
{
while(C4==0);
key_num=11;
DisplayKeyNum(SMG_duanma[key_num]);
}
R4=0;
R1=R2=R3=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0);
key_num=12;
DisplayKeyNum(SMG_duanma[key_num]);//如果C1没有松开,定义key_num为0
}
else if(C2==0)
{
while(C2==0);
key_num=13;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C3==0)
{
while(C3==0);
key_num=14;
DisplayKeyNum(SMG_duanma[key_num]);
}
else if(C4==0)
{
while(C4==0);
key_num=15;
DisplayKeyNum(SMG_duanma[key_num]);
}
}
void main()
{
while(1)
{
ScanKeysMulti();
}
}