单片机学习笔记 8. 矩阵键盘按键检测

更多单片机学习笔记:
单片机学习笔记 1. 点亮一个LED灯
单片机学习笔记 2. LED灯闪烁
单片机学习笔记 3. LED灯流水灯
单片机学习笔记 4. 蜂鸣器滴~滴~滴~
单片机学习笔记 5. 数码管静态显示
单片机学习笔记 6. 数码管动态显示
单片机学习笔记 7. 独立键盘


目录

0、实现的功能

1、Keil工程

1-1 矩阵键盘识别方法

1-2 swich语句

2、代码实现


0、实现的功能

        4*4矩阵键盘+独立键盘的按键检测,可拓展为四管显示

1、Keil工程

1-1 矩阵键盘识别方法

        主要采用列扫描(1111 0000)和行扫描(0000 1111)的方法。

        列扫描的初始操作是输入P3口为0xF0,当S6被按下时,P34由1会变为0,此时P3口为0xE0;同理,S10被按下时,P3也为0xE0。所以第一列被按下时,P3为1110 0000;第二列被按下时,P3为1101 0000;第三列被按下时,P3为1011 0000;第四列被按下时,P3为0111 0000。
所以P30--P33为行线,P34--P37为列线

        再做行扫描,P3初始为0x0F。当S6被按下时,P30会从1变为0,P3为0000 1110.最后再和列扫描的结果相加:1110 0000 + 0000 1110 = 1110 1110,得到确切的位置(第一列,第一行)

        所以P3的数据中,前四位为哪一列,后四位为哪一行。谁为0就是哪一行列

1-2 swich语句

        主要涉及到c语言中的switch语句

2、代码实现

        显示的按键序号和对应显示数字表如下: 
​       
        只要是涉及到按键的,都要进行软件消抖+松手检测。赋值P3=0xf0进行列扫描,找到是哪一列,KeyValue可以直接为0 1 2 3------赋值P3=0x0f进行行扫描,每行之间相差4,此时KeyValue对应的+4即可
        独立按键扫描的话,赋值P3=0xff,这样就不是列扫描和行扫描了。按下哪个,哪一位就为0,找到对应的显示数字即可

代码实现:

#include <reg52.h>
#include <intrins.h>#define uchar unsigned char
#define uint unsigned intsbit WE = P2^7; //锁存器位选,U8的LE,选择哪个数码管
sbit DU = P2^6; //锁存器段选,U9的LE,控制亮什么数字uchar KeyValue = 6;		//按键显示值//共阴极数码管段选表0-9
uchar code table1[] = {
//0		1	  2		3	  4		5	  6		7	  8	
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 
//9		A	  B		C	  D		E	  F		H	  L
0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x76, 0x38,
//n		u	  -		熄灭
0x37, 0x3e, 0x40, 0x00} ;//延时模块
void delay(uint z)
{uint x;uint y;for(x = z; x > 0; x--)for(y = 114; y > 0; y--);
}void KeyScan()
{//4*4矩阵键盘扫描P3 = 0xf0;		//列扫描初始化if(P3 != 0xf0)		//判断按键是否被按下{delay(10);		//软件消抖10msif(P3 != 0xf0)	//再判断是否真正被按下,有可能是误触{switch(P3)		//判断哪一列被按下{case 0xe0:	KeyValue = 0; break;	//第一列case 0xd0:	KeyValue = 1; break;	//第二列case 0xb0:	KeyValue = 2; break;	//第三列case 0x70:	KeyValue = 3; break;	//第四列}P3 = 0x0f;		//行扫描初始化switch(P3)		//判断哪一行被按下{case 0x0e:	KeyValue = KeyValue; break;	//第一行case 0x0d:	KeyValue = KeyValue + 4; break;	//第二行case 0x0b:	KeyValue = KeyValue + 8; break;	//第三行case 0x07:	KeyValue = KeyValue + 12; break;	//第四行}while(P3 != 0x0f);		//松手检测}}//独立按键扫描P3 = 0xff;if(P3 != 0xff){delay(10);		//软件消抖10msif(P3 != 0xff){switch(P3)		//判断哪一行被按下{case 0xfe:	KeyValue = 16; break;	//S2case 0xfd:	KeyValue = 17; break;	//S3case 0xfb:	KeyValue = 18; break;	//S4case 0xf7:	KeyValue = 19; break;	//S5}while(P3 != 0xff);		//松手检测		}}
}void main()
{//指定第一个数码管,不用放在循环里P0 = 0xff;//清除断码,让位锁存器哪个都不选WE = 1;//位选锁存打开P0 = 0xfe;//选第一个管WE = 0;	//进入锁存while(1){KeyScan();		//20个按键扫描DU = 1;//段选锁存打开P0 = table1[KeyValue];DU = 0;//进入锁存}	
}

        可以结合数码管动态显示,弄点好玩的
 

