3.门锁_STM32_矩阵按键设备实现

news2024/12/28 3:22:25

概述

需求来源:

门锁肯定是要输入密码,这个门锁提供了两个输入密码的方式:一个是蓝牙输入,一个是按键输入。对于按键输入,采用矩阵按键来实现。矩阵按键是为了模拟触摸屏的按键输入,后续如果项目结束前还有时间就更新为触摸屏按键输入。

矩阵按键开发整体思路:

由于矩阵按键就是GPIO的控制,所以不进行芯片和设备的分层编写,控制写在同一个文件中,最终向应用层提供一个接口。

代码层级关系: 

矩阵按键控制裸机实现

1、矩阵按键控制原理

原理及实物:

本次使用的是4*4的矩阵按键,它一共有8个引脚。其中4个引脚连接行、4个引脚连接列,我们根据读取到的按键是哪一行哪一列,就可以定位出是哪一个按键按下。在这8个引脚中,需要一组为输出,一组为输入。比如:行引脚为输出、列引脚为输入。或者反之。

实物图如下:

测试方法:

有的矩阵键盘它会给你标注哪几个引脚是行,哪几个引脚是列。但这个矩阵键盘没有,但可以知道的是要么是上面四个引脚为行,要么是下面四个引脚为行。所以我们先对这个矩阵键盘的引脚与行列关系进行测试:

  1. 首先任意一端接5v,用万用表测量按下后哪一个按键为高电平,从而可以判断接5v的引脚控制的是哪一行或者哪一列。
  2. 之后再移动一个引脚,以同样的方法测电平。这样可以得到整个矩阵按键的引脚与行列控制关系。

本次使用的矩阵键盘的引脚与行列控制关系如下:

获取按键行列信息的方法:

有了上述的对应关系,我们选择让列引脚进行输出,行引脚进行输入。检测的电平为低电平,即:GPIO输出低电平,输入端检测到低电平为按下。扫描方法如下:

  1. 首先第0列(pin3)进行拉低其余引脚拉高,然后第0~3(pin4~pin7)行进行读取电平,看是谁按下。有按下就记录下行和列的位置。
  2. 之后依次类推,总共进行4次这个操作。
  3. 根据行和列的位置,计算按键的序号。

2、配置STM32的GPIO

矩阵按键引脚与GPIO的对应关系如下:

矩阵按键引脚GPIO
PIN_0(col 0)PB0(output)
PIN_1(col 1)PB1(output)
PIN_2(col 2)PB2(output)
PIN_3(col 3)PB9(output)
PIN_4(row 0)PB5(input)
PIN_5(row 1)PB6(input)
PIN_6(row 2)PB7(input)
PIN_7(row 3)PB8(input)

使用STM32CubeMx对STM32进行GPIO的初始化配置。

注意:最终GPIO读取的有效电平为低电平,因此输入模式下应该配置上拉电阻。

3、编写STM32控制Key文件

创建两个文件matrix_key.c、matrix_key.h。这两个文件主要实现读取按键的功能,向上为应用层提供读取按键接口。

3.1 引脚宏定义

将按键的引脚与GPIO引脚以宏定义的方式进行声明,这方便后续改变矩阵按键的接线。

具体宏定义如下:

//矩阵键盘接线
#define MATRIX_KEY_PORT_0 GPIOB
#define MATRIX_KEY_PIN_0 	GPIO_PIN_0
#define MATRIX_KEY_PORT_1 GPIOB
#define MATRIX_KEY_PIN_1 	GPIO_PIN_1
#define MATRIX_KEY_PORT_2 GPIOB
#define MATRIX_KEY_PIN_2 	GPIO_PIN_2
#define MATRIX_KEY_PORT_3 GPIOB
#define MATRIX_KEY_PIN_3 	GPIO_PIN_9
#define MATRIX_KEY_PORT_4 GPIOB
#define MATRIX_KEY_PIN_4 	GPIO_PIN_5
#define MATRIX_KEY_PORT_5 GPIOB
#define MATRIX_KEY_PIN_5 	GPIO_PIN_6
#define MATRIX_KEY_PORT_6 GPIOB
#define MATRIX_KEY_PIN_6 	GPIO_PIN_7
#define MATRIX_KEY_PORT_7 GPIOB
#define MATRIX_KEY_PIN_7 	GPIO_PIN_8
3.2 Matrix_Key_SetCol()

