GD32单片机开发实战:从STM32/CubeMX 迁移到快速上手

📅 2026/8/4 12:06:00 👁️ 阅读次数 📝 编程学习
GD32单片机开发实战:从STM32/CubeMX 迁移到快速上手

目标读者:熟悉 STM32 + CubeMX 开发,想快速切换到国产 GD32 单片机的嵌入式工程师。
本文覆盖:开发环境搭建、标准库工程创建、代码生成工具对比、GPIO/定时器/串口实战、STM32→GD32 迁移要点。


一、GD32 是什么?为什么要切?

1.1 GD32 定位

GD32 是北京**兆易创新(GigaDevice)**推出的 32 位通用 MCU,基于 ARM Cortex-M0/M3/M4/M23/M33/RISC-V 内核。常见系列:

系列内核主频特点对标 STM32
GD32F10xCortex-M3108MHz经典入门,Flash 零等待STM32F103
GD32F30xCortex-M4120MHz带 FPU,性能更高STM32F103 升级版
GD32F4xxCortex-M4240MHz高性能,USB/CAN/以太网STM32F4xx
GD32E23xCortex-M2372MHz低功耗,安全STM32G0/U0
GD32H7xxCortex-M7600MHz超高性能STM32H7

1.2 从 STM32 迁移到 GD32 的核心优势

  • Pin-to-Pin 兼容:GD32F10x/F30x 系列可直接替换同封装的 STM32F103。
  • 性价比更高:同规格通常价格更低,供货更稳定。
  • 开发工具链一致:Keil、IAR、VSCode + GCC 都能用,ST-Link/J-Link 也能烧录。
  • 标准库 API 接近 STM32 SPL:函数命名和结构高度相似,学习成本低。

二、开发方式选择:CubeMX 情怀 vs GD32 现实

2.1 GD32 有没有类似 CubeMX 的工具?

工具厂商说明
STM32CubeMXST仅支持 STM32,但可生成 HAL/LL 代码
GD32 Embedded BuilderGigaDevice官方图形化 IDE,可生成 HAL 库工程,支持部分型号
AT32 Work Bench雅特力国产替代方案,但仅用于 AT32

结论:GD32 没有完美对标 CubeMX 的全系列工具。推荐两条路线:

  1. 快速路线(推荐):用GD32 Embedded Builder生成初始化代码 + HAL 库,再基于 HAL 写业务逻辑。
  2. 标准库路线(最稳):手动搭 Keil 工程,使用GD32 标准外设库(SPL),和 STM32 标准库开发体验最接近。
  3. 偷懒路线:GD32F10x/F30x 可以直接烧 STM32CubeMX 生成的 HAL 工程,只需改少量差异点(见第七节)。

三、环境准备

3.1 必备软件与资料

  1. Keil MDK-ARM 5.30+(建议 5.38 或更新)
  2. GD32 Device Family Pack(DFP):Keil 识别芯片用
  3. GD32 Firmware Library:标准外设库 + CMSIS + 启动文件
  4. GD32 Embedded Builder(可选,图形化配置)
  5. 调试器:J-Link、ST-Link、DAP-Link、GD-Link 均可

3.2 资料下载地址

  • 兆易创新官网:https://www.gd32mcu.com/cn/download/7
  • 搜索对应型号,例如GD32F30x_Firmware_LibraryGigaDevice.GD32F30x_DFP.x.x.x.pack

3.3 安装 Keil DFP 包

  1. 双击下载的.pack文件。
  2. 自动识别 Keil 路径,一路 Next。
  3. 打开 Keil → File → Device Database,确认能看到 GigaDevice 系列。

四、标准库工程创建:从零到 LED 闪烁

GD32F303CCT6为例(Cortex-M4,120MHz,256KB Flash,48KB SRAM),这是最常见的入门型号之一。

4.1 创建工程目录

