一、含义
GPIO代表通用输入/输出,是一种用于与外部设备通信的通用接口。
在嵌入式系统中,GPIO通常是一组可以配置为输入或输出的引脚,用于与外部电子元件(如传感器、执行器、LED等)进行数字通信。
| 模式分类 |
工作模式 |
典型功能 / 说明 |
| 输出模式 |
推挽输出 |
输出高电平为 VCC,低电平为 GND,驱动能力强 |
|
开漏输出 |
输出高电平需外部上拉电阻,可实现线与功能 |
| 输入模式 |
上拉输入 |
内部上拉电阻接 VCC,无信号时为高电平 |
|
下拉输入 |
内部下拉电阻接 GND,无信号时为低电平 |
|
浮空输入 |
无上下拉,电平由外部电路决定,易受干扰 |
| 模拟模式 |
模拟输入/输出 |
用于 ADC(采样模拟电压)和 DAC(输出模拟电压) |
| 复用模式 |
复用功能 |
引脚由片上外设控制,如 USART、I²C、SPI 等 |
二、输入模式
GPIO输入模式常用来检查芯片外部IO引脚的状态,
外部电压经过TTL施密特触发器之后,将输出逻辑,最终写于GPIO寄存器。
2.1 TTL施密特触发器
| 项目 |
参数 / 说明 |
| 基本功能 |
整形电路,将输入信号整形为方波信号 |
| 正向阈值电压(上触发点) |
2.31V(0.7 × VDD,适用于 1.7V ≤ VDD ≤ 3.6V) |
| 负向阈值电压(下触发点) |
0.99V(0.3 × VDD,适用于 1.7V ≤ VDD ≤ 3.6V) |
| 逻辑规则 |
• 输入电压 > 正向阈值 → 输出高电平(1) • 输入电压 < 负向阈值 → 输出低电平(0) |
| 5V 容忍输入电压范围 |
-0.3V ~ 5.5V(适用于 2V ≤ VDD ≤ 3.6V) |
| 输出信号类型 |
数字信号(1 / 0) |
2.2 各个模式
| 输入模式 |
内部电阻 |
默认电平 |
典型应用 |
说明 |
| 浮空输入 |
无上拉/下拉 |
高阻态(不确定) |
检测外部真实电平(如按键、外部信号) |
引脚处于高阻状态,电平完全由外部电路决定,易受干扰 |
| 上拉输入 |
内部上拉电阻 |
高电平 |
检测外部信号是否为低电平 |
默认高电平,外部拉低时检测到低电平 |
| 下拉输入 |
内部下拉电阻 |
低电平 |
检测外部信号是否为高电平 |
默认低电平,外部拉高时检测到高电平 |
三、输出模式
GPIO控制器输出模式,主要是由P-MOS管和N-MOS管组成的一个结构单元。
当P-MOS管和N-MOS管同时工作,可组成推挽输出模式
当只有N-MOS管工作时,可组成开漏输出模式
3.1 推挽输出
| 项目 |
说明 |
| 命名依据 |
根据 P-MOS 和 N-MOS 管的工作方式命名 |
| 输入低电平时 |
P-MOS 管导通,N-MOS 管截止 → 对外输出高电平 |
| 输入高电平时 |
P-MOS 管截止,N-MOS 管导通 → 对外输出低电平 |
| 驱动能力 |
强(可直接输出高电平和低电平) |
| 是否需要外部上拉电阻 |
不需要 |
| 典型应用 |
驱动 LED、数字信号输出、普通 I/O 通信 |
3.2 开漏输出
| 项目 |
说明 |
| P-MOS 管状态 |
不论输入高低,始终处于关闭状态 |
| 输入高电平时 |
N-MOS 管导通 → 输出为低电平 |
| 输入低电平时 |
N-MOS 管截止 → 输出为高阻态(既非高电平也非低电平) |
| 输出高电平条件 |
必须外接上拉电阻,由上拉电阻提供高电平 |
| 是否需要外部上拉电阻 |
需要(如需输出高电平) |
| 线与逻辑说明 |
当多个开漏输出引脚并联时: • 所有设备都输出高电平 (高阻态+上拉)→ 总线为高电平 • 任一设备输出低电平 (N-MOS导通)→ 总线被拉低电平 • 这种机制方便实现总线仲裁 和同步通信 |
| 典型应用 |
I²C 总线、SMBus、多设备共享线路(需线与功能的场景) |
3.2.1 ODR与BSRR寄存器
| 对比项 |
ODR 寄存器 |
BSRR 寄存器 |
| 定义 |
输出数据寄存器(Output Data Register) |
端口位设置/复位寄存器(Bit Set/Reset Register) |
| 作用 |
控制 GPIO 引脚的输出电平状态(高/低) |
实现原子操作方式设置或清除 GPIO 引脚状态 |
| 基本功能 |
• 写 1 → 对应引脚输出高电平 • 写 0 → 对应引脚输出低电平 • 可读回当前输出值 |
• 低16位写 1 → 对应引脚输出高电平 • 高16位写 1 → 对应引脚输出低电平 • 写 0 无效,不影响其他引脚 |
| 工作原理 |
读‑改‑写 : 1. 读取整个 ODR 值 2. 修改其中特定位 3. 将修改后的值写回 ODR |
直接写 : 1. 软件准备好要置位/复位的位掩码 2. 一次性写入 BSRR 3. 硬件自动完成对应引脚的电平改变 |
| 是否支持读取 |
支持(可读取当前输出状态) |
不支持(只写寄存器,读返回无效数据) |
| 操作原子性 |
非原子(读‑改‑写之间可能被中断破坏) |
原子(一次写入,硬件一次性完成) |
| 对其它引脚影响 |
有风险(修改一位时必须回写整个寄存器,可能误改其它位) |
无影响(只改变被写 1 的位,其他引脚维持原状) |
| 硬件实现 |
一个锁存器,直接连到输出驱动电路 |
两个锁存器/触发器(一个用于置位,一个用于复位),输出由两个触发器的状态决定 |
ODR 是整体覆盖写入,修改部分引脚时必须先读取全部状态来保护其他引脚;BSRR 是独立脉冲控制,置高和置低分开,永远不需要读取当前状态,因此混合操作也能一步原子完成。
四、模拟与复用模式
| 对比项 |
复用模式 |
模拟模式 |
| 控制主体 |
对应的外设控制器(如 USART、I²C、SPI、定时器等) |
ADC 控制器 / DAC 控制器 |
| 工作原理 |
将 IO 引脚设置为复用模式后,管脚状态的控制不再由 GPIO 控制器控制,而是由对应的外设控制器进行状态控制 |
IO 引脚上的模拟电压在 GPIO 部分不做任何处理,直接输入到芯片内部的 ADC 控制器进行采样处理 |
| 信号类型 |
数字信号(0 或 1) |
模拟信号(连续电压值) |
| 是否经过施密特触发器 |
是(输入路径) |
否(直通 ADC) |
| 引脚状态 |
由外设决定(高/低电平) |
高阻态,电压值由外部模拟电路决定 |
| 典型应用 |
USART、I²C、SPI、PWM、定时器输入捕获、外部中断等 |
ADC 模拟电压采集、DAC 模拟电压输出 |
| 配置要点 |
需将引脚映射到对应的复用功能(AF) |
需配置为模拟模式,引脚连接 ADC/DAC 通道 |
五、GPIO寄存器映射
5.1 GPIO 各组寄存器基址
| GPIO 组 |
寄存器基址 |
| GPIOA |
0x40020000 |
| GPIOB |
0x40020400 |
| GPIOC |
0x40020800 |
| GPIOD |
0x40020C00 |
| GPIOE |
0x40021000 |
| GPIOF |
0x40021400 |
| GPIOG |
0x40021800 |
| GPIOH |
0x40021C00 |
| GPIOI |
0x40022000 |
规律 :每组 GPIO 寄存器地址间隔 0x400(1024 字节)
5.2 GPIO 寄存器映射(偏移地址)
| 寄存器名称 |
缩写 |
偏移地址 |
功能描述 |
| GPIO 端口模式寄存器 |
GPIOx_MODER |
0x00 |
配置引脚模式(输入/输出/复用/模拟) |
| GPIO 端口输出类型寄存器 |
GPIOx_OTYPER |
0x04 |
配置输出类型(推挽/开漏) |
| GPIO 端口输出速度寄存器 |
GPIOx_OSPEEDR |
0x08 |
配置输出速度(低速/中速/高速/超高速) |
| GPIO 端口上拉/下拉寄存器 |
GPIOx_PUPDR |
0x0C |
配置上拉/下拉电阻(上拉/下拉/浮空) |
| GPIO 端口输入数据寄存器 |
GPIOx_IDR |
0x10 |
读取引脚输入电平状态(只读) |
| GPIO 端口输出数据寄存器 |
GPIOx_ODR |
0x14 |
控制引脚输出电平(可读可写) |
| GPIO 端口置位/复位寄存器 |
GPIOx_BSRR |
0x18 |
原子操作置高/置低引脚(只写) |
| GPIO 复用功能低位寄存器 |
GPIOx_AFRL |
0x20 |
配置引脚 0~7 的复用功能 |
| GPIO 复用功能高位寄存器 |
GPIOx_AFRH |
0x24 |
配置引脚 8~15 的复用功能 |
基址与偏移的使用方法
某个具体寄存器的地址 = 该组基址 + 偏移地址
**六、**HAL库接口
6.1 GPIO引脚初始化配置结构体
typedef struct
{
uint32_t Pin; /* 要配置的 GPIO 引脚 */
uint32_t Mode; /* GPIO 引脚的工作模式 */
uint32_t Pull; /* GPIO 引脚是否使用上、下拉电阻 */
uint32_t Speed; /* GPIO 引脚电平反转速度 */
uint32_t Alternate; /* GPIO 引脚复用模式 */
} GPIO_InitTypeDef;
6.2 GPIO引脚状态
typedef enum
{
GPIO_PIN_RESET = 0, /* 低电平状态 */
GPIO_PIN_SET /* 高电平状态 */
} GPIO_PinState;
6.3 HAL_GPIO_Init函数
| 项目 |
说明 |
| 函数功能 |
初始化 GPIO 控制器 |
| 函数原型 |
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init) |
| 参数 GPIOx |
GPIO 组控制器基址(如 GPIOA、GPIOB 等) |
| 参数 GPIO_Init |
GPIO 引脚模式配置(引脚号、模式、上下拉、速度、复用功能等) |
| 返回值 |
无 |
6.4 HAL_GPIO_ReadPin函数
| 项目 |
说明 |
| 函数功能 |
读取 GPIO 端口电平状态 |
| 函数原型 |
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) |
| 参数 GPIOx |
GPIO 组控制器基址(如 GPIOA、GPIOB 等) |
| 参数 GPIO_Pin |
GPIO 组内引脚(如 GPIO_PIN_0、GPIO_PIN_1 等) |
| 返回值 |
GPIO 引脚状态(GPIO_PIN_RESET 低电平 / GPIO_PIN_SET 高电平) |
6.5 HAL_GPIO_WritePin函数
| 项目 |
说明 |
| 函数功能 |
设置 GPIO 端口电平状态 |
| 函数原型 |
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) |
| 参数 GPIOx |
GPIO 组控制器基址(如 GPIOA、GPIOB 等) |
| 参数 GPIO_Pin |
GPIO 组内引脚(如 GPIO_PIN_0、GPIO_PIN_1 等) |
| 参数 PinState |
要设置的状态(GPIO_PIN_RESET 低电平 / GPIO_PIN_SET 高电平) |
| 返回值 |
无 |
6.6 HAL_GPIO_TogglePin函数
| 项目 |
说明 |
| 函数功能 |
反转 GPIO 端口电平状态 |
| 函数原型 |
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) |
| 参数 GPIOx |
GPIO 组控制器基址(如 GPIOA、GPIOB 等) |
| 参数 GPIO_Pin |
GPIO 组内引脚(如 GPIO_PIN_0、GPIO_PIN_1 等) |
| 返回值 |
无 |