在前面分析中,是将列依次拉低,总共需要重复4次。因此需要提供一个将指定列设置为低的函数。

具体函数实现如下:

/*
 * Matrix_Key_SetCol:设置当前扫描的列,PIN0对应右起第一列
 * param i:当前扫描的列数
 * @ret  -1--err  0--success
*/
int Matrix_Key_SetCol(int i){
	
	//1.参数有效性判断
	//按键只有0~4列
	if(i < 0 || i > 3){
		printf("col err\r\n");
		return -1;
	}
	//2.设置相应列扫描
	switch(i){
		case 3:
			GPIOB->BRR |= MATRIX_KEY_PIN_0;
			GPIOB->BSRR |= (MATRIX_KEY_PIN_1|MATRIX_KEY_PIN_2|MATRIX_KEY_PIN_3);
			break;
		case 2:
			GPIOB->BRR |= MATRIX_KEY_PIN_1;
			GPIOB->BSRR |= (MATRIX_KEY_PIN_0|MATRIX_KEY_PIN_2|MATRIX_KEY_PIN_3);
			break;
		case 1:
			GPIOB->BRR |= MATRIX_KEY_PIN_2;
			GPIOB->BSRR |= (MATRIX_KEY_PIN_0|MATRIX_KEY_PIN_1|MATRIX_KEY_PIN_3);
			break;
		case 0:
			GPIOB->BRR |= MATRIX_KEY_PIN_3;
			GPIOB->BSRR |= (MATRIX_KEY_PIN_0|MATRIX_KEY_PIN_1|MATRIX_KEY_PIN_2);
			
			break;
	}
	return 0;
}
3.3 Matrix_Key_RowScan()

在前面分析中,读取行是依次获取的,需要提供一个行扫描的函数。

具体函数实现如下:

/*
 * Matrix_Key_RowScan:获取指定行状态,PIN4对应上面第一行
 * param i:当前扫描的行数
 * @ret  0--没有按键按下  other--按下行的序号
*/
int Matrix_Key_RowScan(void){
	
	//依次判断每一行是否有按下
	if(Matrix_Key_isDown(MATRIX_KEY_PORT_4,MATRIX_KEY_PIN_4)){
		return 1;
	}
	if(Matrix_Key_isDown(MATRIX_KEY_PORT_5,MATRIX_KEY_PIN_5)){
		return 2;
	}
	if(Matrix_Key_isDown(MATRIX_KEY_PORT_6,MATRIX_KEY_PIN_6)){
		return 3;
	}
	if(Matrix_Key_isDown(MATRIX_KEY_PORT_7,MATRIX_KEY_PIN_7)){
		return 4;
	}
	return 0;
}
3.4 Matrix_Key_isDown()

与普通按键扫描一样,按键按下的判断需要进行消抖,将消抖单编写一个函数。

具体函数实现如下:

/*
 * Matrix_Key_isDown:判断指定的按键IO是否按下
 * @ret  0--UP  1--DOWN
*/
int Matrix_Key_isDown(GPIO_TypeDef* KEY_Port,uint32_t KEY_Pin){
	
	if(HAL_GPIO_ReadPin(KEY_Port,KEY_Pin) == GPIO_PIN_RESET){
		HAL_Delay(10);
		if(HAL_GPIO_ReadPin(KEY_Port,KEY_Pin) == GPIO_PIN_RESET){
			return 1;
		}
	}
	return 0;
}
3.5 Matrix_Key_Scan()

有了行列扫描函数,就可以进行按键值的判断。对于应用层,我们只需要一个按下按键的序号,其他的并不关心,所以封装一个如下的接口函数。

具体函数实现如下:

/*
 * Matrix_Key_Scan:矩阵按键接口
 * @ret  0--没有按下  other--按键的序号
*/
int Matrix_Key_Scan(){

	int col;
	int row;
	
	//1.扫描是哪一行哪一列产生的按键
	for(col=0;col<4;col++){
		Matrix_Key_SetCol(col);
		row = Matrix_Key_RowScan();
		if(row != 0){
			break;
		}
	}
	if(col == 4){//没扫描到按键
		return 0;
	}
	//2.计算是哪个按键值
	return ((row-1)*4+(col+1));
	
}
3.6 最终接口函数

