STM32:GPIO输入输出

文章目录

  • 1、GPIO介绍
    • 1.1 GPIO的基本结构
    • 1.1 GPIO的位结构
  • 2、 GPIO工作模式
  • 3、GPIO标准外设库接口函数
    • 3.1 RCC接口函数
    • 3.2 GPIO接口函数
      • 3.2.1 GPIO的读取函数
      • 3.2.1 GPIO的写入函数
  • 4、GPIO的初始化

1、GPIO介绍

GPIO(General Purpose Input Output)通用输入输出口,也就是我们平时所说的I/O口

  • 可配置为8种输入输出模式。
  • 引脚电平:0v~3v,部分引脚可容忍为5v。
  • 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等。
  • 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接受数据等。

1.1 GPIO的基本结构

在这里插入图片描述
在STM32中,所有的GPIO都是挂载在APB2外设总线上的;其中GPIO所有的外设名称都是按照GPIOA、GPIOB、GPIOC等等这样来命名的。

每个GPIO外设总共有16个引脚,编号是0~15;例如GPIOA的第0号引脚,我们一般将其称之为PA0。

在每个GPIO模块内,主要包含了寄存器和驱动器。寄存器就是一段特殊的存储器,内核可以通过APB2总线对寄存器进行读写,这样来完成输出电平和读取电平的功能。

寄存器的每一位对应一个引脚,其中输出寄存器写1,对应的引脚就会输出高电平;写0,就输出低电平。输入寄存器读取为1,就证明对应的端口目前是高电平;读取为0,就是低电平。

STM32是32位的单片机,所有STM32内部寄存器都是32位的,但这个端口只有16位,因此这个寄存器只有低16位对应有端口,而高16位是没有被用到的。

驱动器主要是用来增加信号的驱动能力,寄存器只负责存储数据,若要进行点灯的操作,还是需要驱动器来负责增大驱动能力的。

1.1 GPIO的位结构

在这里插入图片描述
最右边的I/O引脚,接了两个保护二极管来对输入电压限幅。

上面的二极管VDD-3.3V,下面二极管接VSS-0V:

  • 如果输入电压比3.3V还要高,那上方这个二极管就会导通。
  • 输入电压产生的电流就会直接流入VDD而不会流入内部电路,这样就可以避免过高的电压对内部这些电路产生伤害。
  • 如果输入电压比0V还要低,这个电压是相对于VSS的电压,所以是可以有负电压的,这是下方的二极管就会导通,电流会从VSS直接流到I/O出去,而不会从内部电路汲取电流,也可以保护内部电路。
  • 如果输入电压在0~3.3V之间,那两个二极管均不会导通。

左上方一个上拉电阻,一个下拉电阻

  • 目的是为了提供一个默认的输入电平,因为对应一个数字的端口,输入的不是高电平就是低电平,如果输入引脚什么都不接,那到底是算高电平还是低电平。
  • 实际情况是,如果输入引脚啥都不接,这时输入就会处于一种浮空的状态,引脚的输入电平极易受外界干扰而改变。
  • 为了避免引脚悬空导致的输入数据不确定,我们就需要在这里加上上拉或者下拉电阻了。
  • 此时,如果接入上拉电阻,当引脚悬空时,还有上拉电阻来保证引脚的高电平,所以上拉输入又可以称作是默认为高电平的输入模式。

上拉电阻至VDD,下拉电阻至VSS,这个开关是可以通过程序进行配置的:

  • 如果上边断开,下边开关关闭,为下拉模式,反之为上拉模式。
  • 如果两个都断开,就是浮空输入模式

施密特触发器:

  • 他的作用是对输入电压进行整形。
  • 如果输入电压大于某一阈值,输出就会瞬间升为高电平。
  • 如果输入电压小于某一阈值,输出就会瞬间降为低电平。

输入数据寄存器:

  • 用程序读取输入数据寄存器对应某一位的数据,就可以知道端口的输入电平。

上面还有两路线路,这些就是连接到片上外设的一些端口:

  • 模拟输入:连接到ADC上的,因为ADC需要接受模拟量,所以这根线是接到施密特触发器前面的。
  • 复用功能输入:这个是连接到其他需要读取端口的外设上的,比如串口的输入引脚等,这根线接收的是数字量,所以在施密特触发器后面。

2、 GPIO工作模式

通过配置GPIO的端口配置寄存器,端口可以配置位以下8种输入输出模式:

