普中51-矩阵按键

2023-09-20 16:59:36

矩阵按键

原理图如下:
在这里插入图片描述

行列扫描

行列扫描法检测时,先送一列为低电平,其余几列全为高电平(此时我们确 定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电 平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列 的,用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平, 这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。 当然我们也可以将行线置低电平,扫描列是否有低电平。从而达到整个键盘的检 测。

线翻转法

线翻转法,就是使所有行线为低电平时,检测所有列线是否有低电平,如果 有,就记录列线值;然后再翻转,使所有列线都为低电平,检测所有行线的值, 由于有按键按下,行线的值也会有变化,记录行线的值。从而就可以检测到全部 按键。

#include "reg52.h"

typedef unsigned int u16;
typedef unsigned char u8;

#define SMG_A_DP_PORT P0  //共阴极接法-高电平有效
#define KEY_MATRIX_PORT P1 


u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,
	0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

/*
	* 延时函数
	*
	*/
void delay_10us(u16 num){
	while(num--);
}

/*
	* 行列扫描法
	*/
u8 key_matrix_ranks_scan(void){
	u8 key_value = 0;//返回值,0表示没有按键按下
	KEY_MATRIX_PORT=0xf7;//先将第一列设为低电平
	if(KEY_MATRIX_PORT!=0xf7){
		delay_10us(1000);//消抖
		switch(KEY_MATRIX_PORT){//保存第一列的键值
			case 0x77: key_value=1;break;
			case 0xb7: key_value=5;break;
			case 0xd7: key_value=9;break;
			case 0xe7: key_value=13;break;
		}
	}
	while(KEY_MATRIX_PORT!=0xf7);//等待按键松开
	
	KEY_MATRIX_PORT=0xfb;//先将第二列设为低电平
	if(KEY_MATRIX_PORT!=0xfb){
		delay_10us(1000);//消抖
		switch(KEY_MATRIX_PORT){//保存第二列的键值
			case 0x7b: key_value=2;break;
			case 0xbb: key_value=6;break;
			case 0xdb: key_value=10;break;
			case 0xeb: key_value=14;break;
		}
	}
	while(KEY_MATRIX_PORT!=0xfb);//等待按键松开
	
	KEY_MATRIX_PORT=0xfd;//先将第三列设为低电平
	if(KEY_MATRIX_PORT!=0xfd){
		delay_10us(1000);//消抖
		switch(KEY_MATRIX_PORT){//保存第三列的键值
			case 0x7d: key_value=3;break;
			case 0xbd: key_value=7;break;
			case 0xdd: key_value=11;break;
			case 0xed: key_value=15;break;
		}
	}
	while(KEY_MATRIX_PORT!=0xfd);//等待按键松开
	
	KEY_MATRIX_PORT=0xfe;//先将第四列设为低电平
	if(KEY_MATRIX_PORT!=0xfe){
		delay_10us(1000);//消抖
		switch(KEY_MATRIX_PORT){//保存第四列的键值
			case 0x7e: key_value=4;break;
			case 0xbe: key_value=8;break;
			case 0xde: key_value=12;break;
			case 0xee: key_value=16;break;
		}
	}
	while(KEY_MATRIX_PORT!=0xfe);//等待按键松开
	
	return key_value;
}

/**
* 函 数 名 : key_matrix_flip_scan
* 函数功能 : 使用线翻转扫描方法,检测矩阵按键是否按下,按下则返回对应键值
* 输 入 : 无
* 输 出 : key_value:1-16,对应 S1-S16 键,
*0:按键未按下
*/

u8 key_matrix_flip_scan(void){
	u8 key_value = 0;
	KEY_MATRIX_PORT = 0x0f;//先给所有行设为低电平
	if(KEY_MATRIX_PORT!=0x0f){//判断按键是否按下
		delay_10us(1000);//消抖
		if(KEY_MATRIX_PORT!=0x0f){//消抖之后再次判断按键是否按下
			//测试列
			KEY_MATRIX_PORT=0x0f;
			switch(KEY_MATRIX_PORT){
				case 0x07: key_value = 1;break;
				case 0x0b: key_value = 2;break;
				case 0x0d: key_value = 3;break;
				case 0x0e: key_value = 4;break;
			}
			//测试行
			KEY_MATRIX_PORT = 0xf0;
			switch(KEY_MATRIX_PORT){
				case 0x70: key_value = key_value;break;//如果是第一行,那么列值就是所在的键位
				case 0xb0: key_value = key_value+4;break;//如果是第二行,那么列数+4就是所在的键位
				case 0x0d: key_value = key_value+8;break;//如果是第三行,那么列数+8就是所在的键位
				case 0x0e: key_value = key_value+12;break;如果是第四行,那么列数+12就是所在的键位
			}
			
			while(KEY_MATRIX_PORT!=0xf0);//等待按键松开
		}
	
	}else{
		//如果没有按下则返回0
		key_value=0;
	}
	return key_value;

}

/* 
* 主函数
*/
void main(){
	u8 key = 0;
	while(1){
		key = key_matrix_ranks_scan();
		if(key!=0){
			P0 = gsmg_code[key-1];//得到的按键值减 1 换算成数组下标对应 0-F 段码
		}
	}

}

本实验核心代码为 key_matrix_ranks_scan 函数和 key_matrix_flip_scan 函数,前者是使用行列式扫描方式实现,而后者是使用线翻转式扫描方式实现, 实现功能一致,二者可选其一。对于初学者,可能行列式扫描方式更易于理解, 因为比较接近独立按键的编程方式。 行列式扫描原理比较简单,与独立式按键操作类似,即给每一列赋值 0,此 时的矩阵按键就被分割成独立按键,然后再判断每一列中的按键按下情况,并返 回对应的键值。如此循环 4 组,就可将 4 列 4 行按键按下键值全部得到。 而线翻转式扫描相对较难理解,不过静下心,在纸上画画,列举几个数据也是比较容易理解的!!!

结束!!!

更多推荐

【云原生持续交付和自动化测试】5.3 持续交付和DevOps实践基础知识

往期回顾:第一章:【云原生概念和技术】第二章:【容器化应用程序设计和开发】第三章:【基于容器的部署、管理和扩展】第四章:【微服务架构设计和实现】第五章:【5.1自动化构建和打包容器镜像】第五章:【5.2自动化测试和集成测试】持续交付和DevOps实践基础知识5.3.1什么是持续交付5.3.2DevOps实践基础知识5.

云原生之深入解析K8S集群内的服务通信

一、传统的服务到服务通信Kubernetes支持服务间通信的3个原生k8s对象分别为:ClusterIPService、DNS和Kube-Proxy:在进入Kubernetes生态系统之前,快速了解一下传统的服务到服务通信:通信是通过IP地址进行的,因此为了让服务A调用服务B,一种方法是为服务B分配一个静态IP地址。现

Qt应用开发(基础篇)——菜单 QMenu

一、前言QMenu类继承于QWidget,它提供了一个菜单样式的小部件,用于菜单栏、上下文菜单和一些弹出式菜单。QMenu菜单的选项是可选的,它可以是一个下拉的菜单,也可以是独立的上下文菜单。下拉菜单通常作用于当用户单击相应的项目或按下指定的快捷键时,使用QMenuBar::addMenu()将菜单插入到菜单栏中,菜单

复杂问题问答

复杂问题问答写在最前面复杂问题问答问答系统分类知识图谱现存问题论文1分类写在最前面希望通过了解,找到目标应用场景的方法具体属于哪一个分支,并初步实现通过阅读文献,找到了另一个研究方向,所以这个就先这样吧hh参考[1]冯钧,李艳,杭婷婷.问答系统中复杂问题分解方法研究综述[J].计算机工程与应用,2022,58(17):

设计模式-中介者模式

每次乘坐高铁出行时,我都会像这样一个问题:这么多列车都可能通过这条轨道,会不会存在冲突的可能呢?同样的,飞机的起飞和降落时对于道路的选择也会有冲突的可能。这些情况都会造成可怕的后果,而阻止这种情况发生的就是机场调度中心。飞机在起飞和降落前都会请求机场调度中心,由机场调度中心来负责协调飞机、地面道路、摆渡车辆等。因此,机

剑指offer(C++)-JZ67:把字符串转换成整数atoi(算法-模拟)

作者:翟天保Steven版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处题目描述:写一个函数StrToInt,实现把字符串转换成整数这个功能。不能使用atoi或者其他类似的库函数。传入的字符串可能有以下部分组成:1.若干空格2.(可选)一个符号字符('+'或'-')3.数字,字母,符号,空格

线性代数的本质(十)——矩阵分解

文章目录矩阵分解LU分解QR分解特征值分解奇异值分解奇异值分解矩阵的基本子空间奇异值分解的性质矩阵的外积展开式矩阵分解矩阵的因式分解是把矩阵表示为多个矩阵的乘积,这种结构更便于理解和计算。LU分解设AAA是m×nm\timesnm×n矩阵,若AAA可以写成乘积A=LUA=LUA=LU其中,LLL为mmm阶下三角方阵,主

CodeArts Check代码检查服务用户声音反馈集锦(4)

作者:gentle_zhou原文链接:CodeArtsCheck代码检查服务用户声音反馈集锦(4)-云社区-华为云CodeArtsCheck(原CodeCheck),是自主研发的代码检查服务。建立在华为30年自动化源代码静态检查技术积累与企业级应用经验的沉淀之上,为用户提供代码风格、通用质量与网络安全风险等丰富的检查能

【智慧工地源码】智慧工地助力数字建造、智慧建造、安全建造、绿色建造

智慧工地围绕建设过程管理,建设项目与智能生产、科学管理建设项目信息生态系统集成在一起,该数据在虚拟现实环境中,将物联网收集的工程信息用于数据挖掘和分析,提供过程趋势预测和专家计划,实现工程建设的智能化管理,提高工程管理信息水平,逐步实现绿色建设和生态建设。一、施工现场智能化管理物联网智慧工地通过手机/PAD自动感应或采

Python爬虫

一、保存数据到Excelfrombs4importBeautifulSoup#网页解析,获取数据importre#正则表达式,进行文字匹配importurllib.request,urllib.error#制定URL,获取网页数据importxlwt#进行excel操作importsqlite3#进行SQLite数据库

【案例+源码】数据可视化之统计绘图-Seaborn全套教程

数据可视化-Seaborn简易入门Matplotlib试着让简单的事情更加简单,困难的事情变得可能,而Seaborn就是让困难的东西更加简单。seaborn是针对统计绘图的,一般来说,seaborn能满足数据分析90%的绘图需求。Seaborn其实是在matplotlib的基础上进行了更高级的API封装,从而使得作图更

热文推荐