文章目录
- 一、GPIO的概念
- 二、STM32中GPIO的基本结构
- 三、GPIO位结构
- 输入部分分析
- 输出部分分析
- GPIO的8种模式
- 四、GPIO相关函数
一、GPIO的概念
-
GPIO(General Purpose Input Output),意为通用输入输出口,在嵌入式系统中,GPIO是一种用于与外部设备进行数字信号交互的接口
-
GPIO 可以通过设置为输入或输出模式来读取或控制外部设备的状态(根据使用场景可配置为8种输入输出模式)
- 输出模式下可控制端口输出高低电平,向外部设备发送数字信号,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
- 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
-
引脚电平:0V~3.3V,部分引脚可容忍5V
0V 就是低电平,在数字信号中用数据 0 表示
3.3V 就是高电平,在数字信号中用数据 1 表示
二、STM32中GPIO的基本结构
【说明】
-
在STM32中,所有的GPIO都是挂载在APB2外设总线上的
-
每个GPIO外设有16个引脚,编号从0到15
GPIOA的第0号引脚一般把它称作PA0,以此类推,一直到PA15(GPIOB引脚也采用一样的命名方式)
-
在每个GPIO模块内,主要包含了寄存器和驱动器
-
寄存器
寄存器就是一段特殊的存储器,内核可以通过APB2总线对寄存器读写来实现输出电平和读取电平的功能
寄存器的每一位就对应一个引脚,其中输出寄存器写1,对应的引脚就会输出高电平,写0就会输出低电平(由于STM32是32位的单片机,所以STM32内部的寄存器都是32位的,但是每个GPIO的端口只有16位,所以寄存器只有低16位有对应端口,高16位是没有用到的)
-
驱动器
驱动器用于增加信号的驱动能力(驱动器可以提供更强的电流或电压),寄存器只负责存储数据,如果要进行点灯这样的操作就需要驱动器增加驱动能力
-
三、GPIO位结构
GPIO位结构是指GPIO中每一位的具体电路结构
整体结构可以分为两个部分:输入部分和输出部分
输入部分分析
-
I/O 引脚
在 I/O 引脚处连接了两个保护二极管,用于对输入电压进行限幅
上面的二极管接 V D D V_{DD} VDD —— 3.3V,下面的二极管接 V S S V_{SS} VSS —— 0V
如果输入电压高于 3.3V ,上方的二极管导通,输入电压产生的电流会直接流入 V D D V_{DD} VDD 而不会流入内部电路,从而避免过高电压对内部电路产生伤害
如果输入电压低于 0V(相对于 V S S V_{SS} VSS 的电压),下方的二极管导通,电流会从 V S S V_{SS} VSS 直接流出,从而避免从内部电路汲取电流
如果输入电压在 0 ~ 3.3V 之间,那么两个二极管均不会导通
-
上拉电阻 & 下拉电阻
上拉电阻连接至 V D D V_{DD} VDD ,下拉电阻连接至 V S S V_{SS} VSS ,这个开关可以通过程序进行配置
上拉和下拉目的是给输入提供一个默认的输入电平
-
上拉输入模式(默认为高电平的输入模式)
上拉电阻导通连接到高电平 V D D V_{DD} VDD,下拉电阻断开
当外部设备不驱动引脚时,引脚会被上拉电阻拉到高电平
-
下拉输入模式 (默认为低电平的输入模式)
下拉电阻导通连接到低电平 V S S V_{SS} VSS,上拉电阻断开
当外部设备不驱动引脚时,引脚会被下拉电阻拉到低电平
-
浮空输入模式
上拉电阻和下拉电阻都断开,处于高阻态
当外部设备不驱动引脚时,引脚处于未定义状态,可能会受到环境干扰
-
-
TTL施密特(肖特基)触发器:对输入电压进行整形
执行逻辑:如果输入电压大于某一阈值,输出就会瞬间升为高电平;如果输入电压小于某一阈值,输出就会瞬间降低为低电平(预防因为输入数字信号失真产生的误判)
经过施密特触发器整形的波形就可以直接写入输入数据寄存器了
最后使用程序读取输入数据寄存器对应某一位的数据就可以知道端口的输入电平了
-
模拟输入 & 复用功能输入 两条线路适用于连接到片上外设的一些端口
模拟输入:连接到ADC上,因为ADC需要接收模拟量,所以模拟输入线路接在施密特触发器之前
复用功能输入:连接到其他需要读取端口的外设上,比如串口的输入引脚等,所以这根线接收的是数字量,所以接在施密特触发器后面
输出部分分析
-
数字部分可以由输出数据寄存器或片上外设控制,两种控制方式通过数据选择器接到了输出控制部分
-
如果选择通过输出数据寄存器进行控制,就是普通的 I/O 口输出,写输出数据寄存器的某一位就可以操作对应的某个端口了
-
位设置/清除寄存器:用于单独操作输出数据寄存器的某一位而不影响其他位(因为输出数据寄存器同时控制16个端口,并且该寄存器只能整体读写,所以如果想单独控制器中某一个端口而不影响其他端口的话,就需要通过设置 位设置/清除寄存器 )
如果想要对某一位进行置 1 的操作,在位设置寄存器的对应位写 1 ,剩下不需要操作的位写 0 即可;
如果想要对某一位进行清 0 的操作,在位清除寄存器的对应位写 1 ,剩下不需要操作的位写 0 即可
-
-
P-MOS管 & N-MOS管
MOS管就是一种电子开关,数字信号用于控制开关的导通和关闭,开关负责将 I/O 口接到 V D D V_{DD} VDD 或 V S S V_{SS} VSS
-
推挽输出模式
P-MOS 和 N-MOS 均有效
数据寄存器为 1 时,上管断开下管导通,输出接到低电平( V S S V_{SS} VSS )
数据寄存器为 0 时,上管导通下管断开,输出接到高电平( V D D V_{DD} VDD )
引脚输出的电平可以是高电平( V D D V_{DD} VDD )或低电平( V S S V_{SS} VSS ),没有电流流过引脚,这是最常见的输出模式
-
开漏输出模式
P-MOS 无效, N-MOS 有效
数据寄存器为 1 时,下管断开,输出相当于断开,即高阻模式
数据寄存器为 0 时,下管导通,输出接到低电平( V S S V_{SS} VSS )
在开漏输出模式下引脚输出的电平可以是低电平,而不能输出高电平
-
关闭输出模式
P-MOS 和 N-MOS 均无效
输出关闭,端口的电平由外部信号来控制
-
GPIO的8种模式
模式名称 | 性质 | 特征 |
---|---|---|
浮空输入 | 数字输入 | 可读取引脚电平,若引脚悬空,则电平不确定 |
上拉输入 | 数字输入 | 可读取引脚电平,内部连接上拉电阻,悬空时默认高电平 |
下拉输入 | 数字输入 | 可读取引脚电平,内部连接下拉电阻,悬空时默认低电平 |
模拟输入 | 模拟输入 | GPIO无效,引脚直接接入内部ADC |
开漏输出 | 数字输出 | 可输出引脚电平,高电平为高阻态,低电平接VSS |
推挽输出 | 数字输出 | 可输出引脚电平,高电平接VDD,低电平接VSS |
复用开漏输出 | 数字输出 | 由片上外设控制,高电平为高阻态,低电平接VSS |
复用推挽输出 | 数字输出 | 由片上外设控制,高电平接VDD,低电平接VSS |
四、GPIO相关函数
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
void GPIO_AFIODeInit(void);//GPIO_Init是重点
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
//初始化一个或者多个IO口(同一组)的工作方式和速度
/*
第一个参数:GPIOx,GPIO的分组,如 GPIOA,GPIOB,GPIOC等的宏定义
第二个参数:GPIO_InitStruct,GPIO的初始化相关结构体结构体里的成员变量:GPIO_Pin:指定具体的IO脚,如GPIO_Pin_0,GPIO_Pin_1GPIO_Mode:指定GPIO的模式GPIO_Speed:指定IO最快翻转速度,也就是当使用IO产生频率(如PWM)的最大速度
*/void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//用于读取指定引脚电平状态的函数,检查某个特定引脚的输入电平是高电平(逻辑1)还是低电平(逻辑0)
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//用于读取指定引脚的输出数据状态的函数,检查某个特定引脚的输出电平是高电平(逻辑1)还是低电平(逻辑0)
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//将指定的 GPIO 引脚设置为高电平(逻辑1)的函数
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//将指定的 GPIO 引脚设置为低电平(逻辑0)的函数
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
//用于设置指定 GPIO 引脚输出值的函数
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
//用于同时设置指定 GPIO 端口的所有引脚状态的函数void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);
有注释的几个函数是常用函数,可以多看一下
不需要一下全部记住,用到的时候多理解
STM32 专栏文章均参考 《STM32入门教程-2023版 细致讲解 中文字幕》教程视频