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

ops/2024/11/23 18:02:43/

更多单片机学习笔记
单片机学习笔记 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.ppmy.cn/ops/136104.html

相关文章

华为IPD流程管理体系L1至L5最佳实践-解读

该文档主要介绍了华为IPD流程管理体系&#xff0c;包括流程体系架构、流程框架实施方法、各业务流程框架示例以及相关案例等内容&#xff0c;旨在帮助企业建立高效、规范的流程管理体系&#xff0c;实现业务的持续优化和发展。具体内容如下&#xff1a; 1. 华为流程体系概述 -…

BY组态-低代码web可视化组件

简介 BY组态是集实时数据展示、动态交互等一体的全功能可视化平台。帮助物联网、工业互联网、电力能源、水利工程、智慧农业、智慧医疗、智慧城市等场景快速实现数字孪生、大屏可视化、Web组态、SCADA等解决方案。具有实时监控、多样、变化、动态交互、高效、可扩展、支持自动…

创建HTTPS网站

每天&#xff0c;我们都会听到网络上发生身份盗窃和数据侵权的案例&#xff0c;这导致用户对自己访问的网站更加怀疑。他们开始更加了解自己将个人信息放在哪里以及信任哪些类型的网站。了解如何使网站使用HTTPS变得比以往任何时候都更加重要。 解读缩略词&#xff1a;HTTP与HT…

从0开始机器学习--Day29--K-means算法以及PCA降维作业

题目1&#xff1a;计算聚类中心点并对图像进行重构 代码&#xff1a; import numpy as np import scipy.io as sio import matplotlib.pyplot as plt from skimage import iodef find_data_type(X, centers):idx []# 聚类中心和样本点不再变化后每个样本点的的类for i in ra…

瀚海微SD NAND之SD 协议(34)1.8V信号的时序

固定数据窗口输出时序(SDR12、SDR25、SDR50) 固定数据窗口插卡输出时序如下图所示&#xff0c;SDR12、SDR25、SDR50的输出时序 有效窗口由输出延迟(topy)的最小值和最大值指定。 无论温度和电压如何变化&#xff0c;与SDCLK同步的有效数据窗口都是可用的。 输出有效窗口由t…

2025 - 科研神器 - 批量处理 PDF、SVG、PNG 和 JPG 文件,将它们转换为彩色 TIFF 文件,并保存到指定的 tiff 文件夹中

2025 - 科研神器 - 批量处理 PDF、SVG、PNG 和 JPG 文件&#xff0c;将它们转换为彩色 TIFF 文件&#xff0c;并保存到指定的 tiff 文件夹中 Created on 2024-11-22author: wangyang(<itwangyanggmail.comL>) 批量处理 PDF、SVG、PNG 和 JPG 文件&#xff0c;将它们转换为…

gmac phy id 读取

因为bitfile问题导致 读取phy id失败log与正常log对比 在get_phy_id这个接口中加log即可

简单理解下基于 Redisson 库的分布式锁机制

目录 简单理解下基于 Redisson 库的分布式锁机制代码流程&#xff1a;方法的调用&#xff1a;具体锁的实现&#xff1a;riderBalance 方法&#xff1a;tryLock 方法&#xff08;重载&#xff09;&#xff1a;tryLock 方法&#xff08;核心实现&#xff09;&#xff1a; 简单理解…