(1)浮空输入

引脚内部既不接上拉电阻也不接下拉电阻,直接经施密特触发器输入I/O引脚的信号。可以读取到引脚电平,若引脚悬空,则电平不确定。

(2)上拉输入(Input Pull-up)

引脚内部连接上拉电阻,通过开关连接到电源VDD,可读取引脚电平,引脚悬空默认为高电平。

(3)下拉输入(Input Pull-down)
与上拉输入模式相反,内部连接下拉电阻,引脚悬空默认为低电平。

(4)模拟输入

GPIO无效,引脚直接接入内部ADC,实现对外部信号的采集。

(5)开漏输出(Open-Drain,OD)

可输出引脚电平,高电平为高阻态,低电平接Vss。

(6)推挽输出(Push-Pull,PP)

可输出引脚电平,高电平接VDD,低电平接Vss。

(7)复用开漏输出(AF-OD)

由片上外设控制,高电平为高阻态,低电平接Vss。

(8)复用推挽输出(AF-PP)

由片上外设控制,高电平为接VDD,低电平接Vss。

3、GPIO标准外设库接口函数

3.1 RCC接口函数

在这里插入图片描述

我们可以在Library文件中找到rcc.h这个文件,其中里面我们最常用到的就是红框内的3个函数:

	RCC APB外设时钟控制、RCC APB2外设时钟控制、RCC APB1外设时钟控制

其中上面常用的3个函数的操作方法都是一样的,第一个参数选择外设,第二个参数选择使能或失能。

3.2 GPIO接口函数

在这里插入图片描述

上图就是GPIO的全部库函数,其中红色方框内的函数用来实现读写GPIO口的功能,基本上常用的就是上面蓝色方框内的函数。

1.GPIO_DeInit,调用这个函数后,所指定的GPIO外设就会被复位。

2.GPIO_AFIODeInit,也是一样,可以复位AFIO外设。

3.GPIO_Init,用结构体的参数来初始化GPIO口。我们需要先定义一个结构体变量,然后再给结构体赋值,最后调用这个函数,这个函数内部就会自动读取结构体的值,然后自动把外设的各个参数配置好。这种Init函数在STM32中基本所有的外设都有,一般我们初始化外设都是使用这个Init函数来完成的。

4.GPIO_StructInit,这个函数可以把结构体变量赋一个默认值。

3.2.1 GPIO的读取函数

1.uint8_t GPIO_ReadInputDataBit,用来读取输入寄存器的某一个端口的输入值,参数是GPIOx和GPIO_Pin,用来指定某一个端口,返回值是uint8_t,代表这个端口的高低电平。

2.uint16_t GPIO_ReadInputData,读取整个输入寄存器,参数只有一个GPIOx,用来指定外设,返回值是uint16_t,一个16位的数据,每一位代表一个端口值。

3.uint8_t GPIO_ReadOutputDataBit,读取输出寄存器的某一个位,因此他并不是用来读取端口的输入数据的,一般用于输出模式下,用来查询字节输出的是什么。

4uint16_t GPIO_ReadOutputData,用来读取整个输出寄存器。

总结来说:若想读取GPIO口的话,需要用到ReadIput的这两个函数;若在输出模式下,想要看一下现在输出了什么,才需要用到ReadOutput这两个函数。

3.2.1 GPIO的写入函数

1.GPIO_SetBits,可以把指定的端口设置为高电平。

2.GPIO_ResetBits,可以把指定的端口设置为低电平。

3.GPIO_WriteBit,这个函数有三个参数,前两个也是指定端口;第三个是BitValue,可以根据第三个参数的值来设置指定的端口。

4.GPIO_Write,第一个参数GPIOx选择外设;PortValue,这个函数可以同时对16个端口进行写入操作。

4、GPIO的初始化

操作STM32的GPIO总共需要3个步骤,涉及了RCC和GPIO两个外设:

  • 使用RCC开启GPIO的时钟;
  • 使用GPIO_Init函数初始化GPIO;
  • 使用输入或输出函数控制GPIO口。

当我们需要控制一个LED的亮灭时,我们要先对GPIO端口进行初始化

例如我们需要点亮PA0口的LED,首先新建一个LED.c的工程,用来存放LED驱动程序的主题代码,将我们所需要初始化的函数写入这个工程文件中。

首先我们需要调用的是RCC里面的APB2外设时钟控制函数:
在这里插入图片描述

