学习笔记二.矩阵按键

2023-10-31

#学习笔记二:GPIO的探索与矩阵按键
##1.在配置cubemx时,对gpio的配置有开漏输出和推挽输出两种方式,在这里插入图片描述
###这里有一篇文章(别人的文章)讲的很详细link戳这里跳转

通俗来讲,推挽输出,可以输出高电平,也可以输出低电平。

而开漏输出,输出低电平,在有上拉电阻时,可以正常工作,他可以有多个上拉电阻,并且是与关系。
开漏输出
所谓的推挽输出模式,是根据这两个 MOS 管的工作方式来命名的。在该结构中输入高电平时,经过反向后,上方的 P-MOS 导通,下方的 N-MOS 关闭,对外输出高电平;而在该结构中输入低电平时,经过反向后,N-MOS 管导通,P-MOS 关闭,对外输出低电平。当引脚高低电平切换时,两个管子轮流导通,P 管负责灌电流,N 管负责拉电流,使其负载能力和开关速度都比普通的方式有很大的提高。推挽输出的低电平为 0 伏,高电平为 3.3 伏,具体参考图 7_2,它是推挽输出模式时的等效电路。

在这里插入图片描述
开漏输出
开漏输出模式时,上方的 P-MOS 管完全不工作。如果我们控制输出为 0,低电平,则 P-MOS管关闭,N-MOS 管导通,使输出接地,若控制输出为 1 (它无法直接输出高电平) 时,则 P-MOS管和 N-MOS 管都关闭,所以引脚既不输出高电平,也不输出低电平,为高阻态。为正常使用时必须外部接上拉电阻,参考图 7_3 中等效电路。它具有“线与”特性,也就是说,若有很多个开漏模式引脚连接到一起时,只有当所有引脚都输出高阻态,才由上拉电阻提供高电平,此高电平的电压为外部上拉电阻所接的电源的电压。若其中一个引脚为低电平,那线路就相当于短路接地,使得整条线路都为低电平,0 伏。
在这里插入图片描述
##2.还有就是对IO口拉高还是拉低的问题。
这里有三种情况,pull down(拉低),pull up(拉高),no pull down no pull up(什么也不干),这是对IO口初始状态的设定。后面结合实例进行讲解。
##3.GPIO的函数
1.void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
功能: GPIO初始化
实例:HAL_GPIO_Init(GPIOC,&GPIO_InitStruct);

2.void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);
功能:在函数初始化之后的引脚恢复成默认的状态,即各个寄存器复位时的值

实例:HAL_GPIO_Init(GPIOC, GPIO_PIN_4);

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
功能:读取引脚的电平状态、函数返回值为0或1

实例:HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4);

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
功能:引脚输入高低电平

实例:HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4,0);

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
翻转引脚的电平状态

实例:HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_4); 常用在LED上

HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
功能:锁住引脚电平,比如说一个管脚的当前状态是1,当这个管脚电平变化时保持锁定时的值。

实例:HAL_GPIO_LockPin(GPIOC, GPIO_PIN_4);

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
功能: 外部中断服务函数,清除中断标志位

实例:HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
功能: 中断回调函数,可以理解为中断函数具体要响应的动作。

实例:HAL_GPIO_EXTI_Callback(GPIO_PIN_4);
这些函数可以在下图这个.h文件找到。
在这里插入图片描述
下面贴上一段矩阵按键的扫描,帮助理解。

	HAL_GPIO_WritePin (R1_PORT, R1_PIN, GPIO_PIN_RESET);//在MX中设为output,只有这个函数能改变引脚电平状态,拉低一个,剩下的拉高
	HAL_GPIO_WritePin (R2_PORT, R2_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R3_PORT, R3_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R4_PORT, R4_PIN, GPIO_PIN_SET);
	
	if (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN))) 		//在MX中设置为input型,pull up拉高电平,这个函数读取io口电平,不是高即为按下,就锁定了一行中所在的一列
	{
		while (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN))); 
  return 13;                                          //S13   1
	}
	
	if (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)));   
	return 9;		          //S9 2
	}
	if (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)));   
	return 5;                                                      //S5    3
		
	}
		if (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)));   
		return 1;              //S1       4
		
	}

