这份 GPIO/AFIO 的核心逻辑适用于所有 STM32 系列,但不同型号(F1/F4/F7/H7/L4 等)有细节差异,工作中只需关注 “通用逻辑 + 型号专属差异” 即可,本文结合数据手册用通俗易懂的语言整理,详略得当,注重内容实用性。
STM32F1 GPIO+AFIO 实用手册(大白话版)
一、先搞懂基础:STM32 芯片分类(不用记细节,知道就行)
可以把 STM32F1 系列按 “闪存大小” 分成几类,不同类别功能略有差异,但 GPIO 用法基本一样:
- 小容量:闪存 16K~32K(入门款)
- 中容量:闪存 64K~128K(最常用)
- 大容量:闪存 256K~512K(功能更多)
- 互联型:F105/F107(带以太网、双 CAN,GPIO 重映射更丰富)
二、GPIO 核心:8 种工作模式(工作必记,其余可忘)
GPIO 就是芯片的 “对外接口”,每个引脚能设成 8 种模式,用通俗的话解释:
表格
| 输入浮空 | 引脚悬空,啥都不接,只检测外部电平 | 串口 RX、外部中断触发 |
| 输入上拉 | 引脚默认高电平,外部拉低才变低 | 按键检测(不用外接上拉电阻) |
| 输入下拉 | 引脚默认低电平,外部拉高才变高 | 外部传感器信号检测 |
| 模拟输入 | 禁用数字电路,专门接模拟信号 | ADC 采样、DAC 输出 |
| 通用推挽输出 | 能主动拉高 / 拉低,驱动能力强 | 点灯、继电器、电机控制 |
| 通用开漏输出 | 只能拉低,拉高靠外部上拉电阻 | 多设备共用总线(无外设复用) |
| 复用推挽输出 | 由芯片内部外设(如串口)控制,不是手动改 | 串口 TX、SPI 时钟、定时器 PWM |
| 复用开漏输出 | 外设控制 + 开漏特性,需外部上拉 | I2C 的 SCL/SDA、CAN 通信 |
关键提醒:
- 推挽 =“能推能拉”:输出 1 时引脚变高,输出 0 时变低,直接驱动设备;
- 开漏 =“只拉不推”:输出 0 时引脚变低,输出 1 时引脚悬空,必须外接上拉电阻才能变高(I2C 必用)。
三、GPIO 配置:核心是 “4 位开关”(CRL/CRH 寄存器)
每个 GPIO 引脚的模式由 “4 个二进制位” 决定(存在 CRL/CRH 寄存器里),可以理解成 “4 个小开关”:
CNF=Configuration即引脚模式配置位
- 前 2 位(CNF):管 “模式类型”(是推挽还是开漏,是通用还是复用);
- 后 2 位(MODE):管 “速度 / 方向”(输入还是输出,输出的话反应多快)。
极简配置逻辑(记这个就够):
- 模拟输入:CNF=00;浮空输入:CNF=01;上拉 / 下拉输入:CNF=10;
- 通用推挽:CNF=00;通用开漏:CNF=01;复用推挽:CNF=10;复用开漏:CNF=11。
举例子(工作中直接套):
- 想让 PA0 点灯(通用推挽输出):MODE=11(50MHz),CNF=00;
- 想让 PB6 做 I2C_SCL(复用开漏输出):MODE=11,CNF=11;
- 想让 PC13 接按键(输入上拉):MODE=00,CNF=10。
四、7 个 GPIO 寄存器:只记 “怎么用”,别记地址
寄存器就是芯片里的 “开关盒”,不用记具体地址,知道功能和用法就行:
表格
| GPIOx_CRL | 管引脚 0~7 的配置 | 配置 PA0~PA7、PB0~PB7 等 |
| GPIOx_CRH | 管引脚 8~15 的配置 | 配置 PA8~PA15、PB8~PB15 等 |
| GPIOx_IDR | 只读!看引脚实际电平 | 检测按键是否按下、读传感器值 |
| GPIOx_ODR | 读写!设输出电平(但不安全) | 临时改电平,中断里别用 |
| GPIOx_BSRR | 只写!安全改电平(重点) | 中断里点灯 / 控设备,只改 1 个引脚,不影响其他 |
| GPIOx_BRR | 只写!专门清零电平 | 想让引脚变低时用,比 BSRR 简单 |
| GPIOx_LCKR | 锁死配置(复位前改不了) | 工业场景用,普通项目不用 |
1. CRL
Configuration Register Low
-
配置寄存器(低 8 位)
-
管:Pin0 ~ Pin7
2. CRH
Configuration Register High
-
配置寄存器(高 8 位)
-
管:Pin8 ~ Pin15
3. IDR
Input Data Register
-
输入数据寄存器
-
作用:读引脚电平
4. ODR
Output Data Register
-
输出数据寄存器
-
作用:写输出电平
5. BSRR
Bit Set / Reset Register
-
位置位 / 复位寄存器
-
作用:只写 1 有效,安全改引脚
6. BRR
Bit Reset Register
-
位复位寄存器
-
作用:只用来把引脚拉低
7. LCKR
Lock Register
-
锁定寄存器
-
作用:锁死引脚配置,不让改
超级精简记忆(背这 7 行就够)
-
CRL:配置低 8 位
-
CRH:配置高 8 位
-
IDR:读电平
-
ODR:写电平
-
BSRR:安全置位 / 复位
-
BRR:只复位
-
LCKR:锁配置
核心用法(工程必会):
五、复用功能:让 GPIO 听 “外设” 的话(重点)
1. 啥是复用功能?
普通 GPIO 是 “你手动控制”,复用功能是 “把 GPIO 交给串口、I2C、定时器等内部外设控制”,比如串口 TX 引脚,电平由串口自动发,不是你手动改。
2. 复用功能配置步骤(一步都不能少):
3. 关键提醒:
- 复用输出时,GPIO 的 ODR 寄存器失效!引脚电平由外设控制,不是你写 ODR 能改的;
- 如果外设没激活(比如串口没初始化),复用引脚的电平会乱跳,一定要先初始化外设。
六、AFIO:GPIO 的 “搬家公司”(重映射 + 外部中断)
AFIO 是辅助 GPIO 工作的模块,核心就两件事,先开 AFIO 时钟才能用:
1. 引脚重映射(实用)
把外设的默认引脚 “挪到别的引脚”,比如串口 1 默认用 PA9/TX、PA10/RX,如果这两个引脚被占了,就通过 AFIO 把串口 1 挪到 PB6/TX、PB7/RX。
- 配置寄存器:AFIO_MAPR(改里面的 USART1_REMAP 位就行);
- 常用场景:JTAG 引脚(PA13/14/15、PB3/4)想当普通 GPIO 用→改 AFIO_MAPR 的 SWJ_CFG 位,关闭 JTAG 即可。
2. 外部中断配置(必用)
STM32 的外部中断是 “按引脚号分的”(EXTI0~EXTI15),比如 EXTI0 对应所有端口的 0 号引脚(PA0、PB0、PC0…),AFIO 就是用来 “选哪个端口的引脚触发中断”。
- 配置寄存器:AFIO_EXTICR1~4(比如想让 PB0 触发 EXTI0 中断,就往 EXTICR1 的 EXTI0 位写 0001);
- 步骤:先把 GPIO 设为输入模式→用 AFIO 选引脚→配置中断控制器。
七、复位默认状态(排错必知)
- 所有 GPIO 复位后默认是 “浮空输入”;
- JTAG/SWD 引脚(PA13/14/15、PB3/4)复位后带上下拉,想当普通 GPIO 用,必须先通过 AFIO 重映射关闭 JTAG。
八、工程排错小技巧(实用!)
总结(核心 3 句话,记死!)
这份 GPIO/AFIO 的核心逻辑适用于所有 STM32 系列,但不同型号(F1/F4/F7/H7/L4 等)有细节差异,工作中只需关注 “通用逻辑 + 型号专属差异” 即可。
一、通用逻辑(所有 STM32 都适用,记死!)
不管是 F1/F4/F7,还是 L4/G4/H7,GPIO 的核心设计思路完全一致,你之前记的这些内容通用:
- 配置模式的寄存器(F1 是 CRL/CRH,其他型号可能叫 MODER/OTYPER/OSPEEDR/PUPDR)→ 本质都是 “定模式、定速度、定上下拉”;
- 读电平的寄存器(IDR)、写电平的寄存器(ODR)、安全改电平的寄存器(BSRR/BRR)→ 功能和用法完全一样,只是位宽可能从 16 位变 32 位;
- 复用功能核心规则:“GPIO 交给外设控制、需开对应时钟、重映射靠 AFIO/ SYSCFG”→ 逻辑不变;
二、不同型号的关键差异(工作中只记这些,其余可查手册)
1. F1(你学的这款)vs F4/F7/H7(中高端)
表格
| 配置寄存器 | CRL/CRH(4 位配 1 个引脚) | MODER/OTYPER/OSPEEDR/PUPDR(分寄存器配置) | 配置步骤多 1 步,但逻辑一样(比如 F4 先设 MODER 为输出,再设 OTYPER 为推挽) |
| 重映射模块 | AFIO(单独模块) | SYSCFG(整合到系统配置) | 开时钟时 F4 要开 SYSCFG,F1 开 AFIO,代码改个宏就行 |
| 速度等级 | 10/2/50MHz | 25/50/100/180MHz | 配置时选更高速度,不影响用法 |
| 复用模式命名 | 复用推挽 / 开漏 | 复用功能模式(自动区分推挽 / 开漏) | 不用纠结命名,手册查对应外设的 GPIO 配置即可 |
2. F1 vs L0/L4/G4(低功耗 / 性价比款)
- 核心差异:低功耗型号多了 “开漏上拉”“模拟输出” 等小众模式,还支持 “GPIO 唤醒低功耗”,但日常用的推挽 / 上拉输入 / 复用功能完全和 F1 一样;
- 实用影响:做低功耗项目时查手册加配置,普通项目(点灯、串口、I2C)直接照搬 F1 的逻辑。
3. F1 vs STM32H7(高端款)
- 核心差异:H7 的 GPIO 支持更多引脚、更高电压、更精细的速度控制,还能配置 “施密特触发阈值”,但基础用法(配模式、改电平、读电平)和 F1 完全一致;
- 实用影响:高端项目关注手册的 “特殊配置”,基础功能不用重新学。
三、工作中怎么快速适配不同型号(实用技巧)
- 打开对应型号的参考手册,搜 “GPIO 配置”“外设 GPIO 映射”,比如 F4 的 USART1_TX 默认是 PA9,和 F1 一样,直接配复用模式就行;
- 重映射时,F1 查 AFIO_MAPR,F4 查 SYSCFG_MEMRMP/SYSCFG_EXTICR,只是寄存器名变了,功能位的逻辑(比如 USART1_REMAP)完全一致;
- 用 HAL 库:几乎不用改代码,只改引脚定义(比如 F1 是 GPIOA_PIN_0,F4 也是),HAL 库会自动适配寄存器差异;
- 用寄存器:只需要把 F1 的 CRL/CRH 配置,换成对应型号的 MODER/OTYPER 配置,比如 F1 配 PA0 为推挽输出是改 CRL 的 4 位,F4 是改 MODER 为 01(输出)、OTYPER 为 0(推挽)。
总结(核心 2 句话)
简单说:你现在吃透的 F1 GPIO 知识,是所有 STM32 的 “通用语法”,换型号只需要查 “单词表(手册)”,不用重新学 “语法规则”。
一、实验基础信息(硬件 + 功能不变)
1. 硬件接线
表格
| LED | PA0(正极)+ GND(负极) | 串 220Ω 限流电阻 |
| 按键 | PB0(一端)+ GND(另一端) | 上拉输入,按下拉低 |
2. 实验功能
- 默认:LED 以 500ms 频率闪烁;
- 按键按下:LED 停止闪烁,保持常亮;
- 按键松开:LED 恢复闪烁。
#include "stm32f10x.h"
// 简易ms级延时(72MHz)
void Delay_ms(uint32_t ms)
{
uint32_t i,j;
for(i=0;i<ms;i++) for(j=0;j<1141;j++);
}
// GPIO初始化:PA0(LED输出)、PB0(按键上拉输入)
void GPIO_Init_LED_Key(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
// PA0 通用推挽输出 50MHz
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// PB0 上拉输入
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
// 读按键:1=按下,0=未按
uint8_t Key_Read(void)
{
return (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0) ? 1 : 0;
}
int main(void)
{
uint8_t key_flag = 0;
GPIO_Init_LED_Key();
while(1)
{
key_flag = Key_Read();
if(key_flag) // 按键按下,LED常亮
GPIO_SetBits(GPIOA, GPIO_Pin_0);
else // 松开,LED闪烁
{
GPIO_SetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
}
}
}