跳转到定义后查看参数说明,他的第一个参数就应该为RCC_APB2Periph_GPIOA,第二个参数就为ENABLE,这样时钟就开启了。

接着调用GPIO_Init函数,跳转定义查询后可以写出第一个参数为GPIOA,第二个参数是一个结构体,我们先给第二个参数结构体重命名为GPIO_InitStructure,如下所示:

#include "stm32f10x.h"                  // Device header
void LED_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启时钟GPIO_InitTypeDef GPIO_InitStructure;//配置端口模式GPIO_Init(GPIOA,&GPIO_InitStructure);
}

接着我们通过结构体成员操作符“.”来引出结构体成员,如下所示:

GPIO_InitStructure.GPIO_Mode = ;
GPIO_InitStructure.GPIO_Pin = ;
GPIO_InitStructure.GPIO_Speed = ;

接着再配置其中所需要的参数,最后的初始化代码如下:

#include "stm32f10x.h"                  // Device header
void LED_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启时钟GPIO_InitTypeDef GPIO_InitStructure;//配置端口模式GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);
}

当我们完成GPIO初始化后,写入主函数下载后就可以查看LED灯的变化。

上电后LED处于低电平状态,因此为常亮;若想上电为高电平,即LED熄灭的状态则在初始化函数后添加一个写入函数GPIO_SetBits即可。程序如下:

#include "stm32f10x.h"                  // Device header
void LED_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //开启时钟GPIO_InitTypeDef GPIO_InitStructure;//配置端口模式GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_0);
}

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

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

相关文章

bugfix:若依框架下对某个url接口权限放行,登陆后调用却提示403无权限

引言 在构建基于若依(RuoYi)框架的现代Web应用时,API接口的安全与权限管理是不可或缺的一环。Spring Security作为业界广泛采用的安全框架,为若依提供了强大的权限控制能力。然而,在实际开发过程中,开发者常会遇到登录用户访问特…

synchronized对象锁和类锁

一、什么是对象锁和类锁 顾名思义 对象锁可以锁住同一对象下synchronized修饰的方法,但不会影响其他对象。synchronized修饰普通方法就为对象锁。 类锁static synchronized修饰一个方法,当一个线程在执行该方法时,其他任何线程用任何对象调…

软件测试之 接口测试 Postman使用

接口测试 URL HTTP协议 HTTP 请求部分 HTTP响应部分 Postman使用 界面介绍 这里 注意 如果你无法访问 那么 captchaImage这个打错了,给的资料中是错误的地址 https://kdtx-test.itheima.net/api/captchaImage登录接口 科大天下 第一个接口的登录设置 https://kd…

使用map类型的参数在mapper.xml中使用案例

使用map类型的参数在mapper.xml中使用案例 简介:在常见的开发中,对于参数的装载一般使用map类型方式,这样可以避免创建很多参数实体类,不管嵌套多层的数据参数都可以通过map拿取,对于嵌套多层的map,我们需…

如何在Java中使用异常处理机制

如何在Java中使用异常处理机制在Java中,异常处理是一种在程序运行时识别和响应错误情况的机制。它允许程序在出现异常时继续执行,而不是崩溃。Java异常处理机制的核心概念包括try、catch、finally、throw和throws关键字。下面详细介绍这些概念&#xff0…

已知哈夫曼节点个数,求哈夫曼字符编码数

哈夫曼编码(Huffman Coding)是一种用于无损数据压缩的嫡编码(权编码)算法。 在哈夫曼树中,每个叶子节点都代表一个字符,而节点的权重通常代表字符的频率。在哈夫曼编码中,每个字符都会被赋予一个二进制编码。为了获得这些编码,我…

云渲染动画300帧需要多久呢?瑞云渲染为你揭秘

在动画制作过程中,渲染的速度非常关键。对于一个项目需要渲染的300帧来说,由于硬件的限制,许多公司的设备可能无法快速完成这项任务。此时,借助云渲染服务的强大计算能力,可以显著减少完成时间,从而提速整个…

独孤思维:副业拉新排名第一很牛吗

01 30年河东,30年河西。 我从来不觉得,自己星球拉新第一,或者小报童直播一场卖80份有多牛。 因为比我牛比的,比我拉新多的大佬多了去了。 这个5月,比我潜在爆发的牛人也有很多。 过去的历史成绩,代表当…

【Java基础】初识正则表达式

