目录
目的
按下矩阵按键,数码管显示按下的键值
一,STC单片机模块
二,矩阵按键模块
2.1 针脚定义
2.2 矩阵按键位置
2.3 如何理解按键按下后针脚的高低电平
2.3.1 错误理解1
初学者:按键按下后就到通,针脚导通就是高电平(我最开始是这么理解的)。这种理解不是不正确,只是没结合实际电路分析
我们按照初学者的逻辑来分析下
假如S1按下
P17和P13 此时是相同的电平。那么他们是同时处于高电平还是低电平呢?我们在程序中怎么去判定呢是S1按下的呢?这里要明白 系统上电后针脚P10-P17都是低电平。那么P13和P17及时接通了也还是都处于低电平。
2.3.2 错误理解2
既然要有电位差,那直接先给P17-P14都给高电平,然后判定P10-P13上的电平。或者先给P10-P14高电平,然后判断P17-P14 的电平。我们看电路图
我们来判定P17 上的电平。如果是高电平,S1按下 P17是高电平,S2按下P17也是高电平,S3按下P17也是高电平,S4按下P17还是高电平。实际上我们不能确定按下的那个按键。
2.3.3 正确判定按下的是那个按键的逻辑
我们只能依次给P10-P13(纵排)或者P17-P14(横排)高电平,为什么要依次给高电平?不能同时给高电平?上面两个错误理解已经说了。
假如按键按下了S10,我们来分析。
我们先给P10 高电平,如下图,然后分别检测P17-P14的电平状态。发现P17-P14全是低电平。
在把P10设置为低电平,P11设置为高电平,如下图。然后分别检测P17-P14的电平状态。发现P17-P14任然全是低电平。
在把P11设置为低电平,P12设置为高电平,如下图。然后分别检测P17-P14的电平状态。发现P15是高电平,P14、P16、P17是低电平。
再把P12设置为低电平,P13设置为高电平,如下图。然后分别检测P17-P14的电平状态。发现P17-P14任然全是低电平。
所以这里只能依次扫描
2.3.4 判定按键按下的依次扫描程序代码如下
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;
P1=0xFF;
P1_3=0;
if(P1_7==0){Delay_ms(20);while(P1_7==0);Delay_ms(20);KeyNumber=1;}
if(P1_6==0){Delay_ms(20);while(P1_6==0);Delay_ms(20);KeyNumber=5;}
if(P1_5==0){Delay_ms(20);while(P1_5==0);Delay_ms(20);KeyNumber=9;}
if(P1_4==0){Delay_ms(20);while(P1_4==0);Delay_ms(20);KeyNumber=13;}
P1=0xFF;
P1_2=0;
if(P1_7==0){Delay_ms(20);while(P1_7==0);Delay_ms(20);KeyNumber=2;}
if(P1_6==0){Delay_ms(20);while(P1_6==0);Delay_ms(20);KeyNumber=6;}
if(P1_5==0){Delay_ms(20);while(P1_5==0);Delay_ms(20);KeyNumber=10;}
if(P1_4==0){Delay_ms(20);while(P1_4==0);Delay_ms(20);KeyNumber=14;}
P1=0xFF;
P1_1=0;
if(P1_7==0){Delay_ms(20);while(P1_7==0);Delay_ms(20);KeyNumber=3;}
if(P1_6==0){Delay_ms(20);while(P1_6==0);Delay_ms(20);KeyNumber=7;}
if(P1_5==0){Delay_ms(20);while(P1_5==0);Delay_ms(20);KeyNumber=11;}
if(P1_4==0){Delay_ms(20);while(P1_4==0);Delay_ms(20);KeyNumber=15;}
P1=0xFF;
P1_0=0;
if(P1_7==0){Delay_ms(20);while(P1_7==0);Delay_ms(20);KeyNumber=4;}
if(P1_6==0){Delay_ms(20);while(P1_6==0);Delay_ms(20);KeyNumber=8;}
if(P1_5==0){Delay_ms(20);while(P1_5==0);Delay_ms(20);KeyNumber=12;}
if(P1_4==0){Delay_ms(20);while(P1_4==0);Delay_ms(20);KeyNumber=16;}
return KeyNumber;
}
三,创建Keil项目
详细参考:51单片机STC89C52RC——创建Keil项目-CSDN博客
四,代码
main.c
#include <REGX52.H>
#include "ShuMaGuan.h"
#include "Delay.h"
#include "MatrixKey.h"
/**
* 函 数:主函数
* 参 数:无
* 返 回 值:无
*/
void main()
{
unsigned int KeyNum=0,ShowKeyNum=0;
while(1)
{
KeyNum=MatrixKey(); //获取按下的键
if(KeyNum){
ShowKeyNum=KeyNum; //将按下的键赋值给显示值
}
ShuMaGuan_ShowNumber(ShowKeyNum);//数码管显示
}
}
ShuMaGuan.c
#include <REGX52.H>
#include "Delay.h"
/*数码管可显示值*/
unsigned int ShuMaGuan_EnableDisplayValue[]={
0,1,2,3,4,
5,6,7,8,9,
'A','C','E','F','H',
'J','L','P','q','U',
'.','b','d','u','-'};
/*数码管显示值对应的HEX*/
unsigned int ShuMaGuan_EnableDisplayHEX[]={
0x3F,0x06,0x5B,0x4F,0x66,
0x6D,0x7D,0x07,0x7F,0x6F,
0x77,0x39,0x79,0x71,0x76,
0x1E,0x38,0x73,0x67,0x3E,
0x80,0x7C,0x5E,0x1C,0x40};
/**
* 函 数:获取可显值对应的HEX
* 参 数:数码管显示的值
* 返 回 值:数码管显示时对应的HEX
*/
unsigned int ShuMaGuan_GetEnableDisplayValueOfHEX(unsigned int Value)
{
unsigned int index=0;
for(index=0;index<24;index++)//遍历显示值的数组
{
if(ShuMaGuan_EnableDisplayValue[index]==Value)//找到对应值的索引
{
break;
}
}
return ShuMaGuan_EnableDisplayHEX[index];
}
/**
* 函 数:设置数码管要显示的值
* 参 数:显示值
* 返 回 值:无
*/
void ShuMaGuan_SetDisplayValue(unsigned int Value)
{
/*将要显示的值 复制给P0*/
P0=ShuMaGuan_GetEnableDisplayValueOfHEX(Value);
}
/**
* 函 数:设置要显示的数码管 位置
* 参 数:位置(左起1-8)
* 返 回 值:无
*/
void ShuMaGuan_SetDisplayLocation(unsigned int Location)
{
switch(Location) //位码输出
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
}
/**
* 函 数:数码管展示
* 参 数:Location 显示的位置,Value 显示的值
* 返 回 值:无
*/
void ShuMaGuan_Display(unsigned int Location,unsigned int Value)
{
/*显示位置*/
ShuMaGuan_SetDisplayLocation(Location);
/*显示值*/
ShuMaGuan_SetDisplayValue(Value);
/*等待显示稳定*/
Delay_10us(10);
/*消除阴影*/
P0=0x00;
}
/**
* 函 数:显示一个数字
* 参 数:整形数字 -32767到32767
* 返 回 值:无
*/
void ShuMaGuan_ShowNumber(int Num)
{
int Location=8,Temp,Flag=1;
if(Num<0)
{
Num=-Num;//再将负数转为正数
Flag=-1;//表示需要显示‘负号-’
}
Temp=Num%10;
while(Location>0&&Num>0)
{
ShuMaGuan_Display(Location,Temp);
Location--;
Num=Num/10;
Temp=Num%10;
}
if(Flag==-1&&Location>0)
{
ShuMaGuan_Display(Location,'-');//负数显示负号
}
}
ShuMaGuan.h
#ifndef __SHUMAGUAN_H_
#defind __SHUMAGUAN_H_
void ShuMaGuan_Display(unsigned int Location,unsigned int Value);
void ShuMaGuan_ShowNumber(int Num);
#endif
Delay.c
/**
* 函 数:延时函数 毫秒
* 参 数:ms 延时多少毫秒
* 返 回 值:无
*/
void Delay_ms(int ms) //@12.000MHz
{
unsigned char data i, j;
while(ms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
/**
* 函 数:延时函数 毫秒
* 参 数:ms 延时多少毫秒
* 返 回 值:无
*/
void Delay_us(int ms) //@12.000MHz
{
unsigned char data i, j;
while(ms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
/**
* 函 数:延时函数 10微秒
* 参 数:无
* 返 回 值:无
*/
void Delay_10us(int _10us) //@11.0592MHz
{
unsigned char data i;
while(_10us--)
{
i = 2;
while (--i);
}
}
Delay.h
#ifndef __DELAY_H_
#defind __DELAY_H_
void Delay_ms(int ms);
void Delay_10us(int _10us);
#endif
MatrixKey.c
#include <REGX52.H>
#include "Delay.h"
/**
* 函 数:矩阵键盘读取按键键码
* 参 数:无
* 返 回 值:KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
*/
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;
P1=0xFF;
P1_3=0;
if(P1_7==0){Delay_ms(20);while(P1_7==0);Delay_ms(20);KeyNumber=1;}
if(P1_6==0){Delay_ms(20);while(P1_6==0);Delay_ms(20);KeyNumber=5;}
if(P1_5==0){Delay_ms(20);while(P1_5==0);Delay_ms(20);KeyNumber=9;}
if(P1_4==0){Delay_ms(20);while(P1_4==0);Delay_ms(20);KeyNumber=13;}
P1=0xFF;
P1_2=0;
if(P1_7==0){Delay_ms(20);while(P1_7==0);Delay_ms(20);KeyNumber=2;}
if(P1_6==0){Delay_ms(20);while(P1_6==0);Delay_ms(20);KeyNumber=6;}
if(P1_5==0){Delay_ms(20);while(P1_5==0);Delay_ms(20);KeyNumber=10;}
if(P1_4==0){Delay_ms(20);while(P1_4==0);Delay_ms(20);KeyNumber=14;}
P1=0xFF;
P1_1=0;
if(P1_7==0){Delay_ms(20);while(P1_7==0);Delay_ms(20);KeyNumber=3;}
if(P1_6==0){Delay_ms(20);while(P1_6==0);Delay_ms(20);KeyNumber=7;}
if(P1_5==0){Delay_ms(20);while(P1_5==0);Delay_ms(20);KeyNumber=11;}
if(P1_4==0){Delay_ms(20);while(P1_4==0);Delay_ms(20);KeyNumber=15;}
P1=0xFF;
P1_0=0;
if(P1_7==0){Delay_ms(20);while(P1_7==0);Delay_ms(20);KeyNumber=4;}
if(P1_6==0){Delay_ms(20);while(P1_6==0);Delay_ms(20);KeyNumber=8;}
if(P1_5==0){Delay_ms(20);while(P1_5==0);Delay_ms(20);KeyNumber=12;}
if(P1_4==0){Delay_ms(20);while(P1_4==0);Delay_ms(20);KeyNumber=16;}
return KeyNumber;
}
MatrixKey.h
#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__
unsigned char MatrixKey();
#endif
五,代码编译、下载到51单片机
代码编译请参考
《51单片机STC89C52RC——代码编译-CSDN博客》
代码下载请参考
《51单片机STC89C52RC——STCAI-ISP代码下载-CSDN博客》