#include <reg52.h>
#include <intrins.h>#define uchar unsigned char
#define uint unsigned intsbit WE = P2^7; //锁存器位选,U8的LE,选择哪个数码管
sbit DU = P2^6; //锁存器段选,U9的LE,控制亮什么数字uchar KeyValue = 6;		//按键显示值//共阴极数码管段选表0-9
uchar code table1[] = {
//0		1	  2		3	  4		5	  6		7	  8	
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 
//9		A	  B		C	  D		E	  F		H	  K
0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x76, 0x76,
//n		u	  -	  熄灭
0x37, 0x3e, 0x40, 0x00} ;//延时模块
void delay(uint z)
{uint x;uint y;for(x = z; x > 0; x--)for(y = 114; y > 0; y--);
}void KeyScan()
{//4*4矩阵键盘扫描P3 = 0xf0;		//列扫描初始化if(P3 != 0xf0)		//判断按键是否被按下{delay(10);		//软件消抖10msif(P3 != 0xf0)	//再判断是否真正被按下,有可能是误触{switch(P3)		//判断哪一列被按下{case 0xe0:	KeyValue = 0; break;	//第一列case 0xd0:	KeyValue = 1; break;	//第二列case 0xb0:	KeyValue = 2; break;	//第三列case 0x70:	KeyValue = 3; break;	//第四列}P3 = 0x0f;		//行扫描初始化switch(P3)		//判断哪一行被按下{case 0x0e:	KeyValue = KeyValue; break;	//第一行case 0x0d:	KeyValue = KeyValue + 4; break;	//第二行case 0x0b:	KeyValue = KeyValue + 8; break;	//第三行case 0x07:	KeyValue = KeyValue + 12; break;	//第四行}while(P3 != 0x0f);		//松手检测}}//独立按键扫描P3 = 0xff;if(P3 != 0xff){delay(10);		//软件消抖10msif(P3 != 0xff){switch(P3)		//判断哪一行被按下{case 0xfe:	KeyValue = 16; break;	//S2case 0xfd:	KeyValue = 17; break;	//S3case 0xfb:	KeyValue = 18; break;	//S4case 0xf7:	KeyValue = 19; break;	//S5}while(P3 != 0xff);		//松手检测		}}
}void main()
{while(1){KeyScan();		//20个按键扫描P0 = 0xff;//清除断码,让位锁存器哪个都不选WE = 1;//位选锁存打开P0 = 0xfe;//选第一个管WE = 0;	//进入锁存DU = 1;//段选锁存打开P0 = table1[KeyValue];DU = 0;//进入锁存delay(5);P0 = 0xff;//清除断码,让位锁存器哪个都不选WE = 1;//位选锁存打开P0 = 0xfd;//选第2个管WE = 0;	//进入锁存DU = 1;//段选锁存打开P0 = table1[KeyValue+4];DU = 0;//进入锁存delay(5);P0 = 0xff;//清除断码,让位锁存器哪个都不选WE = 1;//位选锁存打开P0 = 0xfb;//选第3个管WE = 0;	//进入锁存DU = 1;//段选锁存打开P0 = table1[KeyValue-3];DU = 0;//进入锁存delay(5);P0 = 0xff;//清除断码,让位锁存器哪个都不选WE = 1;//位选锁存打开P0 = 0xf7;//选第4个管WE = 0;	//进入锁存DU = 1;//段选锁存打开P0 = table1[KeyValue+2];DU = 0;//进入锁存delay(5);}	
}

实物展示: 

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

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

相关文章

【AI日记】24.11.26 聚焦 kaggle 比赛

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 核心工作 1 内容&#xff1a;研究 kaggle 比赛时间&#xff1a;3 小时 核心工作 2 内容&#xff1a;学习 kaggle 比赛 Titanic - Machine Learning from Disaster时间&#xff1a;4 小时备注&#xff1a;这…

排序算法2

排序算法1-CSDN博客 排序算法1中提及的是较为基础(暴力实现&#xff0c;复杂度较高)的排序算法&#xff0c;不适合于数据量较大的场景&#xff0c;比如序列长度达到1e5 接下来以蓝桥另一道题目来理解其它的排序算法 蓝桥3226 蓝桥账户中心 样例 5 1 5 9 3 7 4、快速排序 快速排…

【数据结构实战篇】用C语言实现你的私有队列

&#x1f3dd;️专栏&#xff1a;【数据结构实战篇】 &#x1f305;主页&#xff1a;f狐o狸x 在前面的文章中我们用C语言实现了栈的数据结构&#xff0c;本期内容我们将实现队列的数据结构 一、队列的概念 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端…

macos 14.0 Monoma 修改顶部菜单栏颜色

macos 14.0 设置暗色后顶部菜单栏还维持浅色&#xff0c;与整体不协调。 修改方式如下&#xff1a;

长三角文博会:Adobe国际认证体系推动设计人才评价新标准

2024年11月22日&#xff0c;由上海、江苏、浙江、安徽三省一市党委宣传部共同发起的第五届长三角文化博览会&#xff08;简称“长三角文博会”&#xff09;在上海国家会展中心盛大启幕。长三角文博会自2018年起已成功举办多届&#xff0c;已成为展示区域文化产业发展成果、推动…

安装数据库客户端工具

如果没有勾选下面的&#xff0c;可以运行下面的两个命令 红框为自带数据库 新建数据库 右键运行mysql文件&#xff0c;找到数据库&#xff0c;并刷新

SQL 复杂查询

目录 复杂查询 一、目的和要求 二、实验内容 &#xff08;1&#xff09;查询出所有水果产品的类别及详情。 查询出编号为“00000001”的消费者用户的姓名及其所下订单。&#xff08;分别采用子查询和连接方式实现&#xff09; 查询出每个订单的消费者姓名及联系方式。 在…

Angular面试题汇总系列一

1. 如何理解Angular Signal Angular Signals is a system that granularly tracks how and where your state is used throughout an application, allowing the framework to optimize rendering updates. 什么是信号 信号是一个值的包装器&#xff0c;可以在该值发生变化时…

ES 和Kibana-v2 带用户登录验证

1. 前言 ElasticSearch、可视化操作工具Kibana。如果你是Linux centos系统的话&#xff0c;下面的指令可以一路CV完成服务的部署。 2. 服务搭建 2.1. 部署ElasticSearch 拉取docker镜像 docker pull elasticsearch:7.17.21 创建挂载卷目录 mkdir /**/es-data -p mkdir /**/…

【踩坑】git中文乱码问题

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 背景说明 使用git diff显示中文乱码&#xff0c;如&#xff1a; 修复方法 执行一次&#xff1a; export LESSCHARSETutf-8 如果需要下次登录免输入…

go语言逆向-基础basic

文章目录 go 编译命令 ldflags -w -s的作用和问题使用 file 命令查看文件类型 go 语言逆向参考go ID版本GOROOT和GOPATHGOROOTGOPATHGOROOT和GOPATH的关系示例 go build和 go modpclntab &#xff08;Program Counter Line Table 程序计数器行数映射表&#xff09;Moduledata程…

D2761 适合在个人电脑、便携式音响等系统中作音频限幅用。

概述&#xff1a; D2761是为保护扬声器所设计的音频限幅器&#xff0c;其限幅值可通过外接电阻来调节&#xff0c;适合在个人电脑、便携式音响等系统中作音频限幅用。D2761采用SSOP10、MSOP10、TSSOP14的封装形式封装。 主要特点&#xff1a;  工作电压范围宽&#xff1a;2.7…

【Linux系统】—— 基本指令(四)

【Linux系统】—— 基本指令&#xff08;三&#xff09; 1「find」指令2 「grep」指令2.1 初识「grep」指令2.2 「grep」指令 选项 3 打包压缩基本知识4 「zip / unzip」指令5「tar」命令6 文件互传6.1 Linux 与 Windows 互传6.1.1 Linux向Windows传输6.1.2 Windows向Linux传输…

WordCloud去掉停用词(fit_words+generate)的2种用法

-------------词云图集合------------- WordCloud去掉停用词&#xff08;fit_wordsgenerate&#xff09;的2种用法 通过词频来绘制词云图&#xff08;jiebaWordCloud&#xff09; Python教程95&#xff1a;去掉停用词词频统计jieba.tokenize示例用法 将进酒—李白process_t…

洛谷刷题日记12||图的遍历

反向建边 dfs 按题目来每次考虑每个点可以到达点编号最大的点&#xff0c;不如考虑较大的点可以反向到达哪些点 循环从N到1&#xff0c;则每个点i能访问到的结点的A值都是i 每个点访问一次&#xff0c;这个A值就是最优的&#xff0c;因为之后如果再访问到这个结点那么答案肯…

替代Postman ,17.3K star!

现在&#xff0c;许多人都朝着全栈工程师的方向发展&#xff0c;API 接口的编写和调试已成为许多开发人员必备的技能之一。 工欲善其事&#xff0c;必先利其器。拥有一款优秀的 API 工具对于任何工程师来说都是极为重要的&#xff0c;它能够帮助我们高效地完成各种开发任务。 …

java:拆箱和装箱,缓存池概念简单介绍

1.基本数据类型及其包装类&#xff1a; 举例子&#xff1a; Integer i 10; //装箱int n i; //拆箱 概念&#xff1a; 装箱就是自动将基本数据类型转换为包装器类型&#xff1b; 拆箱就是自动将包装器类型转换为基本数据类型&#xff1b; public class Main {public s…

Node.js的url模块与querystring模块

新书速览|Vue.jsNode.js全栈开发实战-CSDN博客 《Vue.jsNode.js全栈开发实战&#xff08;第2版&#xff09;&#xff08;Web前端技术丛书&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 4.3.1 http模块——创建HTTP服务器、客户端 要使用http模块&#xff0…

【Reinforcement Learning】强化学习下的多级反馈队列(MFQ)算法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

【linux】服务器加装硬盘后如何将其设置为独立硬盘使用

【linux】服务器加装硬盘后如何将其设置为独立硬盘使用 问题描述&#xff1a;本服务器原本使用了两个硬盘作为存储硬盘&#xff0c;同时对这两个硬盘设置了raid1阵列。现在内存不足要进行加载硬盘&#xff0c;新加载的硬盘不设置为raid1&#xff0c;而是将新加装的两个硬盘作为…