HAL学习笔记-4 通用输入输出GPIO

16 篇文章 47 订阅
16 篇文章 17 订阅


一、GPIO概述

GPIO是通用输入/输出(General Purpose I/O)的简称,主要用于工业现场需要用到数字量输入/输出的场合,例如:

  • 输出功能:继电器,LED,蜂鸣器等的控制
  • 输入功能:传感器状态、高低电平等信息的读取
  • 复用功能:片内外设的对外接口
  • 时序模拟:模拟SPI、I2C和UART等常用接口的时序

基本概念

端口(PORT):独立的外设子模块,包含多个引脚,通过多个硬件寄存器控制引脚
GPIO模块由端口GPIOA、GPIOB、GPIOC等多个独立的子模块构成
**引脚(PIN)😗*对应微控制器的一个管脚,归属于端口,由端口寄存器的对应位控制

一个端口默认包含16个引脚,但是不同型号的STM32微控制器所包含的端口数量及各端口包含的引脚数量各不相同,具体信息可查询芯片的数据手册。

二、GPIO模块的电路结构与功能描述

在这里插入图片描述

工作模式分类

输入模式

根据上拉/下拉电阻的使能情况分为浮空输入、上拉输入、下拉输入三种输入模式。
在这里插入图片描述

输入配置
  1. 输出驱动器关闭
  2. 施密特触发器打开,获取引脚状态
  3. 通过PUPDR寄存器值使能上拉/下拉电阻,选择输入模式
  4. 输入数据寄存器每隔一个AHB时钟周期对引脚上的数据进行一次采样
  5. 通过读取输入数据寄存器的值获取引脚电平状态

输出模式

根据两个MOS管的导通情况分为推挽输出和开漏输出。
在这里插入图片描述

输出配置
  1. 输出驱动器打开
    开漏模式:输出寄存器中的“0”可激活N-MOS,从而输出寄存器中 的“1” 会使端口保持高阻态(P-MOS始终不激活)
    推挽模式:输出寄存器中的“0”激活N-MOS,“1”激活P-MOS。
  2. 施密特触发器输入被打开
  3. 通过PUPDR寄存器值使能上拉/下拉电阻
  4. 输入数据寄存器每隔一个AHB时钟周期对引脚上的数据进行一次采样
  5. 通过读取输入数据寄存器的值获取引脚电平状态
  6. 对输出数据寄存器的读访问可获取最后写入值
推挽输出

在这里插入图片描述
P-MOS管的小圆圈表示还要进行一次反相,因此当同相端输出“1”时,反相后,P-MOS管的门级输入低电平,P-MOS管导通。

  • 当输出数据寄存器对应位为“1”时,同相端输出“1”,反相端输出“0”.此时P-MOS管导通,N-MOS管截止,引脚输出高电平
  • 当输出数据寄存器对应位为“0”时,同相端输出“0”,反相端输出“1”.此时P-MOS管截止,N-MOS管导通,引脚输出低电平
开漏输出

开漏输出时,P-MOS管关闭,只有N-MOS管工作,此时只能输出低电平。要输出高电平必须外加上拉电阻,主要用于I2C总线。
在这里插入图片描述

  • 当输出数据寄存器对应位为“1”时,反相端输出“0”。此时N-MOS管截止,由外加的上拉电阻提供高电平
  • 当输出数据寄存器对应位为“0”时,反相端输出“1”。此时N-MOS管导通,引脚输出低电平

模拟模式

单纯的引脚模拟状态或引脚作为片内模拟外设的复用引脚
模拟状态:表示引脚功能选择为模拟模式,但不作为任何片内模拟外设的复用引脚,只是为了减少系统功耗
模拟外设复用引脚:表示引脚作为片内模拟外设(A/D转换模块、D/A转换模块、模拟比较器等)的复用引脚,用于完成相应的功能操作
在这里插入图片描述

模拟配置
  1. 输出驱动器关闭
  2. 施密特触发器输入停用,I/O引脚的每个模拟值的功耗值都为0;输出强制为常量0
  3. 弱上拉/下拉电阻被硬件禁用
  4. 通过读取输入数据寄存器的值为0

