前言
在STM32的开发中,引脚是MCU与外部电路交互的物理桥梁。STM32F103C8T6这款经典的Cortex-M3单片机在LQFP48封装下仅有48个引脚,却能支持GPIO、ADC、USART、SPI、I2C、定时器、USB等多种外设功能——这得益于其灵活的多功能引脚复用机制。深入理解引脚的内部结构、工作模式、复用规则和重映射方法,是编写稳定可靠嵌入式代码的基础。
本文从引脚分类出发,逐步深入到GPIO的8种工作模式、外设复用与重映射机制,并给出完整的标准库配置代码。所有代码均经过验证,可直接用于项目开发。

一、STM32F103C8T6引脚全局概览
1.1 引脚总数与端口分组
STM32F103C8T6采用LQFP48封装,共有48个引脚,按PA、PB、PC、PD端口分组。除去电源、复位、晶振和调试接口占用外,可用的普通GPIO引脚约37个(PA0PA15、PB0PB15、PC13PC15、PD0PD1)。
1.2 核心功能引脚
| 引脚号 | 符号 | 功能 | 设计建议 |
|---|---|---|---|
| 4, 36 | VDD | 3.3V主电源 | 必须并联100nF去耦电容 |
| 3, 35 | VSS | 地 | 就近接PCB地平面 |
| 5 | VBAT | RTC备份电源(1.8V~3.6V) | 可接纽扣电池 |
| 48 | NRST | 复位(低电平有效) | 建议接10kΩ上拉电阻 |
| 8 | PC14 | 低速外部晶振输入(LSE,32.768kHz) | — |
| 9 | PC15 | 低速外部晶振输出(LSE) | — |
| 18 | PD0 | 高速晶振输入(OSC_IN,4MHz~16MHz) | — |
| 19 | PD1 | 高速晶振输出(OSC_OUT) | — |
| 39 | PA13 | SWDIO(调试数据线) | 若用作GPIO需禁用SWD/JTAG |
| 40 | PA14 | SWCLK(调试时钟线) | 同上 |
| 7 | BOOT0 | 启动模式选择 | 需接10kΩ下拉电阻 |
| 20 | PB2 | BOOT1 | — |
注意:PA15、PB3、PB4默认用于JTAG调试功能,若需用作普通GPIO,必须通过AFIO重映射禁用JTAG并保留SWD模式。
1.3 按功能分类总览
| 功能类别 | 典型引脚 | 说明 |
|---|---|---|
| GPIO通用输入/输出 | PA0~PA15, PB0~PB15, PC13~PC15, PD0~PD1 | 每个引脚最多3种功能(主功能 + 默认复用 + 重映射复用) |
| ADC模拟输入 | PA0~PA7, PB0~PB1 | 12位分辨率,最多10个外部通道 |
| USART串口 | USART1: PA9/PA10; USART2: PA2/PA3; USART3: PB10/PB11(重映射) | 3个USART接口 |
| SPI | SPI1: PA5~PA7; SPI2: PB12~PB15 | 2个SPI接口 |
| I2C | I2C1: PB6/PB7; I2C2: PB10/PB11 | 2个I2C接口 |
| 定时器PWM | PA0~PA3, PA6~PA7, PB0~PB1等 | 4个通用定时器,支持多路PWM输出 |
| 调试接口 | PA13(SWDIO), PA14(SWCLK), PA15(JTDI), PB3(JTDO), PB4(JNTRST) | 默认JTAG+SWD,可禁掉JTAG释放引脚 |
二、GPIO的8种工作模式详解
STM32的每个GPIO引脚均可通过软件配置为以下8种模式之一。理解每种模式的内部等效电路和适用场景,是正确配置引脚的前提。
2.1 输入模式(3种)
(1)浮空输入(GPIO_Mode_IN_FLOATING)
引脚电平完全由外部电路决定,内部上拉/下拉电阻均被断开。输入信号经施密特触发器整形后送入输入数据寄存器。
- 适用场景:外部信号已有明确高低驱动(如外接上拉电阻的按键、数字传感器输出)。
- 注意事项:抗干扰能力弱,悬空时电平不确定,可能导致额外功耗。
(2)上拉输入(GPIO_Mode_IPU)
内部约40kΩ上拉电阻被激活,引脚默认状态为高电平。
- 适用场景:按键一脚接GND(省去外部上拉电阻)、低电平有效的信号检测。
- 典型应用:将按键接在引脚和GND之间,未按下时引脚因内部上拉读到高电平,按下时读到低电平。
(3)下拉输入(GPIO_Mode_IPD)
内部约40kΩ下拉电阻被激活,引脚默认状态为低电平。
- 适用场景:高电平有效的信号检测,防止悬空误触发。
2.2 输出模式(2种)
(4)推挽输出(GPIO_Mode_Out_PP)
内部由一对PMOS + NMOS组成的图腾柱结构驱动,可主动输出高电平(接近VDD)或低电平(接近GND),驱动能力强(单个引脚最大25mA)。
- 适用场景:驱动LED、蜂鸣器等负载。
- 电压特性:输出高电平典型值为VDD - 0.5V,即3.3V供电时约2.8V。
- 使用限制:所有引脚总输出电流不得超过150mA(含电源电流)。
(5)开漏输出(GPIO_Mode_Out_OD)
仅保留NMOS下拉管,无PMOS上拉管。输出高电平时引脚处于高阻态,必须外接上拉电阻才能输出明确的高电平。
- 适用场景:I2C总线、电平转换、多设备“线与”逻辑。
- 核心原则:开漏输出必须外接上拉电阻,否则永远无法输出高电平。
2.3 复用功能模式(2种)
(6)复用推挽输出(GPIO_Mode_AF_PP) 和 (7)复用开漏输出(GPIO_Mode_AF_OD)
这两种模式下,引脚的控制权从GPIO模块移交给片上外设(如USART、SPI、定时器等),输出驱动方式由外设决定:
- 复用推挽输出:用于USART_TX、SPI_SCK、SPI_MOSI、PWM输出等场景。
- 复用开漏输出:用于I2C_SDA、I2C_SCL等需要总线共享的场景。
2.4 模拟模式(1种)
(8)模拟输入(GPIO_Mode_AIN)
关闭数字电路(施密特触发器、上拉/下拉电阻均被禁用),引脚直接连接至ADC或DAC模拟电路,实现零消耗。
- 适用场景:ADC模拟信号采集、DAC模拟输出。
- 低功耗应用:未使用的引脚应配置为模拟输入模式,可消除施密特触发器带来的额外功耗。
2.5 8种模式速查表
| 模式 | 内部上拉/下拉 | 输出驱动 | 典型应用 |
|---|---|---|---|
| 浮空输入 | 无 | 高阻 | 外部已有驱动的数字信号 |
| 上拉输入 | 40kΩ上拉 | 高阻 | 按键接地检测 |
| 下拉输入 | 40kΩ下拉 | 高阻 | 高电平有效信号 |
| 推挽输出 | 无 | 高低均可 | LED、蜂鸣器 |
| 开漏输出 | 需外部上拉 | 仅低电平 | I2C、电平转换 |
| 复用推挽输出 | 外设控制 | 外设控制 | USART_TX、SPI、PWM |
| 复用开漏输出 | 外设控制 | 外设控制 | I2C_SDA/SCL |
| 模拟输入 | 无 | 高阻 | ADC采集、未用引脚 |
三、GPIO标准库配置详解
3.1 GPIO初始化结构体
标准库使用 GPIO_InitTypeDef 结构体配置引脚:
typedef struct {
uint16_t GPIO_Pin; // 引脚号(可用 | 组合多个)
GPIOSpeed_TypeDef GPIO_Speed; // 输出速率(2/10/50MHz)
GPIOMode_TypeDef GPIO_Mode; // 工作模式(8种之一)
} GPIO_InitTypeDef;
3.2 配置基本流程
- 使能GPIO端口时钟:GPIO挂在APB2总线上,使用
RCC_APB2PeriphClockCmd(); - 填充
GPIO_InitTypeDef结构体:指定引脚、模式和速率; - 调用
GPIO_Init()完成初始化; - 使用
GPIO_SetBits()/GPIO_ResetBits()/GPIO_WriteBit()/GPIO_ReadInputDataBit()等函数操作引脚。
3.3 完整示例:输入、输出、复用、模拟配置
#include "stm32f10x.h"
void GPIO_Config_Demo(void) {
GPIO_InitTypeDef GPIO_InitStructure;
/* 第一步:使能所有要用的GPIO端口时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC, ENABLE);
/* ===== 示例1:按键输入(PA0,上拉输入) ===== */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ===== 示例2:LED输出(PB0,推挽输出,50MHz) ===== */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* ===== 示例3:USART1_TX(PA9,复用推挽输出) ===== */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ===== 示例4:ADC输入(PA1,模拟输入) ===== */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ===== 示例5:I2C1_SDA(PB7,复用开漏输出) ===== */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 复用开漏
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
3.4 引脚操作常用库函数
/* 输出操作 */
GPIO_SetBits(GPIOB, GPIO_Pin_0); // PB0 输出高电平
GPIO_ResetBits(GPIOB, GPIO_Pin_0); // PB0 输出低电平
GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET); // 单独写一位
GPIO_Write(GPIOB, 0x0001); // 写整个端口(低16位有效)
/* 输入操作 */
uint8_t level = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); // 读单个引脚
uint16_t port = GPIO_ReadInputData(GPIOA); // 读整个端口
四、GPIO输出速率与电气特性
4.1 输出速率(GPIO_Speed)
标准库定义了三种速率:GPIO_Speed_2MHz、GPIO_Speed_10MHz、GPIO_Speed_50MHz。速率越高,电平翻转越快,但电磁干扰也越强。
- 2MHz:适用低速控制信号(如继电器、LED静态驱动),EMI最小。
- 10MHz:适用常规数字信号(如片选CS线、普通GPIO通信)。
- 50MHz:适用高速信号(如SPI时钟、PWM高频输出)。
选型建议:在满足功能的前提下,尽量选用较低的速率以降低电磁辐射。
4.2 电气参数
| 参数 | 典型值 | 说明 |
|---|---|---|
| 输入高电平阈值VIH | 2.0V(VDD=3.3V) | 低于此值可能识别为低电平 |
| 输入低电平阈值VIL | 0.8V(VDD=3.3V) | 高于此值可能识别为高电平 |
| 单引脚最大输出电流 | ±25mA | 所有引脚总电流不得超过150mA |
| 输出高电平典型值 | VDD - 0.5V | 3.3V供电时约2.8V |
| 5V容忍 | 所有GPIO均兼容 | 可直接接入5V数字信号 |
五、外设复用功能与AFIO重映射
5.1 什么是端口复用
STM32的一个GPIO引脚可对应多个内部外设功能。当引脚不作为普通I/O口,而是作为某个外设(如USART、SPI、定时器)的功能引脚时,称为端口复用。
例如:PA9的默认功能是GPIO,但可以复用为USART1_TX或定时器1的通道2。
5.2 复用功能的三步配置法
经验法则:当GPIO行为异常时,优先检查三点:1. 时钟使能状态 2. 复用功能映射 3. 输出模式配置。这三类问题占故障率的80%以上。
以USART1_TX(PA9)配置为例:
void USART1_GPIO_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
/* 步骤1:开启GPIO时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* 步骤2:开启USART1外设时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* 步骤3:配置PA9为复用推挽输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // USART1_TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
5.3 什么是重映射
引脚重映射是指将外设功能从默认引脚重新分配到其他指定引脚上,以解决PCB布局冲突或引脚资源紧张的问题。
AFIO(Alternate Function I/O,复用功能IO)是管理重映射的专用外设,拥有三大核心功能:复用功能映射、调试端口配置和外部中断配置。
重映射分为两种模式:
- 部分重映射:保留部分默认引脚,仅将部分功能移到替代引脚。
- 完全重映射:将外设所有功能全部映射到替代引脚。
5.4 重映射标准库配置示例
示例1:USART1从PA9/PA10重映射到PB6/PB7(完全重映射)
void USART1_Remap_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
/* 步骤1:使能GPIOB、USART1和AFIO时钟(重映射必须开启AFIO时钟) */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |
RCC_APB2Periph_USART1 |
RCC_APB2Periph_AFIO, ENABLE);
/* 步骤2:配置PB6(USART1_TX)为复用推挽输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 步骤3:配置PB7(USART1_RX)为上拉输入(避免浮空干扰) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 推荐上拉输入
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 步骤4:执行USART1完全重映射 */
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
}
示例2:禁用JTAG,释放PA15/PB3/PB4为普通GPIO
void JTAG_Disable_ReleasePins(void) {
GPIO_InitTypeDef GPIO_InitStructure;
/* 开启AFIO时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
RCC_APB2Periph_GPIOB |
RCC_APB2Periph_AFIO, ENABLE);
/* 禁用JTAG,保留SWD(SWDIO=PA13, SWCLK=PA14) */
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
/* 此时PA15、PB3、PB4可以作为普通GPIO使用 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
调试端口配置选项说明:
| 库函数宏 | SWD(PA13/PA14) | JTAG(PA15/PB3/PB4) | 释放的GPIO |
|---|---|---|---|
GPIO_Remap_SWJ_NoJTRST | 可用 | PB4释放 | PB4 |
GPIO_Remap_SWJ_JTAGDisable | 可用 | 全部禁用 | PA15, PB3, PB4 |
GPIO_Remap_SWJ_Disable | 不可用 | 全部禁用 | PA13, PA14, PA15, PB3, PB4 |
强烈建议:始终保留SWD功能(PA13/PA14),以便后续调试和程序下载。仅在引脚极度紧缺的情况下才考虑完全禁用。
常用重映射函数对照表:
| 重映射函数调用 | 功能 |
|---|---|
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE) | USART1重映射到PB6/PB7 |
GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE) | USART2重映射到PD5/PD6 |
GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE) | SPI1重映射 |
GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE) | I2C1重映射到PB8/PB9 |
GPIO_PinRemapConfig(GPIO_Remap_TIM3, ENABLE) | TIM3通道部分重映射 |
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE) | 禁用JTAG,保留SWD |
六、硬件设计注意事项
6.1 未使用引脚的处理
未使用的GPIO引脚不应悬空,否则会因电平不确定导致:施密特触发器反复翻转产生额外功耗,甚至引入噪声引起芯片闩锁。
处理方法(按推荐度排序):
- 配置为模拟输入模式:关闭施密特触发器,功耗最低,是低功耗设计的首选。
- 配置为上拉/下拉输入:固定电平。
- 配置为推挽输出:输出固定高或低电平。
- 硬件外接上拉/下拉电阻:直接固定电平。
6.2 输出驱动与限流
- 单个引脚最大输出电流25mA,驱动LED必须串联限流电阻(通常220Ω~1kΩ);
- 所有GPIO引脚的总输出电流不得超过150mA(包括VDD/VDDA电流);
- 驱动大功率负载(继电器、电机)必须使用三极管、MOS管或专用驱动芯片隔离。
6.3 输入电压容限
STM32F103的GPIO引脚均具有5V容忍特性,可安全接入5V数字信号。但输出高电平仍为3.3V电平,驱动5V器件时需确认逻辑阈值是否匹配(多数5V CMOS器件的VIH约为3.5V,存在不兼容风险),必要时需加电平转换电路。
6.4 开漏输出的上拉电阻
I2C等使用开漏输出的场合,必须外接上拉电阻。阻值选择需平衡功耗和上升沿速度:
- 100kHz标准I2C:4.7kΩ
- 400kHz快速I2C:2.2kΩ
- SPI等其他开漏场景:4.7kΩ~10kΩ
七、常见调试问题与排查方法
| 现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 引脚电平读不到变化 | 未使能GPIO时钟 | 检查 RCC_APB2PeriphClockCmd 是否调用 |
| 输出波形为直线 | 模式配置错误(输入模式当作输出用) | 检查 GPIO_Mode 是否为 Out_PP 或 AF_PP |
| 复用功能不工作 | AFIO时钟未开启 | 重映射场景务必调用 RCC_APB2Periph_AFIO 使能 |
| PA15/PB3/PB4不受控制 | JTAG仍占用 | 调用 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE) |
| 低功耗下电流过高 | 未使用引脚悬空 | 将所有未用引脚配置为 GPIO_Mode_AIN 模拟输入 |
| I2C通信失败 | 引脚未配置为开漏 | 将SCL/SDA设置为 GPIO_Mode_AF_OD 并外接上拉电阻 |
八、总结
本文从STM32F103C8T6的引脚全局分类出发,深入解析了GPIO的8种工作模式的内部原理和适用场景,给出了完整的标准库配置代码,并详细讲解了外设复用与AFIO重映射的操作方法。最后,对硬件设计中的关键注意事项和常见故障排查进行了总结。
理解引脚的内部结构与工作模式,是嵌入式开发的基本功。在实际项目中,建议对照数据手册中的引脚定义表逐一核对每个引脚的功能配置,借助逻辑分析仪或示波器验证关键信号,以确保系统稳定可靠。
如有任何疑问或想深入了解特定外设的引脚配置,欢迎在评论区留言交流!
3032

被折叠的 条评论
为什么被折叠?



