【STM32基础篇】GPIO 工作原理、8种模式深度剖析
1. GPIO 概述与硬件结构解析
GPIO(General Purpose Input/Output,通用输入输出端口)是单片机最基础的外设,任何按键输入、LED 控制、Sensor 传感器读取或通信总线(如 I2C、SPI 模拟)都建立在 GPIO 基础之上。
STM32 的每一个 GPIO 引脚内部结构都非常精密,支持独立配置:
GPIO 引脚结构包含以下核心部件:
-
保护二极管:防止引脚输入电压过高或过低损坏芯片内部电路(输入电压限制在 $V_{DD} + 0.3\text{V}$ 和 $V_{SS} - 0.3\text{V}$ 之间)。
-
上拉/下拉电阻:内部开关控制接上拉电阻(接 $V_{DD}$)或下拉电阻(接 $V_{SS}$)。
-
施密特触发器(Schmitt Trigger):将输入的模拟电平整形转换为逻辑数字信号 $0$ 或 $1$。
-
P-MOS 和 N-MOS 管:构成输出驱动电路,实现推挽或开漏输出。
2. GPIO 的 8 种工作模式详解
STM32 的 GPIO 模式可以通过软件配置为以下 8 种:
2.1 输入模式(Input)
-
输入浮空(GPIO_MODE_INPUT):
-
不接上拉也不接下拉电阻,引脚电平完全由外部输入决定。
-
适用场景:USART 接收引脚(RX)、外部按键(外部已有上下拉)。
-
-
输入上拉(GPIO_MODE_INPUT + Pull-up):
-
内部连接上拉电阻,默认无输入时保持高电平。
-
适用场景:低电平有效的按键检测。
-
-
输入下拉(GPIO_MODE_INPUT + Pull-down):
-
内部连接下拉电阻,默认无输入时保持低电平。
-
适用场景:高电平有效的按键检测。
-
-
模拟输入(GPIO_MODE_ANALOG):
-
关闭施密特触发器和数字通道,输入直接连到 ADC 转换器。
-
适用场景:ADC 电压采集、低功耗省电模式。
-
2.2 输出模式(Output)
-
开漏输出(GPIO_MODE_OUTPUT_OD):
-
上管 P-MOS 始终关闭,仅 N-MOS 导通。输出 $0$ 时接 GND,输出 $1$ 时呈现高阻态。
-
适用场景:需要线与逻辑的通信总线(如 I2C)、或者需要通过外部上拉驱动不同电压等级驱动(如 5V 逻辑)。
-
-
推挽输出(GPIO_MODE_OUTPUT_PP):
-
P-MOS 和 N-MOS 交替导通。输出 $1$ 时强拉高,输出 $0$ 时强拉低,驱动能力强(通常最大可达 20mA)。
-
适用场景:驱动 LED、蜂鸣器、开关管、SPI 时钟线等。
-
-
复用开漏(GPIO_MODE_AF_OD):
-
由片上外设(如 I2C)直接控制引脚,硬件自动切换开漏输出模式。
-
-
复用推挽(GPIO_MODE_AF_PP):
-
由片上外设(如 USART_TX、PWM、SPI_SCK)控制推挽输出。
-
3.完整代码实现(基于 STM32CubeMX + HAL 库)
3.1 STM32CubeMX 配置步骤
-
打开 CubeMX,选择
STM32F103C8T6。 -
将
PC13引脚配置为GPIO_Output(默认 High,推挽模式)。 -
将
PA0引脚配置为GPIO_Input,并在 GPIO 配置栏将 GPIO Pull-up/Pull-down 设置为 Pull-up。 -
在
SYS中将 Debug 设置为Serial Wire。 -
生成工程并在 Keil 中打开。
3.2 C 语言代码实现 (main.c)
#include "main.h"
/* 私有函数声明 */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/**
* @brief 应用程序入口
*/
int main(void)
{
/* 复位所有外设,初始化 Flash 接口和 SysTick */
HAL_Init();
/* 配置系统时钟 (72MHz) */
SystemClock_Config();
/* 初始化所有已配置的 GPIO 引脚 */
MX_GPIO_Init();
/* 初始化 LED 状态:设置为高电平(灭) */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
/* 主循环 */
while (1)
{
/* 读取 PA0 引脚的电平状态 */
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
{
/* 软件消抖:延时 20ms */
HAL_Delay(20);
/* 再次确认按键是否依然被按下 */
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
{
/* 翻转 PC13 引脚电平,实现 LED 亮灭切换 */
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
/* 等待按键释放 (松手检测) */
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
{
// 空等待
}
}
}
}
}
更多推荐

所有评论(0)