以这段代码为例(4*4矩阵按键),在cubemx中设置引脚状态为output,用HAL_GPIO_WritePin这个函数改变引脚电平,将第一行四列的引脚电平分别写为低,高高高,接下来扫描行,
if (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)))
{
while (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)));
return 9; //S9 2
}
我们知道按键按下,电路接通,即低电平按键生效,当读到的电平不是高电平,就锁定了行和列。
下面给出完整代码

uint8_t read_key(void)             //矩阵键盘扫描作用函数
{
		
	HAL_GPIO_WritePin (R1_PORT, R1_PIN, GPIO_PIN_RESET);//在MX中设为output,只有这个函数能改变引脚电平状态,拉低一个,剩下的拉高
	HAL_GPIO_WritePin (R2_PORT, R2_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R3_PORT, R3_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R4_PORT, R4_PIN, GPIO_PIN_SET);
	
	if (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN))) 		//在MX中设置为input型,pull up拉高电平,这个函数读取io口电平,不是高即为按下,就锁定了一行中所在的一列
	{
		while (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN))); 
  return 13;                                          //S13   1
	}
	
	if (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)));   
	return 9;		          //S9 2
	}
	if (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)));   
	return 5;                                                      //S5    3
		
	}
		if (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)));   
		return 1;              //S1       4
		
	}
	
	
	HAL_GPIO_WritePin (R1_PORT, R1_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R2_PORT, R2_PIN, GPIO_PIN_RESET);
	HAL_GPIO_WritePin (R3_PORT, R3_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R4_PORT, R4_PIN, GPIO_PIN_SET);
	if (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN)));   //S14    5
		return 14;              
	}
	if (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)));   //S10    6
	return 10; 
	}
	if (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)));    //S6   7
  return 6;  
	}
	if (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)));   //S2   8
return 2; 
		
	}
	
	HAL_GPIO_WritePin (R1_PORT, R1_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R2_PORT, R2_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R3_PORT, R3_PIN, GPIO_PIN_RESET);
	HAL_GPIO_WritePin (R4_PORT, R4_PIN, GPIO_PIN_SET);
	if (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN)));    //S15  9
return 15; 
	}
	if (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)));   //S11  0
return 11;  
	}
	
	if (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)))
	{

		while (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)));   //S7  K1

		return 7;
	}


		if (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)))             //S3   K2
	{


		while (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)));   

		return 3;
	
	}

		HAL_GPIO_WritePin (R1_PORT, R1_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R2_PORT, R2_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R3_PORT, R3_PIN, GPIO_PIN_SET);
	HAL_GPIO_WritePin (R4_PORT, R4_PIN, GPIO_PIN_RESET);
	if (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C1_PORT, C1_PIN)));   //S16  K3
	return 16;
	}
	if (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C2_PORT, C2_PIN)));   //S12  K4

		return 12;
	}
	if (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C3_PORT, C3_PIN)));   //S8     K5
	return 8; 
	}

		if (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)))
	{
		while (!(HAL_GPIO_ReadPin (C4_PORT, C4_PIN)));   //S4      K6

		return 4;
	}
	return 0;
}

下面是.h文件

#ifndef _key_H_
#define _key_H_


#include "main.h"

#define R3_PORT GPIOC
#define R3_PIN GPIO_PIN_10

#define R2_PORT GPIOC
#define R2_PIN GPIO_PIN_9

#define R1_PORT GPIOC
#define R1_PIN GPIO_PIN_8

#define C2_PORT GPIOC
#define C2_PIN GPIO_PIN_12

#define C4_PORT GPIOC
#define C4_PIN GPIO_PIN_7

#define C3_PORT GPIOC
#define C3_PIN GPIO_PIN_6

#define C1_PORT GPIOD
#define C1_PIN GPIO_PIN_2

