51单片机STC89C52RC——4.1 矩阵按键(数码管显示按键值)

目录

目录

目的

一,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博客

六,效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值