正则表达式只适用于字符串 匹配matches 实际使用的是String类中定义的方法boolean matches(String regex) public static void piPei( ){String regex"[1][356789]\\d{9}";boolean boo"14838384388".matches(regex);System.out.println(boo); }验证qq号…

QtConcurrent::run操作界面ui的注意事项(2)

前面的“QtConcurrent::run操作界面ui的注意事项(1)”,末尾说了跨线程的问题,引出了Qt千好万好,就是跨线程不好。下面是认为的最简单的解决办法:使用QMetaObject::invokeMethod(相比较信号-槽&a…

构建无服务器数仓(二)Apache DolphinScheduler 集成以及 LOB 粒度资源消费分析

引言 在数据驱动的世界中,企业正在寻求可靠且高性能的解决方案来管理其不断增长的数据需求。本系列博客从一个重视数据安全和合规性的 B2C 金融科技客户的角度来讨论云上云下混合部署的情况下如何利用亚马逊云科技云原生服务、开源社区产品以及第三方工具构建无服务…

18 分页:介绍

目录 简单例子 页表存在哪里 列表中究竟有什么 分页:也很慢 内存追踪 小结 在解决大多数空间管理问题上面,操作系统有两种方法: 第一种就是将空间分割成不同长度的分片,类似于虚拟内存管理中的分段,但是这个方法…

电商平台自动回复脚本制作的流程!

随着电子商务的快速发展,电商平台在日常运营中面临着大量的客户咨询和服务需求,为了提高客户服务效率和质量,许多电商平台采用了自动回复脚本,以快速响应客户问题并提供准确的信息。 本文将详细介绍电商平台自动回复脚本制作的流…

证券期货市场失信记录代表什么?

证券期货市场失信记录是指参与证券期货市场的个人或机构在交易、信息披露、内部控制等方面存在违法违规失信行为的记录。 这些失信行为包括但不限于未履行承诺、拒不履行已达成的纠纷调解协议、未按期兑付本息、未按约定履行担保责任、实施犯罪行为,以及在融资融券…

SpringBoot MybatisPlus 配置动态表名多数据源

需求 业务场景: 日志、交易流水表或者其他数据量大的表,通过日期进行了水平分表,需要通过日期参数,动态的查询数据。 实现思路:利用MybatisPlus的动态表名插件DynamicTableNameInnerInterceptor ,实现Sql执行时&#…

Matten:视频生成与Mamba-Attention

Matten:视频生成与Mamba-Attention 摘要IntroductionRelated WorkMethodology Matten: Video Generation with Mamba-Attention 摘要 在本文中,作者介绍了Matten,一种具有Mamba-Attention架构的尖端潜在扩散模型,用于视频生成。在极小的计算…

带EXCEL附件邮件发送相关代码

1.查看生成的邮件 2.1 非面向对象的方式(demo直接copy即可) ​ REPORT Z12. DATA: IT_DOCUMENT_DATA TYPE SODOCCHGI1,IT_CONTENT_TEXT TYPE STANDARD TABLE OF SOLISTI1 WITH HEADER LINE,IT_PACKING_LIST TYPE TABLE OF SOPCKLSTI1 WITH HEADER LIN…

《他强由他强,清风拂山岗;他横由他横,明月照大江》之三

常见的设计模式 1.策略模式 使用场景 通俗来说,策略模式就像是让你有一个策略的工具箱,在不同的情况下选择最合适的策略来解决问题。 使用场景通常包括以下一些: 多重条件判断语句: 当一个操作包含大量的条件判断语句,并且这些分支具有不同的行为时,可以使用策略模式来…

docker runc升级1.1.12

上传runc-1.1.12制品至中控机 874e970eaa932a97de9888344ae08f24 runc.arm64 将所有节点的runc文件备份 所有节点(包括master+node) vim host [all] 10.1.0.183 ansible_password=Bigdata@Ksyun123 ansible_user=root ansible_port=22 10.1.0.249 ansible_password=Bigdata…

关于 vs2019 c++ 20规范,STL 库提供的标准分配器 alloctor 及其 traits 及涉及分配器交换的全局函数 _Pocs

(1) 我们写 c 代码,使用 STL 库中的模板,很少自己写对象的分配器。用 STL 中的分配器也够用。研究 STL 中的分配器也可以为咱们自己写分配器提供参考。 咱们会遇到这样的场景,例如交换两个容器对象: list a ,b ; a .swap (b) ; 这…