一、要求
在CT107D单片机训练平台上,首先将J5处的跳线帽接到1~2引脚,使按键S4~S19组成4*4的矩阵键盘。在扫描按键的过程中,发现有按键触发信号后,待按键松开后,数码管显示相应的数字。按键顺序是:从左至右,从上到下,依次显示0~F。
二、矩阵键盘按键识别方法
矩阵键盘比独立的按键识别要复杂一些。与独立按键不同的是,矩阵键盘的每个按键两个引脚都是连接在单片机的I/O端口,一个作为行信号,另一个作为列信号。
其识别方法是:列线作为输入端,通过电阻接正电源或用程序预设为高电平,并将行线所接的单片机的I/O口作为输出端且预设为低电平。这样,当没有按键按下时,所有列线输入端都是高电平,行线输出是低电平。一旦有按键按下,则列线输入线就会被拉低。这样就可以通过读取输入线的状态就可以得知是否有按键按下并确定是哪个按键按下。
三、硬件电路分析
如图所示是矩阵矩阵键盘与单片机IO口连接硬件电路图。其中矩阵键盘的行线连接在P3.0~P3.3,第一、二列线对应的连接在P4.4和P4.2,第三、四列线对应的连接在P3.5和P3.4。
本次实验中还设计到数码管的使用,数码管硬件电路连接参考:
【蓝桥杯-单片机学习笔记(三)】共阳数码管的静态显示_Backlight__的博客-优快云博客
四、程序
在引脚配置时注意,P4口要自己定义。我使用的头文件reg52.h中没有定义P4,所以在程序中我给P4做了定义,P4口定义后才能使用。
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
sfr P4 = 0xc0; //定义P4口地址
sbit R1 = P3^0; //row-行,定义行
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;
sbit C1 = P4^4; //column-列,定义列
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;
uchar code table[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0xff};//共阳段码表
void delay_ms(uchar xms) //@11.0592MHz
{
uchar i,j;
while(xms)
{
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
xms--;
}
}
void channel_select(uchar n) //要使用数码管,所以需要对译码器的输出通道进行选择
{
switch(n)
{
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 num_display(uchar num) //在数码管上显示字符
{
channel_select(6);
P0 = 0x01; //打开第一个数码管的位选
channel_select(7); //打开数码管的段选
P0 = num; //显示字符
}
void key_scanf()
{
R1 = 0;
R2 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if(C1 == 0)
{
num_display(table[0]);
delay_ms(1000);
}
else if(C2 == 0)
{
num_display(table[1]);
delay_ms(1000);
}
else if(C3 == 0)
{
num_display(table[2]);
delay_ms(1000);
}
else if(C4 == 0)
{
num_display(table[3]);
delay_ms(1000);
}
R2 = 0;
R1 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if(C1 == 0)
{
num_display(table[4]);
delay_ms(1000);
}
else if(C2 == 0)
{
num_display(table[5]);
delay_ms(1000);
}
else if(C3 == 0)
{
num_display(table[6]);
delay_ms(1000);
}
else if(C4 == 0)
{
num_display(table[7]);
delay_ms(1000);
}
R3 = 0;
R1 = R2 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if(C1 == 0)
{
num_display(table[8]);
delay_ms(1000);
}
else if(C2 == 0)
{
num_display(table[9]);
delay_ms(1000);
}
else if(C3 == 0)
{
num_display(table[10]);
delay_ms(1000);
}
else if(C4 == 0)
{
num_display(table[11]);
delay_ms(1000);
}
R4 = 0;
R1 = R3 = R2 = 1;
C1 = C2 = C3 = C4 = 1;
if(C1 == 0)
{
num_display(table[12]);
delay_ms(1000);
}
else if(C2 == 0)
{
num_display(table[13]);
delay_ms(1000);
}
else if(C3 == 0)
{
num_display(table[14]);
delay_ms(1000);
}
else if(C4 == 0)
{
num_display(table[15]);
delay_ms(1000);
}
}
void system_init()
{
channel_select(4);
P0 = 0xff;
}
void main()
{
system_init();
while(1)
{
key_scanf();
}
}