#define R4_PORT GPIOC
#define R4_PIN GPIO_PIN_11
uint8_t OLED_change(uint8_t SS);
uint8_t  read_key(void);
unsigned int call(unsigned int  high_time);



#endif

欢迎指正

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

学习笔记二.矩阵按键 的相关文章

  • 【Python数据挖掘课程】五.线性回归知识及预测糖尿病实例

    今天主要讲述的内容是关于一元线性回归的知识 Python实现 包括以下内容 1 机器学习常用数据集介绍 2 什么是线性回顾 3 LinearRegression使用方法 4 线性回归判断糖尿病 前文推荐 Python数据挖掘课程 一 安装P
  • Ubuntu 20.04换国内源

    ubuntu默认的源是国处的源 更新下载速度较慢 因此安装好ubuntu20 04之后 将其源更新为国内的源 步骤如下 1 备份原始的源 源的路径 etc apt sources list 备份操作 cd etc apt cp source
  • 【电工技术】期末复习题

    1 电路是为实现人们的某种需求 由 电源 中间环节和负载三部分按一定方式组合起来 使电流流通的整体 2 在使用叠加定理对电路进行分析时 通常要对电源作除源处理 处理方法是将各个理想电压源 短接 将各个理想电流源 开路 3 利用戴维宁定理可以
  • 分析冰蝎三流量特征以及请求包

    1 使用wireshark获取冰蝎流量 首先在冰蝎中执行命令 捕捉流量 流量特征 可以看Accept字段的值 冰蝎脚本的这个请求值比较固定 还可以看user agent这个字段的值 还可以看content的值 2 分析流量 将数据包内容复制
  • 关于有些网站访问不了的问题

    1 网络攻击导致的 先要确定是不是仅仅一个用户的网页打不开 如果是一个用户的网页打不开 非常可能是这个网站的代码有问题 或许是域名没有分析好等原因 如果是大无数用户或全部用户的网页打不开 首要确定是不是攻击以致的 因为攻击有非常多种 例如C