复用模式

引脚电平状态由片内外设控制,一般情况下,处于复用模式的引脚的参数可借助CubeMX自动配置。
在这里插入图片描述

复用配置

对 I/O 端口进行编程作为复用功能时:

  1. 可将输出缓冲器配置为推挽或开漏模式
  2. 输出缓冲器由外设信号驱动(发送器使能和数据)
  3. 施密特触发器输入激活
  4. 根据PUPDR寄存器值决定弱上拉/下拉电阻使能状态
  5. 输入数据寄存器每隔一个AHB时钟周期对引脚上的数据进行一次采样
  6. 通过读取输入数据寄存器的值获取引脚电平状态

用法总结

输入模式

  • 浮空输入:按键识别
  • 上拉输入:IO内部上拉电阻输入
  • 下拉输入:IO内部下拉电阻输入

模拟模式

  • 作为片内模拟外设的对外引脚
  • 单纯作为低功耗使用

输出模式

  • 推挽输出:可以输出高/低电平,主要用于连接数字器件,如指示灯和继电器等模块
  • 开漏输出:只能输出低电平,适合于电流型驱动,也可作为电平转换

复用模式

  • 复用推挽:片内外设功能(UART的Tx,Rx;SPI的MOSI,MISO,SCK,SS)
  • 复用开漏:片内外设功能(I2C的SCL,SDA)

三、GPIO模块的常用寄存器介绍

每个端口包含10个寄存器,其中x表示端口号,取值从A开始。分别介绍如下。

GPIO端口模式寄存器(GPIOx_MODER)

偏移地址:0x00
复位值:每款芯片略有差异,具体查阅参考手册
在这里插入图片描述

GPIO端口输出类型寄存器(GPIOx_OTYPER)

偏移地址:0x04
复位值:每款芯片略有差异,具体查阅参考手册
在这里插入图片描述

GPIO端口输出速度寄存器(GPIOx_OSPEEDR)

偏移地址:0x08
复位值:每款芯片略有差异,具体查阅参考手册
速度的划分参考设备数据手册和电源及负载状态,
在这里插入图片描述

GPIO端口上拉/下拉寄存器(GPIOx_PUPDR)

偏移地址:0x0C
复位值:每款芯片略有差异,具体查阅参考手册
在这里插入图片描述

GPIO端口输入数据寄存器(GPIOx_IDR)

偏移地址:0x10
复位值:每款芯片略有差异,具体查阅参考手册
这些位为只读形式,只能在字模式下访问,它们包含相应IO端口的输入值。
在这里插入图片描述

GPIO端口输出数据寄存器(GPIOx_ODR)

偏移地址:0x14
复位值:每款芯片略有差异,具体查阅参考手册
对于原子置位复位,可通过写BSRR寄存器进行设置。
在这里插入图片描述

GPIO端口置位/复位寄存器(GPIOx_BSRR)

偏移地址:0x18
复位值:每款芯片略有差异,具体查阅参考手册
这些位为只写形式,只能在字、半字或字节模式下访问。读取这些位可返回0x0000,如果BR和BS同时写入1,BS优先级高,优先输出高电平。
在这里插入图片描述

四、基于寄存器方式控制GPIO

1.利用指针访问单个寄存器

通过查询芯片的参考手册,可查找到各端口寄存器映射到的地址,根据寄存器起始地址及偏移量可访问指定寄存器。

地址转换方法

  1. 对于C语言的编译器而言,寄存器的地址值只代表一个有符号常数,无法代表地址;
  2. 在C语言中,利用指针类型来存放变量的地址,利用指针类型定义的变量称为指针变量;
  3. 利用强制类型转换可以将常数转为指针变量;
  4. 指针的基类型表示指针所指向变量的类型,它决定了从该地址开始可以访问的地址范围;
  5. 指针的解引用表示从指针所指向的地址中取出存放的数据。
