【解析】GD32引脚复用:从JTAG到GPIO的PB3、PB4重映射实战

张开发
2026/4/18 23:26:02 15 分钟阅读

分享文章

【解析】GD32引脚复用:从JTAG到GPIO的PB3、PB4重映射实战
1. 为什么PB3和PB4引脚不听话最近在用GD32F103做项目时遇到了一个奇怪的问题PB4引脚设置为推挽输出后电压始终只有0.9V完全达不到预期的3.3V。查了半天电路也没发现问题最后才发现原来是JTAG功能在捣鬼。很多新手都会遇到类似的情况明明代码配置正确硬件连接也没问题但PB3、PB4就是无法正常作为GPIO使用。这其实是因为GD32微控制器在设计时默认将PB3(JTDO)、PB4(JNTRST)分配给JTAG调试接口使用了。就像你家客厅的插座虽然看起来是普通插座但实际上已经被预留给空调专用电路了插其他电器自然不好使。JTAG是芯片调试的重要接口包含以下信号线PB3JTDOJTAG数据输出PB4JNTRSTJTAG复位PA13JTMSJTAG模式选择PA14JTCKJTAG时钟PA15JTDIJTAG数据输入当我们需要把这些引脚当作普通GPIO使用时就必须先解除它们的JTAG功能。这个过程专业术语叫做引脚重映射就像给房间重新布线把原本给空调的电路改造成普通插座。2. 深入理解GD32的重映射机制2.1 AFIO时钟是关键钥匙在开始重映射之前有个重要步骤经常被忽略——开启AFIO时钟。AFIO(Alternate Function I/O)是GD32中管理引脚复用功能的模块就像小区的物业管理中心负责协调各个功能区域的使用权。rcu_periph_clock_enable(RCU_AF); // 必须首先开启AFIO时钟如果不执行这行代码后续所有重映射操作都会无效。我曾经在一个项目中浪费了半天时间排查最后发现就是这个简单的时钟使能语句被注释掉了。2.2 三种重映射模式详解GD32提供了三种不同的JTAG重映射配置就像给你三种改造方案部分释放模式GPIO_SWJ_SWDPENABLE_REMAPgpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);效果禁用JTAG-DP保留SW-DP释放引脚PB3、PB4、PA15保留功能PA13、PA14仍可用于SWD调试适用场景最常用的模式既释放了引脚又保留了SWD调试能力最小释放模式GPIO_SWJ_NONJTRST_REMAPgpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE);效果仅释放PB4(JNTRST)保留功能其他JTAG引脚保持原功能适用场景只需要PB4作为GPIO的特殊情况完全禁用模式GPIO_SWJ_DISABLE_REMAPgpio_pin_remap_config(GPIO_SWJ_DISABLE_REMAP, ENABLE);效果完全禁用JTAG和SWD释放引脚PB3、PB4、PA13、PA14、PA15风险禁用后将无法通过SWD/JTAG调试适用场景对引脚资源极度敏感且不需要调试的场景3. 完整配置实战步骤3.1 硬件准备检查清单在开始编程前建议先检查这些硬件细节开发板型号是否与代码匹配如GD32F103C8T6PB3/PB4引脚是否未被其他外设占用测量引脚电压确认当前状态确保调试器连接正常特别是使用SWD模式时3.2 逐步配置代码示例下面是一个完整的配置示例将PB3、PB4配置为推挽输出#include gd32f10x.h void gpio_config(void) { // 1. 开启GPIO和AFIO时钟 rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_AF); // 2. 重映射配置保留SWD调试能力 gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE); // 3. 配置PB3、PB4为推挽输出 gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3 | GPIO_PIN_4); // 4. 初始电平设置 GPIO_BOP(GPIOB) GPIO_PIN_3 | GPIO_PIN_4; // 初始高电平 }3.3 常见问题排查指南遇到问题时可以按照这个流程排查测量电压法未重映射时PB3/PB4电压约为0.9V内部弱上拉成功重映射后应能正常输出0V/3.3V调试器连接检查如果使用GPIO_SWJ_SWDPENABLE_REMAP模式SWD调试应仍可用如果调试器无法连接检查是否误用了GPIO_SWJ_DISABLE_REMAP代码执行顺序验证确保重映射配置在GPIO初始化之前检查所有相关时钟是否使能寄存器级诊断查看AFIO_MAPR寄存器值printf(AFIO_MAPR: 0x%08X\n, AFIO_MAPR);期望值使用GPIO_SWJ_SWDPENABLE_REMAP时应为0x020000004. 进阶技巧与注意事项4.1 多外设复用的协调管理当PB3/PB4需要用作其他外设功能时如SPI、I2C配置顺序尤为关键。建议采用以下流程先使能AFIO时钟配置JTAG重映射使能目标外设时钟配置GPIO为复用功能模式初始化外设例如配置SPI1使用PB3(SCK)、PB4(MISO)// 1. 时钟使能 rcu_periph_clock_enable(RCU_AF); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_SPI1); // 2. JTAG重映射 gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE); // 3. GPIO配置 gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3); // SCK gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4); // MISO // 4. SPI初始化 spi_parameter_struct spi_init_struct; spi_struct_para_init(spi_init_struct); spi_init_struct.device_mode SPI_MASTER; // ...其他SPI参数配置 spi_init(SPI1, spi_init_struct);4.2 低功耗模式下的特殊处理在低功耗应用中需要注意进入休眠前确保JTAG重映射状态与唤醒后一致某些低功耗模式下AFIO时钟可能被关闭唤醒后需要重新配置测量引脚漏电流时要考虑JTAG内部上拉的影响4.3 跨型号兼容性考虑不同GD32系列的重映射功能略有差异GD32F10x系列支持本文介绍的所有模式GD32E23x系列重映射寄存器位置可能不同GD32VF103系列需使用RISC-V特有的配置方式建议在移植代码时查阅对应型号的参考手册检查寄存器映射表使用宏定义实现条件编译#if defined(GD32F10x) #include gd32f10x.h #define REMAP_FUNC GPIO_SWJ_SWDPENABLE_REMAP #elif defined(GD32E23x) #include gd32e23x.h #define REMAP_FUNC GPIO_SWJ_SWDPENABLE_REMAP_E23x #endif void remap_config(void) { gpio_pin_remap_config(REMAP_FUNC, ENABLE); }在实际项目中我遇到过GD32F103到GD32E230的移植发现重映射寄存器的偏移地址变了最后通过对比参考手册才解决了问题。这也提醒我们引脚复用配置一定要以当前使用的芯片手册为准。

更多文章