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博客》

六,效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/355941.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

山东济南比较出名的起名大师的老师,中国最厉害的改名大师颜廷利:短命的小草,年年自损;长寿的大树,万古长青。。。(升命学说)

在中国第一起名大师的老师颜廷利教授的《升命学说》中&#xff0c;通过“净化论”、“和合法则”、“唯悟主义”以及“镜正理念”的阐述&#xff0c;我们得以窥见生命的不同维度。他以自然界中短命的小草与长寿的大树为例&#xff0c;揭示了生命形态的对比与哲理。 小草&#…

PHP和Mysql前后端交互效果实现

一、连接数据库基本函数 mysqli_connect(); 作用&#xff1a;创建数据库连接&#xff0c;打开一个新的mysql的连接。传参顺序&#xff1a;数据库地址、数据库账号、数据库密码 <?phpecho mysqli_connect("localhost",root,root) ?> /*结果&#xff1a;F…

vue技巧(十)全局配置使用(打包后可修改配置文件)

1、背景 vue打包目前主流用的有webpack和vite两种&#xff0c;默认用的webpack。&#xff08;二者的区别大家可以各自上网查&#xff0c;我没用过vite&#xff0c;所以不过多介绍&#xff09;vue通过webpack打包后&#xff0c;源码会被压缩&#xff0c;但一些关键配置可…

网络与协议安全复习 - 电子邮件安全

文章目录 PGP(Pretty Good Privacy)功能 S/MIME(Secure/Multipurpose Internet Mail Extensions)DKIM(Domain Keys Identified Mail) PGP(Pretty Good Privacy) 使用符号&#xff1a; Ks&#xff1a;会话密钥、KRa&#xff1a;A 的私钥、KUa&#xff1a;A 的公钥、EP&#xff…

雷池社区版自动SSL

正常安装雷池&#xff0c;并配置站点&#xff0c;暂时不配置ssl 不使用雷池自带的证书申请。 安装&#xff08;acme.sh&#xff09;&#xff0c;使用域名验证方式生成证书 先安装git yum install git 或者 apt-get install git 安装完成后使用 git clone https://gitee.com/n…

AI通用大模型不及垂直大模型?各有各的好

​​​​​​​AI时代&#xff0c;通用大模型和垂直大模型&#xff0c;两者孰优孰劣&#xff0c;一直众说纷纭。 通用大模型&#xff0c;聚焦基础层&#xff0c;如ChatGPT、百度文心一言&#xff0c;科大讯飞星火大模型等&#xff0c;都归属通用大模型&#xff0c;它们可以解答…

Android开发系列(六)Jetpack Compose之Box

Box是一个用来组合和控制子元素布局的组件。它可以在一个矩形区域内排列一个或多个子元素&#xff0c;并根据所提供的参数来控制它们的位置、大小和样式。 Box的功能类似传统的FrameLayout。 下面通过示例了解Box的使用方法&#xff0c;首先看一个最简单的示例&#xff0c;如下…

如何正确理解和评估品牌价值?

在当今这个品牌林立的商业世界里&#xff0c;我们常常听到企业家们满怀憧憬地谈论品牌梦想。 但究竟是什么驱使这些企业去打造一个品牌&#xff0c;到底是市场的激烈竞争&#xff0c;还是内心的情感寄托&#xff1f;亦或是社会发展的必然趋势&#xff0c;引领我们追求超越产品…

openh264 宏块级码率控制源码分析

openh264 宏块级码率控制函数关系 宏块级核心函数分析 WelsRcMbInitGom函数 功能&#xff1a;openh264 码率控制框架中宏块级码率控制函数&#xff0c;根据是否启用GOM QP来决定如何设置宏块的QP值&#xff0c;以控制编码的质量和比特率。原理过程&#xff1a; 函数参数&…

nginx出现504 Gateway Time-out错误的原因分析及解决