unsigned int *p   //表示定义一个指向无符号整型的指针
p = 0x4002000UL  // 表示为指针变量P赋值,指向地址单元0x40020000
//*p即指针的解引用,表示访问从地址单元0x4002000开始的4个地址单元的内容

寄存器宏定义

#define GPIOA_MODER *(volatile unsigned int *)(0x40020000UL)


寄存器地址值不具备符号特性,寄存器为32位,volatile避免编译器优化

例程开发

1)新建MDK工程
  1. 在合适位置新建STM32_Register文件夹,表示此文件夹中存放的为寄存器操作工程
  2. 打开MDK软件,选择Project菜单新建工程,找到上一步创建的文件夹,创建名为LED的工程
  3. 选择目标MCU
  4. 在工具栏上点开Manager RTE,勾选CMSIS下CORE和DECVICE下Startup组件
2)新建源文件并编写用户代码
  1. 在工程窗口中选择Source Group1文件夹右键单击选择添加新项到该文件夹
  2. 选择C File类型文件,命名为main.c
  3. 将该文件中添加如下代码
    在这里插入图片描述
3)编译下载

首先在工程设置的Debug标签页中,选择仿真器并在仿真器设置中勾选Reset and Run;然后编译下载。

2.利用结构体指针访问寄存器组

实际开发中我们需要访问多个寄存器,通过手册我们可看出,端口寄存器地址是连续的,那么可利用结构体来实现对连续的多个寄存器进行定义。
在这里插入图片描述

寄存器组宏定义

#define GPIOA ((GPIO_TypeDef *)0x40020000UL)


将常数转换为了结构体指针,通过结构体指针加内部成员变量的形式,即可访问硬件寄存器。

 GPIOA->MODER;

芯片头文件

上述结构体方式已经被ST公司以头文件的方式提供,ST公司将STM32微控制器片内所有外设的寄存器都采用上述的方法进行了定义。
用户在使用时,只需包含该头文件,就可以通过外设结构体指针访问外设的相关寄存器。
不同型号微控制器头文件各不相同,如STM32F411系列微控制器的头文件为stm32f411xe.h

例程开发

在这里插入图片描述

四、基于HAL库方式控制GPIO

使用Cube MX建立工程的流程已在HAL库介绍中介绍过,这里直接以GPIO模块为例展开实践。

1. 目标选择

  1. 启动CubeMX软件,选择“ACESS TO MCU SELECTOR”,进入MCU筛选器
  2. 在芯片搜索框中输入要使用的芯片型号系列
  3. 在芯片列表框中双击具体的芯片型号,启动芯片配置

2. 基础配置

1)选择时钟源

根据需要,在RCC选项卡中选择所需时钟源

2)配置调试接口

我们使用的ST-Link调试器,所以在SYS页面的Debug选项中选择Serial Wire

3.引脚分配

单击所要配置的引脚,在下拉选项中选择所要使用的模式,如控制LED,就选择GPIO_Output。可自定义引脚名称,便于识别,提高程序代码可读性。

4.外设配置

在GPIO选项卡中,在出现的引脚清单中,单击要配置的引脚,进行引脚的初始化配置:初始电平,引脚模式,上下拉电阻,频率,用户标签等。

5.时钟配置

  1. 修改时钟源频率
  2. 选择锁相环输入时钟
  3. 选择系统时钟源
  4. 设置HCLK频率,并回车

6.工程配置

设置工程名称和路径,选择IDE;在代码生成选项卡中,根据需要勾选一些选项,一般选择如下
在这里插入图片描述

7.生成工程

最后点击右上角的GENERATE CODE,生成对应工程初始化代码,生成完成后可点击OPEN PROJECT在IDE中打开工程代码

8.程序编写

在MDK软件中

  • main.h文件中对端口和引脚取了别名,即上面步骤中定义的用户标签
  • main.c文件中添加用户代码,代码添加在USER CODE BEGIN 和USER CODE END之间。
    上面生成的GPIO初始化代码在gpio.c中
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = LED_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : PBPin PBPin */
  GPIO_InitStruct.Pin = KEY1_Pin|KEY2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值