在测试中,发现接口函数在按键按下时会不停的输出按键序号,我们只想让他输出一次,因此对接口函数进行了又一次的封装。

具体函数实现如下:

/*
 * Matrix_Key_GetDownNum:矩阵按键接口
 * @ret  0--没有按下  other--按键的序号 
*/
int Matrix_Key_GetDownNum(){
	
	int key_down_num = 0;
	int res = 0;
	static int key_up = 1;
	
	key_down_num = Matrix_Key_Scan();
	if(key_down_num != 0){
		if( key_up == 1){
			key_up = 0;
			res = key_down_num;
			//printf("key_down_num = %d\r\n",key_down_num);
		}
	}else{
		key_up = 1;
	}
	return res;
}

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

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

相关文章

关于 QImage原始数据格式与cv::Mat原始数据进行手码数据转换 的解决方法

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/141996117 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

神经网络骨架nn.Module

文章目录 一、认识nn.Module二、nn.Module的基础加1操作 一、认识nn.Module nn.Module 是 PyTorch 中的一个核心类&#xff0c;它是所有神经网络模块的基类。在 PyTorch 中构建模型时&#xff0c;通常会继承这个类来创建自定义的网络结构。nn.Module 提供了一系列用于构建神经…

MyBatis-Plus拦截器接口InnerInterceptor失效?因MyBatis缓存机制而踩的一个深坑

InnerInterceptor 接口是 MyBatis-Plus 提供的一个拦截器接口&#xff0c;用于实现一些常用的 SQL 处理逻辑。例如某个组件运作在多系统的平台上&#xff0c;不同系统需要隔离&#xff0c;于是可以通过这个拦截器接口&#xff0c;给每一条要执行的sql末尾拼接一个AND systemId …

3个恢复方法详解:iPhone手机快速找回备忘录

当我们在工作或者是学习时&#xff0c;总会有一些灵光乍现的好想法&#xff0c;我们通常会将这些想法记录在iPhone手机备忘录中&#xff0c;以便随时查看。但是&#xff0c;如果出现不慎删除备忘录的情况&#xff0c;iPhone该如何找回备忘录呢&#xff1f;不用担心&#xff0c;…

[JAVA基础知识汇总-1] 创建线程的几种方式(含线程池相关)

文章目录 1. 继承Thread类2. 实现Runnable接口3. 实现Callable接口4. 线程池4.1 利用Executors工具类来创建线程池4.2 为什么不建议使用Executors来创建线程池&#xff1f;4.3 ThreadPoolExecutor是线程池的核心实现类&#xff0c;可以利用它来创建线程池4.4 线程池的状态 可以…

数字化转型的关键指南:《数字化专业知识体系》深度剖析应用策略

数字化浪潮下的企业生存法则 随着全球企业加速数字化转型&#xff0c;如何有效应对技术变革带来的挑战和机遇成为各行业关注的焦点。传统的IT管理模式已经无法满足日益复杂的数字化需求&#xff0c;亟需一种新型、综合的知识体系来引导企业迈向成功。《数字化专业知识体系》&a…

【MySQL】MySQL基础

目录 什么是数据库主流数据库基本使用MySQL的安装连接服务器服务器、数据库、表关系使用案例数据逻辑存储 MySQL的架构SQL分类什么是存储引擎 什么是数据库 mysql它是数据库服务的客户端mysqld它是数据库服务的服务器端mysql本质&#xff1a;基于C&#xff08;mysql&#xff09…

【unix高级编程系列】线程

引言 我们知道unix进程中可以有多个线程&#xff0c;进程中的线程可以访问该进程的所有组成部分。并且CPU的调度单元就是线程。这就面临一个问题&#xff1a;当进程中的临界资源需要在多个线程中共享时&#xff0c;如何解决一致性问题&#xff1f; 本文将从线程的概念、线程的…

Bootstrap 字体图标无法显示问题,<i>标签字体图标无法显示问题

bootstrap fileInput 以及 Bootstrap 字体图标无法显示问题。 今天在用 bootstrap fileInput 插件的时候发现图标无法显示&#xff0c;如下&#xff1a; 查看DOM&#xff0c;发现那些图标是<i>标签做的&#xff1a; 网上的方案 方案1 网上很多人说是我们打乱了boots…

