STM32CubeMX实现4X5矩阵按键(HAL库实现)

为了实现计算器键盘,需要使用4X5矩阵按键,因此,我在4X4矩阵键盘上重新设计了一个4X5矩阵按键。原理图如下:

原理描述:

4X5矩阵按键,可以设置4个引脚为输出,5个引脚为输入模式,4个引脚依次设置为低电平,5个引脚依次扫描读取电平变化,如果为低电平,则表示按键按下,这样就可以通过坐标算出按键的位置(二维矩阵坐标)。

设计的PCB板如下:

3D效果图如下:

实物图:

接线表如下:

矩阵按键

STM32

R5

PA15

上拉输入模式

R4

PB12

上拉输入模式

R3

PB13

上拉输入模式

R2

PB14

上拉输入模式

R1

PB15

上拉输入模式

C1

PA8

推挽输出模式

C2

PA9

推挽输出模式

C3

PA10

推挽输出模式

C4

PA11

推挽输出模式

-

PA2

USART2_TX

-

PA3

USART2_RX

功能:

        将按键的信息在串口2显示,和博客原理一致:

4X4矩阵按键实现,博客地址:

STM32CubeMX实现矩阵按键(HAL库实现)_使用hal库使用矩阵按键-CSDN博客

CubeMX配置过程如下:

注意:这里需要注意一下,如果用STM32F103C8T6最小系统USB供电,PA12口不能作为普通的输入输出口,因为该口与USB相接,导致电平混乱。

代码如下:

按键扫描:

/* USER CODE BEGIN 0 */
uint16_t keyScan(void)
{
	HAL_GPIO_WritePin(GPIOA, COL1_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, COL2_Pin|COL3_Pin|COL4_Pin, GPIO_PIN_SET);
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 20;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 4;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 8\r\n", 8, 0XFFFF);
		return 8;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 12\r\n", 9, 0XFFFF);
		return 12;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 16\r\n", 9, 0XFFFF);
		return 16;
	}
	HAL_GPIO_WritePin(GPIOA, COL2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, COL1_Pin|COL3_Pin|COL4_Pin, GPIO_PIN_SET);
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 19;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 3\r\n", 9, 0XFFFF);
		return 3;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 7\r\n", 9, 0XFFFF);
		return 7;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 11\r\n", 9, 0XFFFF);
		return 11;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 15\r\n", 9, 0XFFFF);
		return 15;
	}
	HAL_GPIO_WritePin(GPIOA, COL3_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, COL1_Pin|COL2_Pin|COL4_Pin, GPIO_PIN_SET);
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 18;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 2\r\n", 9, 0XFFFF);
		return 2;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 6\r\n", 9, 0XFFFF);
		return 6;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 10\r\n", 9, 0XFFFF);
		return 10;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 14\r\n", 9, 0XFFFF);
		return 14;
	}
	HAL_GPIO_WritePin(GPIOA, COL4_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, COL1_Pin|COL2_Pin|COL3_Pin, GPIO_PIN_SET);
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 17;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 1\r\n", 9, 0XFFFF);
		return 1;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 5\r\n", 9, 0XFFFF);
		return 5;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 9\r\n", 9, 0XFFFF);
		return 9;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 13\r\n", 9, 0XFFFF);
		return 13;
	}
	return 0;
}
/* USER CODE END 0 */

主函数:

int main(void)
{
  /* USER CODE BEGIN 1 */
	uint16_t keyValue = 0;		//	按键返回的键值
	uint8_t str[10] = "";
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_GPIO_WritePin(GPIOA, COL1_Pin|COL2_Pin|COL3_Pin|COL4_Pin, GPIO_PIN_SET);	//	初始化高电平
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if((keyValue = keyScan()) !=0 )
		{
			sprintf((char*)str,"key: %d\r\n",keyValue);
			HAL_UART_Transmit(&huart2, str, strlen((char*)str), 0XFFFF);
		}
  }
  /* USER CODE END 3 */
}

实现效果,如下:

代码并不是很复杂。

代码如下:

STM32CubeMX实现4X5矩阵按键(HAL库实现)资源-CSDN文库

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MPS---MPQ86960芯片layout设计总结

MPQ86960 是一款内置功率 MOSFET 和栅极驱动的单片半桥。它可以在宽输入电压 (VIN) 范围内实现高达 50A 的连续输出电流 (IOUT),通过集成MOSFET 和驱动可优化死区时间 (DT) 并降低寄生电感,从而实现高效率。 MPQ86960 兼容三态输出控制器,另…

Ubantu22.04 通过FlatPak安装微信

Ubuntu22.04 下使用Flatpak稳定安装微信! 国际惯例,废话不多说,先上效果图。为啥使用Flatpak,因为Wechat官方只在FlatPak发布了最新的版本。之前使用了Wine以及Dock安装Wechat,效果都不是很理想,bug很多。所以使用了FlatPak。 Fl…

GRPC使用之ProtoBuf

1. 入门指导 1. 基本定义 Protocol Buffers提供一种跨语言的结构化数据的序列化能力,类似于JSON,不过更小、更快,除此以外它还能用用接口定义(IDL interface define language),通protoc编译Protocol Buffer定义文件,…

【Spring Cloud】微服务的简单搭建

文章目录 🍃前言🎄开发环境安装🌳服务拆分的原则🚩单一职责原则🚩服务自治🚩单向依赖 🍀搭建案例介绍🌴数据准备🎋工程搭建🚩构建父子工程🎈创建父…

关闭vue3中脑瘫的ESLine

