通用输入输出 GPIO 模块
基于 STM32F103 · 零基础讲解 GPIO 结构、八种工作模式、标准外设库与 HAL 库点灯。
🎯学习目标
- 了解 GPIO 的基本概念;
- 理解 STM32F103 的 GPIO 内部结构、工作模式和使用特性;
- 理解 GPIO 的输入输出模式;
- 熟悉 GPIO 相关的标准外设库函数和 HAL 库函数;
- 掌握用标准库 / HAL 库实现 LED 灯闪烁。
1GPIO 概述
GPIO(General Purpose Input/Output,通用输入输出)端口内部由一个个寄存器组成:一个引脚对应一个寄存器位,改变寄存器中的数据就能改变外设的工作方式。
💡 一句话理解GPIO 就是单片机上"可编程控制高低电平"的引脚。写寄存器=控制引脚输出,读寄存器=读取引脚输入。
与 51 单片机相比,STM32 拥有更多 I/O 引脚、更强驱动能力、更灵活的控制方式,功能也更强大。
2引脚与内部结构
STM32F103ZET6 引脚分类(144 引脚,六大类)
| 类别 | 引脚举例 |
|---|---|
| 电源引脚 | VDD、VSS、VREF+/-、VDDA、VSSA、VBAT |
| 晶振引脚 | PC14、PC15、OSC_IN、OSC_OUT |
| 复位引脚 | NRST |
| BOOT 引脚 | BOOT0、BOOT1 |
| 程序下载引脚 | PA13、PA14、PA15、PB3、PB4 |
| GPIO 引脚 | 共 7 组(PA~PG),每组 16 个:Px0~Px15 |
图1 · GPIO 组织结构:7 组 × 16 引脚,每组由 7 个寄存器控制
大多数引脚还通过复用技术兼具其他专用功能(如串口、ADC、IIC 等)。
3八种工作模式 ⭐(核心考点)
STM32 的 GPIO 共有 8 种工作模式,分为输出和输入两大类。点击卡片翻转查看要点:
📤 输出模式(4 种)
🔵
推挽输出
Push-Pull, PP两个 MOS 管互补导通:输出高电平时 P-MOS 导通,低电平时 N-MOS 导通。驱动能力强、速度快,最常用
🟠
开漏输出
Open-Drain, OD只有下拉 MOS 管、无上拉,漏极悬空。需外接上拉电阻。用于电平转换、IIC 总线、线与
🔷
复用推挽
AF Push-Pull推挽输出 + 复用功能(AFIO),引脚给片上外设用。如串口 TX、SPI
🔶
复用开漏
AF Open-Drain开漏输出 + 复用功能。如 IIC 的 SCL/SDA
📥 输入模式(4 种)
⬆️
上拉输入
IPU内部接上拉电阻,默认高电平。无输入时读到 1
⬇️
下拉输入
IPD内部接下拉电阻,默认低电平。无输入时读到 0
🔘
浮空输入
Floating既不上拉也不下拉,电平由外部决定。状态不确定,需外部确定电平
📊
模拟输入
Analog施密特触发器关闭,不接上下拉,信号直连片上外设。典型用于 A/D 采集
⭐ 推挽 vs 开漏(必考)推挽:能主动输出高和低电平,驱动强,但不能"线与";开漏:只能拉低,输出高靠外部上拉电阻,可多设备"线与",适合 IIC 总线和电平转换。
4GPIO 输出速度
注意:输出速度不是信号速度,而是 I/O 口驱动电路的响应速度。STM32F103 有 3 档:
🐢
2 MHz
低速。LED、蜂鸣器等普通外设。功耗低。
🚶
10 MHz
中速。一般复用功能。
🚀
50 MHz
高速。IIC、SPI 等高速复用输出。
💡 选择原则结合实际选择:保证信号稳定的同时降低功耗。普通外设用 2MHz,高速复用用 10/50MHz。
5GPIO 寄存器(每组 7 个)
每组 GPIO 端口(Px)由 7 个寄存器组成,控制该端口 16 个引脚:
| 寄存器 | 作用 |
|---|---|
| CRL / CRH(配置低/高) | 配置每个引脚的模式和速度(低 8 位 / 高 8 位) |
| IDR(输入数据) | 读取引脚输入电平 |
| ODR(输出数据) | 设置引脚输出电平 |
| BSRR(位设置/复位) | 原子地置位/复位引脚(高 16 位复位,低 16 位置位) |
| BRR(位复位) | 原子地复位引脚 |
| LCKR(锁定) | 锁定引脚配置 |
6标准外设库接口函数
源码在 stm32f10x_gpio.c,头文件 stm32f10x_gpio.h 声明了共 18 种库函数。
| 类型 | 常用函数 | 功能 |
|---|---|---|
| 初始化/复位 | GPIO_Init() | 按结构体参数初始化 GPIO |
GPIO_DeInit() | 恢复默认复位值 | |
| 引脚操作 | GPIO_SetBits() | 置位引脚(输出高) |
GPIO_ResetBits() | 复位引脚(输出低) | |
GPIO_WriteBit() | 写指定引脚电平 | |
GPIO_ReadInputDataBit() | 读输入引脚电平 | |
| 外部中断 | GPIO_EXTILineConfig() | 配置端口为中断线输入 |
GPIO_Init() 有两个参数:① 端口 x(A~G);② 指向 GPIO_InitTypeDef 结构体的指针。结构体成员:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 引脚 0~15 或 All
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 工作模式(推挽输出)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; // 输出速度
GPIO_Init(GPIOA, &GPIO_InitStructure);
7标准库 vs HAL 库
| 对比 | 标准外设库 (StdPeriph) | HAL 库 |
|---|---|---|
| 抽象程度 | 贴近寄存器,效率高 | 高度抽象,跨系列可移植 |
| 初始化 | GPIO_Init() | HAL_GPIO_Init() |
| 写引脚 | GPIO_SetBits()/ResetBits() | HAL_GPIO_WritePin() |
| 翻转 | 读 ODR 取反写回 | HAL_GPIO_TogglePin() |
| 读引脚 | GPIO_ReadInputDataBit() | HAL_GPIO_ReadPin() |
| 配套工具 | 手写 | STM32CubeMX 图形化生成 |
⭐重点例题:LED 闪烁
例题:用标准库让 PA0 上的 LED 每 500ms 闪烁一次
思路:① 开 GPIOA 时钟 → ② 配 PA0 为推挽输出 → ③ 循环置位/复位 + 延时。
// ① 使能 GPIOA 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// ② 配置 PA0 推挽输出 2MHz
GPIO_InitTypeDef g;
g.GPIO_Pin=GPIO_Pin_0; g.GPIO_Mode=GPIO_Mode_Out_PP; g.GPIO_Speed=GPIO_Speed_2MHz;
GPIO_Init(GPIOA,&g);
// ③ 主循环闪烁
while(1){
GPIO_SetBits(GPIOA,GPIO_Pin_0); delay_ms(500); // 亮
GPIO_ResetBits(GPIOA,GPIO_Pin_0); delay_ms(500); // 灭
}
关键点:① 必须先开时钟(GPIO 挂在 APB2 总线),不开时钟配置无效;② LED 接法决定亮灭逻辑(共阳极时低电平亮)。
HAL 库等价写法
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef g={0};
g.Pin=GPIO_PIN_0; g.Mode=GPIO_MODE_OUTPUT_PP; g.Speed=GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA,&g);
while(1){ HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_0); HAL_Delay(500); }
🎯自测(点击展开)
STM32F103 有几组 GPIO?每组几个引脚?
7 组(PA~PG),每组 16 个引脚(Px0~Px15)。
推挽输出和开漏输出有什么区别?
推挽能主动输出高低电平、驱动强;开漏只能拉低,输出高靠外部上拉,可"线与",适合 IIC 总线和电平转换。
"GPIO 输出速度"指的是什么?
指 I/O 口驱动电路的响应速度,不是信号速度。有 2/10/50MHz 三档。
配置 GPIO 前必须先做什么?
使能对应 GPIO 端口的时钟(如 RCC_APB2PeriphClockCmd),否则配置无效。
📝强化题库
选择题点选即时判分;填空题输入后"检查"或"显示答案"。
已答 0/0答对 0正确率 —
已答 0/0答对 0