nginx出现504 Gateway Time-out错误的原因分析及解决 1、查看公网带宽是否被打满 2、查看网络是否有波动(可以在nginx上ping后端服务&#xff0c;看是否有丢包情况) 3、查看服务器资源使用情况(cpu、内存、磁盘、网络等) 4、查看nginx日志&#xff0c;具体到哪个服务的哪个…

校园任务平台系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;论坛管理&#xff0c;任务咨询管理&#xff0c;用户管理&#xff0c;基础数据管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;任务资讯公告&#…

如何将办公文档压缩成rar格式文件?

压缩包格式是我们生活工作中常用到的文件格式&#xff0c;那么如何得到一个rar格式的压缩文件&#xff1f;或者说如何将文件压缩成rar格式而不是zip格式呢&#xff1f;今天我们来了解一下如何压缩为rar格式文件。 首先&#xff0c;下载并安装WinRAR&#xff0c;然后用鼠标选择需…

Android找不到so,实际上apk中有的

解决apk中有.so&#xff0c;实际运行时找不到的问题 排查方向&#xff1a; ①、.so安装位置是否实际存在文件&#xff08;context.getApplicationInfo().nativeLibraryDir&#xff09; ②、当前ARM架构适配配置或者匹配&#xff08;armeabi-v7a, arm64-v8a, x86_64, ...&#…

拒绝零散碎片, 一文理清MySQL的各种锁

系列文章目录 学习MySQL先有全局观&#xff0c;细说其发展历程及特点 Mysql常用操作&#xff0c;谈谈排序与分页 拒绝零散碎片&#xff0c; 一文理清MySQL的各种锁&#xff08;收藏向&#xff09; 系列文章目录一、MySQL的锁指什么二、排他与共享三、全局锁&#xff08;Global…

Java网络爬虫入门

文章目录 1、导入依赖2、CrawlerFirst 1、导入依赖 <dependencies><!-- HttpClient --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version></…

【ARMv8/ARMv9 硬件加速系列 3.3 -- SVE LD2D 和 ST2D 使用介绍】

文章目录 SVE 多向量操作LD2D(加载)LD2D 操作说明LD2D 使用举例ST2D(存储)ST2D 使用举例ST2D 存储示例代码ld2d 和 st2d 小结SVE 多向量操作 在ARMv8/9的SVE (Scalable Vector Extension) 指令集中,st2d和ld2d指令用于向量化的存储和加载操作,具体地,它们允许同时对两个…

英文字母表

目录 一 设计原型 二 后台源码 一 设计原型 二 后台源码 namespace 英文字母表 {public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){foreach (var item in panel1.Controls){if (item ! null)…

代理网络基础设施 101:增强安全性、速度和可扩展性

编辑代理网络在现代网络架构中发挥着重要作用&#xff0c;充当管理和重新路由数据流的中介。它们处理的数据可以是各种类型&#xff0c;包括搜索查询和潜在的敏感客户信息&#xff0c;这凸显了它们在数据安全方面的作用。 然而&#xff0c;代理的好处不仅限于安全性。它们为用…

java:Multiple Bounds--类型变量(TypeVariable)定义的高级用法--<A extends ClassAIfAIfB >

做Java开发工作好多年了。今天偶然翻到 java.lang.TypeVariable的源码&#xff0c;好奇为什么 TypeVariable.getBounds()返回类型是个数组。 一般不都是<T extends Number> 这样用码&#xff1f;T难道还能extends多个类型&#xff1f; 同问&#xff1a;不应该是extend,为…

Java基础 - 练习(五)根据今天日期获取一周内的日期(基姆拉尔森公式)

基姆拉尔森计算公式用于计算一周内的日期。比如给你年月日&#xff0c;从而计算今天是星期几。 基姆拉尔森公式 Week (d2*m3*(m1)/5yy/4-y/100y/4001) mod 7&#xff0c; 3<m<14Week的取值范围是0 ~ 6&#xff0c;其中0代表星期日&#xff0c;1 ~ 6分别代表星期一到星期…