简介:面向嵌入式开发者和电子专业学生,这份资源系统梳理了STM32F103RCT6微控制器基于Cortex-M3内核的引脚功能,涵盖GPIO输入输出模式与中断触发、USART/SPI/I2C等复用功能、12位ADC与DAC转换、外部中断输入、内外时钟源选择以及JTAG/SWD调试接口等主要类别,并给出LED状态指示、按键检测、温度采集、串行通信等典型应用场景,可直接用于原理图设计、外设选型与底层驱动开发。资源为单个docx文档,压缩包仅14KB,内容精炼、便于离线查阅。文档按引脚功能分类讲解,同时说明配置要点与寄存器设置思路,部分引脚还给出了复用映射和中断触发方式的说明,对照官方数据手册可快速定位引脚复用关系与初始化流程。已有2462人学习下载,适合初学者快速建立STM32F103RCT6引脚功能全貌,也适合项目开发时随手查阅对照,减少翻手册的时间。
1. STM32F103RCT6 引脚功能文档:为什么每次画板前都要翻一遍
STM32F103RCT6 作为一块基于 ARM Cortex-M3 内核的常用 MCU,很多人第一次拿到它时先找数据手册里的封装图,却忽略了引脚功能文档里那些最容易埋雷的细节——GPIO 默认状态、复用功能(AF)映射、ADC/DAC 通道分配、外部中断引脚、时钟与 JTAG/SWD 调试口占用。这份资源把常用引脚按 GPIO、复用外设、模拟通道、外部中断、时钟和调试接口拆开讲,适合两类人:正在画原理图、要做引脚分配的硬件工程师,以及固件初始化时被复用冲突搞乱顺序的嵌入式开发者。它的价值不在罗列引脚,而在让你画板前先建立一张引脚占用表,避免后期飞线。
2. 引脚资源全景:先分清可配置与不可配置的边界
STM32F103RCT6 的引脚数量决定了它能同时挂载的外设上限。拿到这份文档,第一件事不是看某个引脚能干什么,而是建立「引脚类别」的概念:哪些是纯 GPIO,哪些带 AF 复用,哪些是模拟专用通道,哪些是系统功能引脚。这四类引脚在初始化代码里的处理方式完全不同,混在一起配置是新手最常见的翻车点。
2.1 GPIO 引脚:输入输出、上下拉和中断触发
GPIO 是这份文档里篇幅最多的一类,因为它几乎覆盖了 PA、PB、PC 全部引脚。每个 GPIO 引脚在复位后的默认状态大多是浮空输入,这意味着上电瞬间外部电平没被钳住,直接驱动 LED 或读按键都会得到不确定结果。配置 GPIO 时,需要关注四个维度:模式(输入/输出)、输出类型(推挽/开漏)、速度(2MHz/10MHz/50MHz)和上下拉(上拉/下拉/浮空)。
我在实际项目里习惯先确定引脚方向,再定输出类型。输出控制 LED、继电器这类负载,推挽输出最直接,拉电流和灌电流能力都能用;如果是 I2C 这类需要外部上拉的总线,就必须选开漏输出,否则总线仲裁会被强行拉低。配置代码通常在 GPIO 初始化结构体里一次性完成,但要注意:同时操作多个引脚时,GPIO_Pin 参数可以用按位或合并,例如GPIO_Pin_0 | GPIO_Pin_1,这不会影响其他引脚的已有配置。
中断功能是 GPIO 里最容易绕晕的部分。外部中断 EXTI 的引脚映射不是每个引脚独立对应一个中断号,而是 PA0~PG0 共享 EXTI0 这条线,PA1~PG1 共享 EXTI1,以此类推。如果 PA0 和 PB0 同时开了 EXTI0,中断回调里必须读两个引脚的电平才能区分来源。这份文档中的外部中断章节只讲了触发方式,没强调共享关系,但实际编码时几乎必然踩到。
2.2 外部中断引脚:边沿触发与电平触发的选择依据
外部中断的触发方式直接影响系统响应速度和误触发概率。边沿触发(上升沿/下降沿)适合按键、编码器这类信号跳变明确的场景;电平触发适合需要持续监测电平状态的场景,比如低电平有效的报警信号。配置 EXTI 时,除了 GPIO 初始化,还要调用GPIO_EXTILineConfig把引脚连接到对应的 EXTI 线,这一步漏掉,中断永远不会触发。
上升沿和下降沿同时开启也是常用手段——捕获 PWM 信号的周期时,同一引脚记录上升沿和下降沿的时间戳,相减就是脉宽。但注意,外部中断服务函数里要尽快清标志位,而且不要在中断里做耗时操作,比如把数据写入 Flash。ST 的标准外设库已经封装了EXTI_ClearITPendingBit,顺序是:读状态、清标志、处理逻辑,这个顺序不能反。
另外,不是所有封装引脚都引出了外部中断能力。某些封装上 PA0 和 PA1 可能被 OSC 或调试功能占用,文档里会标注「重映射」字样。这时候要么换引脚,要么用定时器输入捕获代替 EXTI,后者在测量频率时反而更精确。
2.3 时钟引脚与调试接口:默认占用的优先级
时钟引脚包括 OSC_IN、OSC_OUT 和 NRST,它们属于系统级引脚,功能相对固定。OSC_IN/OSC_OUT 用于接外部 8MHz 晶振,如果板子上不想用外部晶振,这两个引脚可以当 GPIO 用,但必须在 RCC 配置里明确关闭 HSE,否则引脚电平被内部偏置电路影响,读到的值不稳定。值得注意的是,PD0 和 PD1 与 OSC_IN/OSC_OUT 复用,默认状态下它们是时钟引脚,不是普通 IO。
JTAG/SWD 调试引脚是另一个隐蔽的占用源。PA13/PA14/PA15 和 PB3/PB4 复位后默认分配给 JTAG/SWD 调试接口,很多人画完板才发现这几个引脚做不了普通 GPIO。解决办法是启用 AFIO 重映射,关闭 JTAG 保留 SWD,或者完全关闭调试口。但后者意味着下次烧录得先用串口 ISP 擦除,非常被动。我的建议是:只要板子还需要调试,就保留 SWD,把 PA13/PA14 留给调试器,其余引脚再分配外设。
3. 复用功能与 ADC/DAC:把引脚功能表变成初始化代码
复用功能(AF)是 STM32F103RCT6 灵活性的核心,也是最容易引发「引脚不够用」焦虑的来源。一个引脚往往能映射到 USART、SPI、I2C、定时器等多个外设,但同一时刻只能选一个功能。文档里的引脚功能表看起来每个引脚都能干很多事,实际设计时却要面对「外设多、引脚少」的取舍问题。
3.1 复用功能 AF 映射:USART/SPI/I2C/定时器的引脚选型
选引脚的第一原则是优先使用外设的默认映射,少用重映射。默认映射意味着芯片内部已经把这些引脚和外设模块接好,只需配置 GPIO 模式为 AF 复用即可;重映射虽然能腾出更多可用引脚,但需要额外开启 AFIO 时钟并调用GPIO_PinRemapConfig,代码量增加,且改板时容易遗漏。
以 USART1 为例,常见默认映射是 TX 在 PA9、RX 在 PA10,这也是串口下载和调试最常用的组合。如果 PA9/PA10 被别的功能占了,可以把 USART1 重映射到 PB6/PB7,但 PB6/PB7 通常又和 I2C1 冲突。这种取舍没有标准答案,只能靠画板前把整张引脚占用表列出来逐个排除。SPI1 的情况类似,默认映射在 PA5/PA6/PA7,重映射到 PB3/PB4/PB5 后就要面对调试口占用问题。
表格是这类资源最有效的表达形式。以下是我在建引脚分配表时常用的记录格式,借鉴了文档中的复用功能章节,补充了方向和外设模块两列:
| 引脚 | 默认功能 | 复用功能 | 使用方向 | 所属外设 | 备注 |
|---|---|---|---|---|---|
| PA9 | GPIO | USART1_TX | 输出 | USART1 | 默认映射 |
| PA10 | GPIO | USART1_RX | 输入 | USART1 | 默认映射 |
| PA5 | GPIO | SPI1_SCK | 输出 | SPI1 | 注意和 LED 冲突 |
| PB6 | GPIO | I2C1_SCL / USART1_TX | 双向 | I2C1 | 开漏 + 上拉 |
| PC3 | GPIO | ADC123_IN13 | 模拟输入 | ADC1 | 采样通道 |
3.2 ADC 与 DAC:12 位分辨率下的通道分配顺序
ADC 引脚的分配顺序直接影响采样稳定性和代码复杂度。STM32F103RCT6 的 ADC 是 12 位逐次逼近型,多个 ADC 共用同一组输入通道,但规则组和注入组可以并行采样。文档中提到可以连接模拟传感器读取电压,实际落地时要注意:ADC 引脚对应的 GPIO 模式必须设为模拟输入,不能设置上下拉,否则内部电阻会改变采样电压,尤其是接高阻抗传感器时误差会被放大。
通道分配还有个容易被忽略的点:相邻引脚的数字噪声。如果 ADC 引脚旁边刚好是 PWM 输出引脚,采样值可能会周期性跳动。解决办法是采样时间尽量拉长,并且在 PCB 布局上把模拟地和数字地在 ADC 引脚附近单点汇接。DAC 引脚数量在这个封装里有限,波形输出场景用得不多,但如果要用,注意输出驱动能力较弱,需要外部运放缓冲才能驱动低阻抗负载。
另一个实际问题是 ADC 的参考电压。内部 VREFINT 通道可以用来校准,但如果你把 VREF+ 接到了外部基准源,初始化时就要把对应 GPIO 配置成模拟输入,而不是让它悬空。这份资源没有展开讲校准流程,但实际产品里温度漂移的影响必须考虑。
3.3 最小初始化配置:以 PA9/PA10 复用 USART1 为例
以下代码是我在某个跨平台系统项目里反复用过的 USART1 初始化片段,展示了 GPIO 配置和复用功能的配合方式:
void USART1_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; // 开启 GPIOA 时钟和 AFIO 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); // 配置 PA9 为 USART1_TX 复用推挽输出 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); // 配置 PA10 为 USART1_RX 浮空输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); }这段代码的关键在GPIO_Mode_AF_PP,它告诉芯片这不是普通推挽输出,而是把引脚交给 USART1 的外设模块接管。TX 引脚必须设为复用推挽,RX 引脚保持浮空输入,不需要上下拉——串口对端的电平会决定总线状态。GPIO_Speed_50MHz在这里不是传输速度,而是 GPIO 引脚的翻转速率上限,USART 波特率在 115200 时 2MHz 也够用,但保持 50MHz 能兼容后续扩展。注意:如果开启了重映射,比如把 USART1 挪到 PB6/PB7,这里还要额外调用GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE),我在调试时经常忘记这一步,导致串口完全无输出。
4. 引脚配置避坑指南:五个重复踩到的占用冲突
4.1 现象:JTAG 关闭后程序下载失败
之前调试一块板子,固件里为了省出 PA15 和 PB3 做 GPIO,直接调用了GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE),把整个调试口全关了。结果程序跑飞后想重新烧录,调试器连接不上,只能飞线 BOOT0 拉高走串口 ISP 才能恢复。
原因:关闭 SWJ 相当于把 PA13/PA14/PA15 全部释放给 GPIO,调试器失去了握手通道。解决:保留 SWD 口,只关 JTAG。正确写法是GPIO_Remap_SWJ_JTAGDisable,这样 PA15、PB3、PB4 可以当 GPIO,但 PA13/PA14 仍然是 SWD 引脚。从那以后我每次配置调试口之前,一定会确认是否保留了 SWD 通道。
4.2 现象:USART 发送正常但接收乱码
某次外接 GPS 模块,TX 接 PA10 后收到的全是乱码。查了一遍波特率、校验位都没问题,最后发现是 PA10 被配置成了复用推挽输出,而不是浮空输入。
原因:RX 引脚方向错误。USART 接收端是芯片输入方向,配置成推挽输出后会干扰对端驱动电平。解决:RX 引脚设为GPIO_Mode_IN_FLOATING或带上拉输入,TX 引脚才用复用推挽。这个错误在刚接触 STM32 时很容易犯,因为数据手册里的引脚定义表看起来 TX/RX 都是「复用」状态,但同一页右下角的小字注明了方向。
4.3 现象:ADC 采样值整体偏高且跳动
采集电位器电压时,未旋动电位器,采样值却在 200 和 800 之间大幅波动。检查接线没问题,后来才发现 ADC 引脚没有设置成模拟输入模式。
原因:GPIO 配置成浮空输入时,内部施密特触发器仍然激活,数字噪声会耦合进模拟通道。解决:把 ADC 对应引脚设置为GPIO_Mode_AIN,此时模拟开关接通、数字输入通路断开,采样稳定性明显改善。同一条经验也适用于 DAC 输出引脚,输出模式固定后不能复用作数字 IO。
4.4 现象:外部中断反复触发,按键像抽风一样
按键接到 PA0,配置了下降沿触发,但按键按下一次,中断服务函数里计数却增加了好几倍。检查硬件没有抖动问题,后来发现是 EXTI 线映射重复了——PA0 和 PB0 都属于 EXTI0,代码里两个引脚都开了 EXTI0 中断线。
原因:EXTI 线 0~15 对应的是 PAx~PGx 的同一个引脚号,不是每个引脚独立中断。PA0 和 PB0 同时使能 EXTI0,中断标志被两个来源共享。解决:在产品设计阶段就避免同一 EXTI 线上挂多个引脚。如果确实要接多个按键,分散到 EXTI0、EXTI1、EXTI2 等不同线上,或者干脆用定时器轮询。
4.5 现象:VCC 对地短路,芯片发烫
这是硬件问题,但根源在引脚配置。GPIO 输出模式选成了推挽,同时外部电路又强行拉低该引脚,形成大电流灌入。
原因:推挽输出模式下,引脚要么强拉高、要么强拉低,和外部电路的电平逻辑冲突时会直接短路。解决:凡是驱动外部有源器件、总线这类不确定电平的引脚,优先用开漏输出配合外部上拉。开漏输出只能下拉,电平由外部上拉电阻决定,天然避免了对顶冲突。类似问题在配置 LED 驱动时也可能出现,但 LED 是纯电阻负载,推挽没问题。
5. 从文档到工程:画板前用引脚功能表做一轮自检
很多人拿到这份引脚功能文档,是等原理图画到一半时才翻出来临时查某个引脚能不能用。但更高效的做法是把文档当成设计输入的一部分,在原理图绘制之前就完成引脚级分配,并让硬件和固件开发共用同一张表。这样能避免画板时发现引脚不够、不得不飞线改网络的被动局面。
5.1 先建一张引脚分配表:把功能需求映射到具体引脚
引脚分配表的建立步骤不复杂,但需要把需求列全。第一步,列出所有外设模块:几个 USART、几路 ADC、有没有 SPI Flash、I2C 传感器、PWM 输出通道。第二步,对照文档中的引脚映射表,给每个外设选默认映射引脚,并标记方向。第三步,检查冲突,把重复分配的引脚挑出来,优先保那些不可替代的功能,比如晶振引脚、调试口、启动配置引脚。
我在某个工业控制板项目里用的是下面这张模板,后来也共享给做底层驱动的同事:
| 外设功能 | 首选引脚 | 备选引脚 | 方向 | 配置模式 | 状态 |
|---|---|---|---|---|---|
| USART1_TX | PA9 | PB6 | 输出 | 复用推挽 | 已占用 |
| USART1_RX | PA10 | PB7 | 输入 | 浮空输入 | 已占用 |
| ADC1_IN0 | PA0 | — | 模拟输入 | 模拟输入 | 已占用 |
| 按键扫描 | PA2 | PA3 | 输入 | 上拉输入 | 可选 |
| LED 指示 | PC13 | PC14 | 输出 | 推挽输出 | 可选 |
这张表的另一层价值,是让硬件工程师在画封装时就知道哪个引脚附近要留滤波电容、哪个引脚要串电阻。比如 ADC 通道的引脚,走线要避开 PWM 输出线;USART 的 TX/RX 之间不需要特殊处理,但差分信号或高速 SPI 就要考虑等长。固件开发者拿到这张表后,可以直接生成 GPIO 初始化结构体,不用再去翻手册核对每个引脚的功能。
5.2 启动配置与下载接口:画板时最容易忽略的固定区域
启动引脚 BOOT0 和 BOOT1 不属于 GPIO,但它们的电平状态决定了芯片上电后从哪里执行代码。常见做法是 BOOT0 通过 10kΩ 电阻下拉到 GND,BOOT1 同样下拉,这样正常上电从主闪存启动。如果板子需要支持串口下载,BOOT0 要引出跳线或焊盘,方便拉高进入系统存储器启动模式。这个引脚不需要固件配置,但原理图上少了它,调试时就没法快速恢复。
下载接口区域同样需要提前规划。哪怕最终产品不用调试器,开发阶段也建议预留 4 针的 SWD 接口:SWDIO、SWCLK、GND、VCC。它只占 4 个引脚,却能省去上百次拔插 USB 转串口的麻烦。PA13/PA14 这两个引脚无论有没有调试器,优先保持默认调试功能,直到固件开发完全结束再考虑释放。
VCAP 引脚是文档里容易漏掉但必须接电容的引脚。它连接内部稳压器输出,需要外接一个 1μF 左右的陶瓷电容到地,容值过小或 ESR 过大,芯片可能在启动时复位。我的经验是,每个 VCAP 引脚旁边放一个 1μF 的 0402 电容,离引脚越近越好,这在 PCB 布局时就要提前留出位置。
5.3 复查迭代:把引脚功能表和实际 PCB 网络对照
画完原理图、导完网表之后,最后一轮检查一定不能省。至少核对三处:一是所有复用引脚是否都切到了目标外设,比如 SPI 的 NSS 引脚如果不需要硬件片选,要配置为 GPIO 或禁用,否则 SPI 通信会因为片选电平不对而超时;二是中断引脚是否避开了调试口,特别是 PA15/PB3/PB4 这几个;三是电源和地引脚的滤波电容是否都到位,每个 VDD 引脚配一个 100nF 电容,不要图省事只放一个总电容。
我一般会打印一份引脚功能文档里的引脚图,然后拿一支笔,在原理图上逐个勾掉已经分配的引脚。这个过程看似原始,但比任何软件检查都直观。等到 PCB 回来、焊好第一块板,先用 SWD 连接、读芯片 ID,确认调试通再上电跑代码——这一步能筛掉大部分焊接短路问题。
6. 一个验证技巧:用外部中断回调拆解引脚配置是否真生效
每次写完 GPIO 初始化代码,我并不会急着跑完整业务逻辑,而是用一个最小化的外部中断测试来验证引脚配置是否和预期一致。这个方法特别适合确认复用功能和中断映射是否正确,能快速定位是硬件问题还是代码问题。
测试思路很简单:选一个配置为外部中断输入的引脚,用手直接触碰它(或者用杜邦线短接到 VCC/GND),观察中断回调里是否捕获到跳变。如果配置正确,触碰瞬间就能触发回调;如果没有任何反应,先排查 GPIO 模式是否设成了复用而非普通输入,再检查中断通道使能和 NVIC 配置。下面这段代码是我在某个模拟项目 X 里用的 EXTI 验证模板:
void EXTI0_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line0) != RESET) { // 记录中断触发次数,同时点亮一个 LED 做指示 trigger_count++; GPIO_SetBits(GPIOC, GPIO_Pin_13); EXTI_ClearITPendingBit(EXTI_Line0); } }这段中断服务函数本身不复杂,但有两个细节值得留意。第一,trigger_count是全局变量,查看它时要加volatile修饰,否则编译器优化可能让 main 函数里的循环读不到更新后的值。第二,GPIO_SetBits 放在中断里只是为了快速验证,实际产品代码里 LED 开关最好放在主循环处理,中断里只置标志位。用这个测试确认引脚配置生效后,再注释掉测试代码,切换成真正的业务处理逻辑。
另一次在调试某图像处理 Demo 时,我用同样的方法排查了一路 PWM 输出的问题。那次不是外部中断,而是定时器通道输出,但验证思路一致:把引脚配置代码拆出来单独测,而不是在大循环里盲目加打印信息。从那以后,每次更换引脚分配或者调整外设映射,我都会在功能开发前跑一遍这类最小验证,确认引脚级别的行为正确再继续往下写逻辑,希望帮到你。
本文还有配套的精品资源,点击获取