GD32F303_LED_Demo/ ├── CMSIS/ # 内核文件 + 启动文件 + system_xxx.c ├── FWLIB/ # 标准外设库 .c/.h ├── User/ # main.c、gd32f30x_it.c、用户驱动 └── Project/ # Keil 工程文件

4.2 拷贝官方库文件

GD32F30x_Firmware_Library_V2.1.x/中复制:

CMSIS 目录:

Firmware/CMSIS/GD/GD32F30x/Include/*.h Firmware/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c Firmware/CMSIS/GD/GD32F30x/Source/ARM/startup_gd32f30x_hd.s (根据容量选择)

容量与启动文件对应关系:

容量类型Flash 大小启动文件
XD≤64KBstartup_gd32f30x_xd.s
CL128~256KBstartup_gd32f30x_cl.s
HD≥512KBstartup_gd32f30x_hd.s

GD32F303CCT6 是 256KB Flash,选_cl.s

FWLIB 目录:

Firmware/GD32F30x_standard_peripheral/Include/*.h Firmware/GD32F30x_standard_peripheral/Source/*.c

User 目录:

Firmware/Template/Keil5_project/gd32f30x_it.c Firmware/Template/Keil5_project/gd32f30x_it.h Firmware/Template/Keil5_project/main.c

4.3 Keil 中创建工程

  1. Project → New μVision Project,保存到Project/目录。
  2. 选择芯片:GigaDevice → GD32F303 → GD32F303CCT6
  3. 弹出的Manage Run-Time Environment直接点OK(我们手动添加库)。
  4. 点击Manage Project Items(品字形图标),添加分组:
    • CMSIS:添加system_gd32f30x.c和对应启动文件.s
    • FWLIB:添加所有gd32f30x_xxx.c
    • User:添加main.cgd32f30x_it.c

4.4 工程配置

打开Options for Target → Target

  • IROM1:起始0x08000000,大小按芯片填写(如 0x40000 = 256KB)
  • IRAM1:起始0x20000000,大小按芯片填写(如 0xC000 = 48KB)

C/C++ 选项卡:

添加 Include Paths:

../CMSIS ../FWLIB/Include ../User

添加全局宏定义:

GD32F30X_CL USE_STDPERIPH_DRIVER

注意:不同容量芯片宏定义不同:GD32F30X_XDGD32F30X_CLGD32F30X_HD

Debug 选项卡:

选择你的调试器(如 J-Link / ST-Link / CMSIS-DAP),设置 SWD 接口,Flash Download 中添加对应芯片的 Flash 算法。

4.5 编写 LED 闪烁代码

假设 LED 接在PA0(低电平点亮):

// main.c#include"gd32f30x.h"voidgpio_config(void){rcu_periph_clock_enable(RCU_GPIOA);gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_0);}voiddelay_ms(uint32_tms){for(uint32_ti=0;i<ms;i++){for(uint32_tj=0;j<6000;j++);// 粗略延时,120MHz 下约 1ms}}intmain(void){gpio_config();while(1){gpio_bit_reset(GPIOA,GPIO_PIN_0);// LED 亮delay_ms(500);gpio_bit_set(GPIOA,GPIO_PIN_0);// LED 灭delay_ms(500);}}

编译、下载、复位,LED 闪烁成功!


五、SysTick 精准延时(替代 CubeMX 生成的 HAL_Delay)

CubeMX 会自动生成HAL_Delay(),GD32 标准库没有现成函数,需要自己写。

// systick.c#include"systick.h"volatilestaticuint32_tdelay_fac_us=0;volatilestaticuint32_tdelay_fac_ms=0;voidsystick_config(void){// 选择 HCLK 作为 SysTick 时钟源(不分频)systick_clksource_set(SYSTICK_CLKSOURCE_HCLK);delay_fac_us=SystemCoreClock/1000000U;delay_fac_ms=SystemCoreClock/1000U;}voiddelay_us(uint32_tus){uint32_ttemp;SysTick->LOAD=us*delay_fac_us;SysTick->VAL=0;SysTick->CTRL=SysTick_CTRL_ENABLE_Msk|SysTick_CTRL_CLKSOURCE_Msk;do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;SysTick->VAL=0;}voiddelay_ms(uint32_tms){while(ms--){delay_us(1000);}}

然后在main()开头调用systick_config(),之后用delay_ms(500)替代之前的粗略延时。


六、常用外设实战

6.1 GPIO 输入(按键检测)

voidkey_config(void){rcu_periph_clock_enable(RCU_GPIOA);gpio_init(GPIOA,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,GPIO_PIN_1);}uint8_tkey_pressed(void){if(RESET==gpio_input_bit_get(GPIOA,GPIO_PIN_1)){delay_ms(10);// 消抖if(RESET==gpio_input_bit_get(GPIOA,GPIO_PIN_1)){return1;}}return0;}

6.2 USART 串口打印

以 USART0(PA9/PA10)为例:

voidusart_config(void){rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_USART0);gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9);gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_10);usart_baudrate_set(USART0,115200);usart_word_length_set(USART0,USART_WL_8BIT);usart_stop_bit_set(USART0,USART_STB_1BIT);usart_parity_config(USART0,USART_PM_NONE);usart_hardware_flow_rts_config(USART0,USART_RTS_DISABLE);usart_hardware_flow_cts_config(USART0,USART_CTS_DISABLE);usart_receive_config(USART0,USART_RECEIVE_ENABLE);usart_transmit_config(USART0,USART_TRANSMIT_ENABLE);usart_enable(USART0);}voidusart_send_char(uint8_tch){usart_data_transmit(USART0,ch);while(usart_flag_get(USART0,USART_FLAG_TBE)==RESET);}voidusart_send_string(char*str){while(*str){usart_send_char(*str++);}}

对比 STM32 标准库:

操作STM32 SPLGD32 SPL
使能时钟RCC_APB2PeriphClockCmdrcu_periph_clock_enable
GPIO 初始化GPIO_Initgpio_init
设置引脚高电平GPIO_SetBitsgpio_bit_set
串口发送USART_SendDatausart_data_transmit

6.3 定时器 PWM(呼吸灯)

以 TIMER0 通道 0(PA8)为例:

voidtimer_pwm_config(void){rcu_periph_clock_enable(RCU_GPIOA);rcu_periph_clock_enable(RCU_TIMER0);rcu_periph_clock_enable(RCU_AF);gpio_init(GPIOA,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_8);timer_parameter_struct timer_initpara;timer_oc_parameter_struct timer_ocinitpara;timer_deinit(TIMER0);timer_initpara.prescaler=119;// 120MHz / 120 = 1MHztimer_initpara.alignedmode=TIMER_COUNTER_EDGE;timer_initpara.counterdirection=TIMER_COUNTER_UP;timer_initpara.period=999;// 1kHz PWMtimer_initpara.clockdivision=TIMER_CKDIV_DIV1;timer_init(TIMER0,&timer_initpara);timer_ocinitpara.outputstate=TIMER_CCX_ENABLE;timer_ocinitpara.ocpolarity=TIMER_OC_POLARITY_HIGH;timer_ocinitpara.ocidlestate=TIMER_OC_IDLE_STATE_LOW;timer_channel_output_config(TIMER0,TIMER_CH_0,&timer_ocinitpara);timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,500);timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);timer_primary_output_config(TIMER0,ENABLE);timer_enable(TIMER0);}

七、从 STM32 迁移到 GD32 的关键注意点

7.1 可以直接烧 STM32 程序的型号

以下型号寄存器地址和 STM32F103 基本兼容,理论上可直接烧录:

  • GD32F10x 系列
  • GD32F30x 系列
  • GD32E103 系列

7.2 必须修改的几个点

1)晶振启动超时

如果程序卡在时钟初始化,修改 HSE 启动超时:

// STM32#defineHSE_STARTUP_TIMEOUT((uint16_t)0x0500)// GD32 建议#defineHSE_STARTUP_TIMEOUT((uint16_t)0xFFFF)
2)Flash 容量选择

GD32 的 Flash 划分和 STM32 不同,需确认启动文件和 Linker 配置。

3)ADC/DAC 精度与时序

GD32 部分型号 ADC 采样时间默认值不同,需根据数据手册调整。

4)USB 外设

GD32F103 的 USB 与 STM32F103 不完全一致,移植 USB 时需要专门适配。

7.3 使用 CubeMX 生成 HAL 代码再改

如果你离不开 CubeMX:

  1. 选择同封装、同资源的 STM32 型号(如 STM32F103C8T6)。
  2. 用 CubeMX 生成 HAL 工程。
  3. 将芯片型号替换为 GD32F303CCT6。
  4. 修改时钟宏、HSE 超时、Flash 算法。
  5. 重新编译下载。

但推荐长期使用 GD32 时,还是用标准库或 Embedded Builder,避免隐藏兼容性问题。


八、GD32 Embedded Builder 图形化开发(替代 CubeMX 方案)

8.1 下载与安装

官网下载GD32 Embedded Builder,解压即可使用,无需安装。

8.2 创建工程

  1. 打开 Embedded Builder。
  2. File → New → GD Project。
  3. 输入工程名,选择芯片型号。
  4. 配置引脚、时钟、外设。
  5. 点击生成代码,生成 HAL 库工程。

8.3 优缺点

优点缺点
图形化配置,类似 CubeMX支持芯片型号有限
自动生成 HAL 初始化代码生成的代码结构和 CubeMX 有差异
集成编译调试社区资料不如 Keil + SPL 丰富

九、推荐学习路径

如果你只有 STM32/CubeMX 经验,建议按下面顺序:

  1. 第 1 天:安装 Keil + DFP,下载 Firmware Library,跑通 LED 闪烁。
  2. 第 2 天:写 SysTick 延时、按键输入、串口打印。
  3. 第 3 天:定时器中断、PWM、ADC 采集。
  4. 第 4 天:I2C/SPI 外设驱动(OLED、EEPROM、Flash)。
  5. 第 5 天:尝试 GD32 Embedded Builder 生成 HAL 工程。
  6. 持续:读 GD32 Reference Manual + 数据手册,积累寄存器级理解。

十、常见问题 FAQ

Q1:GD32 能用 ST-Link 烧录吗?

可以。ST-Link、J-Link、DAP-Link、GD-Link 都支持 SWD 烧录。

Q2:为什么程序下载后不运行?

检查:

  • 芯片型号是否选对
  • 启动文件容量是否匹配
  • HSE 超时是否足够
  • 是否点击了复位或勾选了 “Reset and Run”

Q3:GD32 的 HAL 库和 STM32 HAL 一样吗?

不完全一样。GD32 的 HAL 库结构和命名有自己的风格,但思路相似。

Q4:GD32F303 能完全替代 STM32F103 吗?

硬件上 Pin-to-Pin 兼容,简单项目可直接替换;复杂外设(USB、以太网)需要验证。


十一、总结

从 STM32/CubeMX 切换到 GD32,最大的变化不是技术栈,而是心态

  • 不要期待 100% 对等的图形化工具
  • 标准库开发反而更贴近底层,更可控
  • GD32 Embedded Builder 在快速进步,可作为辅助

核心口诀

下库 → 建工程 → 配路径 → 写 GPIO → 加延时 → 扩外设 → 看手册

按照这个流程,3 天内你就能从 STM32 开发者变成 GD32 开发者。


附录:常用资源链接

  • 兆易创新官网:https://www.gd32mcu.com
  • GD32 资料下载:https://www.gd32mcu.com/cn/download/7
  • Keil MDK:https://www.keil.com/download
  • ARM GCC Toolchain:https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads

本文基于 GD32F30x 标准外设库和 Keil MDK-ARM 整理,适用于 GD32F10x/F30x 系列入门。