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博客》
六,效果

相关文章:
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 判定按键按下的依次扫描程…...
解决双击bootstrap.bat没有生成b2.exe文件
双击bootstrap.bat但是并没有没有生成b2.exe文件,会报如下错误: "cl" 不是内部或外部命令,也不是可运行的程序 或批处理文件。D:\cppsoft\boost_1_85_0\tools\build\src\engine>dir *.exe 驱动器 D 中的卷是 Data 卷的序列号是…...
AI穿戴设备是未来手机的终结者?中国AI商业化的未来预测
AI技术的发展正处于商业化应用的关键阶段,而中国在互联网时代已凭借商业化应用逆袭。AI算法大模型虽强大,但真正普惠民众需与设备深度结合。穿戴式智能设备就成为了新战场,AI算法与穿戴设备结合能释放更大工作效率。私人助理AI将成趋势&#…...
FPGA+Nvidia Orin NX+AI 异构视频图像处理开发平台在高端医疗和工业检测的应用,支持定制,支持国产化
FPGAGPU 异构架构视频图像处理开发平台,它结合了 AMD Zynq UltraScale MPSoC(FPGA)与 NVIDIA Jetson Orin NX(GPU)的强大功能,能够应用于对图像精准度和实时性有着严苛要求的行业领域。 Zynq UltraScale MP…...
2000-2023年各省名义GDP、实际GDP、GDP平减指数数据(含原始数据+计算过程+计算结果)(以2000年为基期)
2000-2023年各省名义GDP、实际GDP、GDP平减指数数据(含原始数据计算过程计算结果)(以2000年为基期) 1、时间:2000-2023年 2、范围:31省 3、指标:名义GDP、国内生产总值指数、实际GDP、GDP平减…...
python学习—字典(Dictionary)
系列文章目录 python学习—列表和元组 python学习—循环语句-控制流 python学习—合并TXT文本文件 python学习—统计嵌套文件夹内的文件数量并建立索引表格 python学习—查找指定目录下的指定类型文件 python学习—年会不能停,游戏抽签抽奖 python学习—合并多个Ex…...
鸿蒙开发:【组件启动规则(FA模型)】
组件启动规则(FA模型) 启动组件是指一切启动或连接应用组件的行为: 启动PageAbility、ServiceAbility,如使用startAbility()等相关接口。连接ServiceAbility、DataAbility,如使用connectAbility()、acquireDataAbili…...
网络编程5----初识http
1.1 请求和响应的格式 http协议和前边学过的传输层、网络层协议不同,它是“一问一答”形式的,所以要分为请求和响应两部分看待,同时,请求和响应的格式是不同的,我们来具体介绍一下。 1.1.1 请求 在介绍请求之前&…...
“用友审批+民生付款”,YonSuite让企业发薪更准时
随着现代企业经营模式的不断创新和市场竞争的加剧,企业薪资管理和发放的效率、准确性和及时性已成为企业管理的重要一环。然而,在实际操作中,许多企业面临着薪资管理复杂、发放流程繁琐、数据不准确等难点和痛点。为了解决这些问题࿰…...
EtherCAT扫盲,都是知识点
1. 什么是EtherCAT EtherCAT,全称Ethernet for Control Automation Technology,字面意思就是用于控制自动化技术的以太网。它是一种基于以太网的实时工业通信协议,简单说,就是让机器们通过网线互相聊天的高级方式。 EtherCAT 是最…...
开发中遇到的错误 - @SpringBootTest 注解爆红
我在使用 SpringBootTest 注解的时候爆红了,ait 回车也导不了包,后面发现是因为没有加依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId>…...
数据仓库的实际应用示例-广告投放平台为例
数据仓库的数据分层通常包括以下几层: ODS层:存放原始数据,如日志数据和结构化数据。DWD层:进行数据清洗、脱敏、维度退化和格式转换。DWS层:用于宽表聚合值和主题加工。ADS层:面向业务定制的应用数据层。…...
Beyond VL了解学习
Beyond VL:多模态处理的前沿 在今天的数据驱动时代,我们经常需要处理和分析多种类型的数据,例如文本、图像、视频和音频。Beyond VL 是一个先进的多模态模型,专为处理这些多种数据而设计。它能够同时处理多种模态的数据ÿ…...
AI音乐革命:创意产业的新篇章
随着科技的飞速发展,人工智能(AI)在各个领域的应用越来越广泛,特别是在音乐产业中,AI音乐大模型的涌现,正在重新定义音乐创作的边界。最近一个月,随着多个音乐大模型的轮番上线,素人…...
python从入门到精通1:注释
在Python编程中,注释是一种非常重要的工具,它不仅可以帮助我们记录代码的目的、工作方式以及任何需要注意的地方,还可以使代码更具可读性。Python提供了两种主要的注释方式:单行注释和多行注释。下面我们将深入探讨这两种注释方式…...
CountDownLatch(应对并发问题的工具类)
CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作以后,再执行当前线程;比如我们在主线程需要开启2个其他线程,当其他的线程执行完毕以后我们再去执行主线程,针对这 个需求我们就可以使用CountDownLatch来进…...
HarmonyOS开发知识 :扩展修饰器,实现节流、防抖、权限申请
引言 防重复点击,利用装饰器面向切面(AOP)的特性结合闭包,实现节流、防抖和封装权限申请。 节流 节流是忽略操作,在触发事件时,立即执行目标操作,如果在指定的时间区间内再次触发了事件&…...
自然语言NLP的基础处理
NLP基本处理从句子的情感分析、实体与实体直接的关系,句子结构来分析 情感分析 1.句子的情感分析找出句子表达的是正面、负面还是中性的情感。 情感分析的影响因素: 词语顺序:词语的顺序可以影响句子的整体情感。例如,“我喜欢…...
带颜色的3D点云数据发布到ros1中(通过rviz显示)python、C++
ros中发布点云数据xyz以及带颜色的点云数据xyzrgb ros中发布点云数据xyz可以直接用python来做或者C(看个人偏好) ros中发布带颜色的点云数据xyzrgb环境1.新建ROS工作空间2.创建功能包 ros中发布点云数据xyz 可以直接用python来做或者C(看个人偏好) 在这里我们带有颜色的点云数…...
python学习—列表和元组
系列文章目录 python学习—合并TXT文本文件 python学习—统计嵌套文件夹内的文件数量并建立索引表格 python学习—查找指定目录下的指定类型文件 python学习—年会不能停,游戏抽签抽奖 python学习—循环语句-控制流 python学习—合并多个Excel工作簿表格文件 文章目…...
OpenClaw成本优化方案:ollama GLM-4-7-Flash替代OpenAI API实测
OpenClaw成本优化方案:ollama GLM-4-7-Flash替代OpenAI API实测 1. 为什么需要寻找OpenAI API的替代方案 去年我开始在个人项目中使用OpenClaw实现自动化办公流程时,很快被OpenAI API的token消耗速度震惊了。一个简单的"读取邮件附件-解析内容-生…...
【FreeRTOS实战入门】一、从CubeMX到第一个任务:手把手搭建FreeRTOS工程
1. 为什么选择FreeRTOS与CubeMX组合 第一次接触嵌入式实时操作系统时,很多人会纠结选择哪种RTOS。我当年在uC/OS-II和FreeRTOS之间犹豫了很久,最终选择了后者。原因很简单:FreeRTOS不仅完全免费开源,还有STM32CubeMX这个神器加持。…...
FireRed-OCR保姆级教程:一键部署,精准提取表格公式转Markdown
FireRed-OCR保姆级教程:一键部署,精准提取表格公式转Markdown 1. 引言:为什么选择FireRed-OCR? 在日常工作和学习中,我们经常遇到需要从PDF、图片等文档中提取表格、公式等内容的情况。传统OCR工具往往难以准确识别复…...
前端微前端架构:别再把所有功能都放在一个应用里了
前端微前端架构:别再把所有功能都放在一个应用里了 各位前端同行,咱们今天聊聊前端微前端架构。别告诉我你还在把所有功能都放在一个应用里,那感觉就像在一个房间里放了所有家具。 为什么你需要微前端架构 最近看到一个项目,单页应…...
Python多线程性能翻倍实录(GIL禁用+细粒度原子操作配置全指南)
第一章:Python无锁GIL环境下的并发模型概览Python 的全局解释器锁(GIL)长期被视为多线程 CPU 密集型任务的瓶颈。然而,随着 CPython 3.13 的正式引入“实验性无锁 GIL”(--without-pymalloc 配合 --with-gildisabled 构…...
Golang错误处理实战:defer、panic和recover的正确打开方式(附避坑指南)
Golang错误处理实战:defer、panic和recover的正确打开方式(附避坑指南) 在Golang的世界里,错误处理是一门艺术。与传统的try-catch机制不同,Go采用了独特的defer-panic-recover组合拳。这种设计哲学体现了Go语言"…...
面向对象高级三:内部类 枚举 泛型 java.lang包下常用API
一.内部类1.内部类概述 2.成员内部类(实例内部类)(1)成员内部类可以定义类的一切成员(2)当创建对象时不能直接给内部类创建对象而要先创建外部类的对象 然后new成员内部类的对象(3)在…...
7天打造智能助理:OpenClaw+Qwen3-VL:30B飞书开发周计划
7天打造智能助理:OpenClawQwen3-VL:30B飞书开发周计划 1. 为什么选择这个组合? 去年冬天,我偶然在GitHub上发现了OpenClaw这个项目。当时我正在为团队寻找一个既能处理日常办公自动化,又能理解图片内容的智能助手方案。传统的RP…...
测试用例设计-XMind
🚀 一、XMind 用例设计核心思路👉 和传统Excel不同,XMind强调:以“功能模块”为主干 以“用户场景”为分支 以“测试点”为叶子节点👉 本质结构:模块 → 场景 → 用例点 → 具体测试数据/预期📌…...
MySQL迁移到达梦数据库:DMP文件转换的3种方案对比(附性能测试数据)
MySQL到达梦数据库迁移实战:DMP文件转换方案深度评测 在国产化替代浪潮下,越来越多的企业开始将MySQL数据库迁移至达梦等国产数据库平台。作为国产数据库的领军者,达梦DM8在性能、安全性和兼容性方面表现出色,但迁移过程中数据类型…...