随机推荐

  • 面试了一个00后,绝对能称为是内卷届的天花板

    前言 公司前段缺人 也面了不少测试 结果竟然没有一个合适的 一开始瞄准的就是中级的水准 也没指望来大牛 提供的薪资也不低 面试的人很多 但平均水平很让人失望 令我印象最深的是一个00后测试员 他技术基础方面确实还不错 面试也表现的非常自信
  • rsync服务

    文章目录 rsync简介 rsync特性 rsync的ssh认证协议 rsync命令 rsync简介 rsync是可以实现增量备份的工具 配合任务计划 rsync能实现定时或间隔同步 配合inotify或sersync 可以实现触发式的实时
  • 新一代树莓派 Raspberry Pi 2 性能测试之软件无线电追踪飞机信息

    新一代树莓派 Raspberry Pi 2 性能测试之软件无线电追踪飞机信息 转载自zza1003169 2015年02月28日 于 开源杂志 发表 安装开源软件无线电 GNU Radio 用电视棒追踪飞机轨迹 众所周知 树莓派 Raspb
  • Discuz!教程之当插件、门户或自定义页面设置成首页时手机版访问跳转到forum.php?mobile=yes的问题

    最近由于项目需要 将自定义单页设置为网站首页 测试过程中一直发现手机版无法访问 被强制跳转到了forum php mobile yes页面 仔细查看了一下Discuz 代码 source class discuz discuz applic
  • 免费python课程排行榜-重庆Python培训机构排行榜

    重庆千锋python全栈开发培训 0基础教学 带你玩转python开发 30天直追年薪20万 快速咨询 Python是一种非常强大的计算机语言 你可能已经听说过很多种流行编程语言 比如非常难学的C语言 非常流行的Java语言 适合初学者的B
  • Apollo如何通知/订阅主题topic

    转自 https blog csdn net u012423865 article details 80024870 How to advertise and subscribe a topic 导读 众所周知 Apollo是基于ROS开发
  • Qt5下串口对高频率自发性数据的接收及处理方法

    在项目中需要用Qt5 9采集仪表中的数据 仪表是以200Hz的频率主动向外连续发送数据 发送频率很高 而且主动发送 不需要软件发送一次 再读取一次 而是软件直接读取 这种直接连续读取 有两个关键点 1 如何从接收buffer里面查找出所需的
  • React:refs转发和useImperativeHandle

    具体的使用范例 可以参考官方API Refs转发 本人也是看了官方API以后自己所学习理解领悟的给记录一下 如果有不正确的地方 可以在文章下方的评论区参与评论 然后指正出来 欢迎各位来评论吧 refs是用来绑定元素的 一定要注意 React
  • Excel导出级联下拉功能实现

    效果如下 直接上代码 自己看 工具类 import cn hutool core util ObjectUtil import com alibaba fastjson JSONObject import lombok extern slf
  • Django vue 搭建前后端分离的web 二

    bootstrap的安装和使用 安装 在vue项目下使用npm直接安装即可 由于bootstrap依赖jQuery 所以第一步安装jQuery npm install jquery 检查在package json的dependencies中
  • 【FPGA实现SPI发送】——详解Verilog代码实现

    FPGA实现SPI发送 详解Verilog代码实现 在FPGA开发中 SPI Serial Peripheral Interface 通信协议是常用的一种 它可以实现单片机与外围设备的连接与数据传输 本文将详细讲解如何通过Verilog代码
  • IGBT基本工作原理及IGBT的作用是什么?

    IGBT由栅极 G 发射 E 和集电极 C 三个极控制 如图1 IGBT的开关作用是通过加正向栅极电压形成沟道 给PNP晶体管提供基极电流 使IGBT导通 反之 加反向门极电压消除沟道 切断基极电 使IGBT关断 由图2可知 若在IGBT的
  • SQL语言编程学习系列(一)——数据库及表的创建与管理

    本系列同样是记录代码为主 附带实验内容与要求 可参考代码 SQL编码习惯为小写且习惯性换行 实验的环境和软件为Microsoft SQLServer 2019 实验内容 1 创建教务管理数据库 jwgl 其数据文件和日志文件分别为jwgl
  • conv、deconv、fractional-strided conv

    fractional strided conv 反卷积有时候也被叫做Fractionally Strided Convolution 翻译过来大概意思就是小数步长的卷积 对于步长 s gt 1的卷积 我们可能会想到其对应的反卷积步长 s l
  • React 子组件调用父组件函数时传递参数遇到的问题

    子组件TodoListUI js中render函数返回的渲染页面代码包含的LIst组件 index是循环的下标
  • dhcp协议_DHCP服务器设置

    DHCP服务器 动态主机配置协议是一个局域网的网络协议 指的是由服务器控制一段IP地址范围 客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码 首先 DHCP服务器必须是一台安装有Windows 2000 Server Adva
  • 在导入maven项目时出现maven-compiler-plugin:2.3.2:compile插件的错误

    在导入项目时提示报错 No marketplace entries found to handle maven compiler plugin 2 3 2 compile in Eclipse Please see Help for mor
  • Java注解的学习和自定义一个简单的注解

    学习Java注解的使用 一 Java注解的含义 Java注解 Annotations 是Java 5之后引入的特性 用于为Java代码提供元数据 这些元数据本身不直接影响代码的逻辑功能 但可以被编译器 开发工具或框架用于生成代码 执行测试
  • android面试-垃圾回收算法(久邦涉及到)

    推荐参考深入理解Java虚拟机书籍 垃圾回收算法包括四种 标记清除 标记整理 复制 分代回收算法 1 标记 清除 这是一种最基础的收集算法 Mark Sweep 分为标记 清除两个阶段 标记阶段 先标记出所有需要回收的对象 在标记完成后统一
  • 学习笔记二.矩阵按键

    学习笔记二 GPIO的探索与矩阵按键 1 在配置cubemx时 对gpio的配置有开漏输出和推挽输出两种方式 这里有一篇文章 别人的文章 讲的很详细link戳这里跳转 通俗来讲 推挽输出 可以输出高电平 也可以输出低电平 而开漏输出 输出低