端口复用
🧩什么是端口复用?
端口复用是指一个 GPIO 引脚既可以作为通用 I/O,也可以作为外设功能引脚(如 USART、SPI、TIM)的功能引脚,通过配置该引脚的工作模式来“复用”为外设的信号输入/输出。
STM32F103 管脚图(LQFP64 & LQFP144)展示了哪些引脚支持功能复用和重映射:
举例:
PA9
默认是 GPIO,但也可以作为USART1_TX
;
PA10
默认是 GPIO,也可以作为USART1_RX
;
当我们通过 GPIO_Init()
把这两个引脚配置为 复用推挽输出 / 浮空输入,并启用 USART 时,它们就不再是普通 GPIO,而是串口引脚 —— 这就是端口复用。
配置步骤(以 USART1 为例):
// 1. 使能 GPIO 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 2. 使能 USART1 外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 3. 配置 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. 配置 RX(PA10)为浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
端口重映射
🧩 什么是端口重映射(Remap)?
端口重映射 是指将一个外设的 I/O 引脚从默认位置映射到其他 GPIO 引脚上,从而 灵活调整引脚布局、减少 PCB 板布线冲突。
每个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在STM32中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。
为了使不同器件封装的外设IO功能数量达到最优,可以把一些复用功能重新映射到其他一些引脚上。STM32中有很多内置外设的输入输出引脚都具有重映射(remap)的功能。
参考官方手册:《STM32中文参考手册V10》的P116页“8.3复用功能和调试配置”
USART1 默认与重映射对照表:
数据手册引脚描述:
部分重映射 & 完全重映射
部分重映射:功能外设的部分引脚重新映射,还有一部分引脚是原来的默认引脚。
完全重映射:功能外设的所有引脚都重新映射。
部分重映射 重映射部分 I/O(如 USART3 的 TX/RX),其余保持默认
完全重映射 所有相关引脚都被重映射到新的位置
示例:USART3 重映射情况(来自表格):
USART3_REMAP[1:0] | TX | RX | CK | CTS RTS |
---|---|---|---|---|
00 (默认) |
PB10 | PB11 | PB12 | PB13 |
01 (部分) |
PC10 | PC11 | PC12 | - |
11 (完全) |
PD8 | PD9 | PD10 | PD11 |
举例:
默认:
USART1_TX
在PA9
,USART1_RX
在PA10
;
重映射后: 可以改为PB6
和PB7
;
这个由 AFIO(Alternate Function I/O)模块 通过寄存器控制。
以下代码为引脚重映射配置过程(串口1为例):
使能GPIO时钟(重映射后的IO);
使能功能外设时钟(例如串口1);
使能AFIO时钟。重映射必须使能AFIO时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
开启重映射。
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
根据第一个参数,来确定是部分重映射还是全部重映射
// 配置步骤(以 USART1 重映射为例):
// 1. 使能重映射目标引脚的 GPIO 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 2. 使能 USART1 外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 3. 使能 AFIO 时钟(必须)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// 4. 启用 USART1 重映射
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
// 5. 配置新引脚 PB6 和 PB7
// TX - PB6
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);
// RX - PB7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
🧩相关寄存器(重映射控制)
哪些情况需要开启AFIO辅助功能时钟?
对寄存器AFIO_MAPR,AFIO_EXTICRX和AFIO_EVCR进行读写操作前,应当首先打开AFIO时钟。
寄存器 | 作用说明 |
---|---|
AFIO_MAPR |
控制端口的重映射(USARTx、TIMx等) |
AFIO_EXTICR |
控制外部中断线 EXTI 的 GPIO 映射 |
AFIO_EVCR |
控制 EVENTOUT 事件输出端口 |
🧩端口复用与重映射的对比
项目 | 端口复用 | 端口重映射 |
---|---|---|
本质区别 | GPIO 改为外设功能引脚 | 外设功能引脚从一个 GPIO 映射到另一个 |
控制方式 | 配置 GPIO 模式 | 配置 AFIO_MAPR 寄存器 |
是否需要 AFIO | 否 | 是,必须开启 RCC_APB2Periph_AFIO |
应用场景 | 各外设首次初始化 | 当默认引脚冲突,需重新布局时使用 |
示例 | PA9/PA10 → USART1_TX/RX |
PB6/PB7 → USART1_TX/RX (重映射) |
一些重映射的常见应用场景:
应用场景示例 | 原因 |
---|---|
外设引脚冲突 | 多个外设默认用同一组引脚 |
PCB 布线更合理 | 避免交叉布线、简化走线 |
灵活使用多串口/多个定时器 | 通过重映射让它们共存 |
外部中断 EXTI 线冲突需另换引脚 | 使用 AFIO_EXTICR 重映射中断线 |
简单点说,端口复用就是把 GPIO 引脚配置为外设引脚(模式配置);端口重映射是把外设引脚从默认位置换到其他引脚(AFIO 配置)。
以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!