在创建vue3的时候脑子一抽选了ESLine,然后这傻卵子ESLine老是给我报错 博主用的idea开发前端 ,纯粹是用不惯vscode 关闭idea中的ESLine,这个只是取消红色波浪线, 界面中的显示 第二步,在vue.config.js中添加 lintOnSave: false 到这里就ok了,其他的我试过了一点用没有

Google Java Style Guide深度解读:打造优雅的代码艺术

在软件工程的世界里,代码不仅仅是实现功能的工具,它也是团队之间沟通的桥梁,是软件质量和可维护性的直接反映。Google Java Style Guide作为一套广受认可的编码规范,不仅定义了代码的书写规则,更深刻地影响着Java开发者…

绿色金融相关数据合集(2007-2024年 具体看数据类型)

数据类型: 1.绿色债券数据:2014-2023 2.绿色信贷相关数据:2007-2022 3.全国各省及地级市绿色金融指数:1990-2022 4.碳排放权交易明细数据:2013-2024 5.绿色金融试点DID数据:2010-2023 数据来源&#…

python操作SQLite3数据库进行增删改查

python操作SQLite3数据库进行增删改查 1、创建SQLite3数据库 可以通过Navicat图形化软件来创建: 2、创建表 利用Navicat图形化软件来创建: 存储在 SQLite 数据库中的每个值(或是由数据库引擎所操作的值)都有一个以下的存储类型: NULL. 值是空值。 INTEGER. 值是有符…

Linux—网络设置

目录 一、ifconfig——查看网络配置 1、查看网络接口信息 1.1、查看所有网络接口 1.2、查看具体的网络接口 2、修改网络配置 3、添加网络接口 4、禁用/激活网卡 二、hostname——查看主机名称 1、查看主机名称 2、临时修改主机名称 3、永久修改主机名称 4、查看本…

【python】pyqt5大学生成绩信息管理系统-图形界面(源码+报告)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

基于支持向量机、孤立森林和LSTM自编码器的机械状态异常检测(MATLAB R2021B)

异常检测通常是根据已有的观测数据建立正常行为模型,从而将不同机制下产生的远离正常行为的数据划分为异常类,进而实现对异常状态的检测。常用的异常检测方法主要有:统计方法、信息度量方法、谱映射方法、聚类方法、近邻方法和分类方法等。 …

飞书 API 2-4:如何使用 API 将数据写入数据表

一、引入 上一篇创建好数据表之后,接下来就是写入数据和对数据的处理。 本文主要探讨数据的插入、更新和删除操作。所有的操作都是基于上一篇(飞书 API 2-4)创建的数据表进行操作。上面最终的数据表只有 2 个字段:序号和邮箱。序…

巴图自动化PN转Modbus RTU协议转换网关模块快速配置

工业领域中常用的通讯协议有:Profinet协议,Modbus协议,ModbusTCP协议,Profibus协议,Profibus DP协议,EtherCAT协议,EtherNET协议,CAN,CanOpen等,它们在自动化…

kubeadm快速部署k8s集群

文章目录 Kubernetes简介1、k8s集群环境2、linux实验环境初始化【所有节点】3、安装docker容器引擎【所有节点】4、安装cri-dockerd【所有节点】5、安装 kubeadm、kubelet、kubectl【所有节点】6、部署 k8s master 节点【master节点】7、加入k8s Node 节点【node节点】8、部署容…

【链表】【双指针】1、合并两个有序链表+2、分隔链表+3、删除链表的倒数第N个结点+4、链表的中间结点+5、合并两个链表

3道中等2道简单 数组和字符串打算告一段落,正好最近做的几乎都是双指针,所以今天做链表! 1、合并两个有序链表(难度:简单) 该题对应力扣网址 AC代码 思路简单 /*** Definition for singly-linked list.…

昇思25天学习打卡营第12天|简单的深度学习ResNet50图像分类 - 构建ResNet50网络

ResNet主要解决深度卷积网络在深度加深时候的“退化”问题。在一般的卷积神经网络中,增大网络深度后带来的第一个问题就是梯度消失、爆炸,这个问题Szegedy提出BN层后被顺利解决。BN层能对各层的输出做归一化,这样梯度在反向层层传递后仍能保持…

P1392 取数

传送门&#xff1a;取数 如若你看完题解后&#xff0c;仍有问题&#xff0c;欢迎评论 首先说一下 我首先想到的思路 &#xff08; 20%通过率 &#xff09;&#xff1a;通过dfs , 将所有的情况放入priority_queue中&#xff08;greater<int>&#xff09;&#xff0c;维持…

计算两种人像之间的相似度

通过调研&#xff0c;目前存在几种能够计算两个人脸相似度的方法&#xff1a; 1.使用结构相似性计算人脸之间的相似度 结构准确性&#xff1a;生成的图片是否保留了原图足够多细节。 &#xff08;1&#xff09;结构准确性衡量指标&#xff1a;SSIM/MMSSIM SSIM&#xff08;结构…

纯前端低代码开发脚手架 - daelui/molecule

daelui/molecule低代码开发脚手架&#xff1a;分子组件开发、预览、打包 页面代码示例、大屏代码示例预览 可开发页面组件 可开发大屏组件 项目git地址&#xff1a;https://gitee.com/daelui/molecule 在线预览&#xff1a;http://www.daelui.com/daelui/molecule/app/index.…

STM32第十六课:WiFi模块的配置及应用

文章目录 需求一、WiFi模块概要二、配置流程1.配置通信串口&#xff0c;引脚和中断2.AT指令3.发送逻辑编写 三、需求实现代码总结 需求 完成WiFi模块的配置,使其最终能和服务器相互发送消息。 一、WiFi模块概要 本次使用的WiFi模块为ESP-12F模块&#xff08;安信可&#xf…