目录
目录
目的
一,STC单片机模块
二,矩阵按键模块
2.1 针脚定义
编辑
2.2 矩阵按键位置
2.3 如何理解按键按下后针脚的高低电平
2.3.1 错误理解1
2.3.2 错误理解2
2.3.3 正确判定按下的是那个按键的逻辑
2.3.4 判定按键按下的依次扫描程序代码如下
三,创建Keil项目
四,代码
五,代码编译、下载到51单片机
六,效果
编辑
目的
按下矩阵按键,数码管显示按下的键值
一,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博客》