dfs序+线段树,CF 838B - Diverging Directions

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 838B - Diverging Directions 二、解题报告 1、思路分析 注意这是一棵有…

正点原子STM32F103+ESP8266+DS18B20+DHT11连接阿里云

文章目录 MQTT协议1. 基础知识2. 报文形式3. 连接报文4. 心跳报文5. 订阅报文5.1. 订阅主题报文SUBSCRIBE5.2. 订阅确认SUBACK5.3. 取消订阅UNSUBSCRIBE5.4. 取消订阅确认UNSUBACK 6. 发布报文6.1. 发布消息PUBLISH6.2. 发布确认PUBACK 7. 阿里云账号创建8. 网络调试助手接入阿…

机器人助力上下料搬运,加速仓库转运自动化

近年来&#xff0c;国内制造业领域掀起了一股智能化改造的浪潮&#xff0c;众多工厂纷纷采纳富唯智能提供的先进物流解决方案&#xff0c;这一举措显著优化了生产流程&#xff0c;实现了生产效率的飞跃式增长。得益于这些成功案例&#xff0c;某信息技术服务企业在工厂智能物流…

如何打造高校实验室教学管理系统?Java SpringBoot助力,MySQL存储优化,2025届必备设计指南

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

每日一题——第八十一题

打印如下图案: #include<stdio.h> int main() {int i, j;char ch A;for (i 1; i < 5; i, ch){for (j 0; j < 5 - i; j){printf(" ");//控制空格输出}for (j 1; j < 2 * i; j)//条件j < 2 * i{printf("%c", ch);//控制字符输出}prin…

❤《实战纪录片 1 》原生开发小程序中遇到的问题和解决方案

《实战纪录片 1 》原生开发小程序中遇到的问题和解决方案 文章目录 《实战纪录片 1 》原生开发小程序中遇到的问题和解决方案1、问题一&#xff1a;原生开发中 request请求中返回 的数据无法 使用this传递给 data{}中怎么办&#xff1f;2、刚登录后如何将token信息保存&#xf…

[网鼎杯 2020 青龙组]bang-快坚持不下去的第五天

ps:安卓的解壳&#xff0c;也就是frida-dexdump一把嗦&#xff0c;其他wp上说用真机成功的几率大一些&#xff0c;我就用的模拟器 详细的看这一篇博客&#xff1a; 安卓模拟器Frida环境搭建 &#xff08;mumuadbfrida&#xff09; 在python中安装frida时多一步 pip install…

【Dash】feffery_antd_componenet 中的 AntdSpace

一、feffery_antd_componenet 中的 AntdSpace feffery_antd_components&#xff08;简称fac&#xff09;中的AntdSpace组件是一个基于Ant Design的Dash第三方组件&#xff0c;它用于在水平或垂直方向上放置多个元素&#xff0c;并提供元素之间的间距。以下是AntdSpace组件的一…

一文说清什么是AI原生(AI Native)应用以及特点

引言&#xff1a;智能新纪元 如今&#xff0c;走在街头&#xff0c;哪儿不被智能科技包围&#xff1f;智能音箱、自动驾驶汽车、聊天机器人......这些都在用不同的方式提升我们的生活体验。然而&#xff0c;究竟什么才能称得上“AI原生应用”呢&#xff1f; 什么是AI原生&…

C++:STL简介

✨ Blog’s 主页: 白乐天_&#xff3e;&#xff56;&#xff3e; &#x1f308; 个人Motto&#xff1a;他强任他强&#xff0c;清风拂山岗&#xff01; &#x1f4ab; 欢迎来到我的学习笔记&#xff01; 一、STL引入 STL&#xff08;Standard template libaray-标准模板库…

最新厦门新能安社招入职Verify测评笔试攻略敬请查收SHL

作为全球知名锂电池供应商——ATL与CATL的合资公司&#xff0c;新能安专注高端锂电池的研究与创新&#xff0c;聚焦储能系统、微型车、智能产品驱动电池等三大领域的研发、生产、销售与服务。 a.测评内容包含演绎推理数字推理两部分&#xff0c;大约用时40分钟左右; b.正式测评…