目标读者:熟悉 STM32 + CubeMX 开发,想快速切换到国产 GD32 单片机的嵌入式工程师。
本文覆盖:开发环境搭建、标准库工程创建、代码生成工具对比、GPIO/定时器/串口实战、STM32→GD32 迁移要点。
一、GD32 是什么?为什么要切?
1.1 GD32 定位
GD32 是北京**兆易创新(GigaDevice)**推出的 32 位通用 MCU,基于 ARM Cortex-M0/M3/M4/M23/M33/RISC-V 内核。常见系列:
| 系列 | 内核 | 主频 | 特点 | 对标 STM32 |
|---|---|---|---|---|
| GD32F10x | Cortex-M3 | 108MHz | 经典入门,Flash 零等待 | STM32F103 |
| GD32F30x | Cortex-M4 | 120MHz | 带 FPU,性能更高 | STM32F103 升级版 |
| GD32F4xx | Cortex-M4 | 240MHz | 高性能,USB/CAN/以太网 | STM32F4xx |
| GD32E23x | Cortex-M23 | 72MHz | 低功耗,安全 | STM32G0/U0 |
| GD32H7xx | Cortex-M7 | 600MHz | 超高性能 | 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 的工具?
| 工具 | 厂商 | 说明 |
|---|---|---|
| STM32CubeMX | ST | 仅支持 STM32,但可生成 HAL/LL 代码 |
| GD32 Embedded Builder | GigaDevice | 官方图形化 IDE,可生成 HAL 库工程,支持部分型号 |
| AT32 Work Bench | 雅特力 | 国产替代方案,但仅用于 AT32 |
结论:GD32 没有完美对标 CubeMX 的全系列工具。推荐两条路线:
- 快速路线(推荐):用GD32 Embedded Builder生成初始化代码 + HAL 库,再基于 HAL 写业务逻辑。
- 标准库路线(最稳):手动搭 Keil 工程,使用GD32 标准外设库(SPL),和 STM32 标准库开发体验最接近。
- 偷懒路线:GD32F10x/F30x 可以直接烧 STM32CubeMX 生成的 HAL 工程,只需改少量差异点(见第七节)。
三、环境准备
3.1 必备软件与资料
- Keil MDK-ARM 5.30+(建议 5.38 或更新)
- GD32 Device Family Pack(DFP):Keil 识别芯片用
- GD32 Firmware Library:标准外设库 + CMSIS + 启动文件
- GD32 Embedded Builder(可选,图形化配置)
- 调试器:J-Link、ST-Link、DAP-Link、GD-Link 均可
3.2 资料下载地址
- 兆易创新官网:https://www.gd32mcu.com/cn/download/7
- 搜索对应型号,例如
GD32F30x_Firmware_Library和GigaDevice.GD32F30x_DFP.x.x.x.pack
3.3 安装 Keil DFP 包
- 双击下载的
.pack文件。 - 自动识别 Keil 路径,一路 Next。
- 打开 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 | ≤64KB | startup_gd32f30x_xd.s |
| CL | 128~256KB | startup_gd32f30x_cl.s |
| HD | ≥512KB | startup_gd32f30x_hd.s |
GD32F303CCT6 是 256KB Flash,选_cl.s。
FWLIB 目录:
Firmware/GD32F30x_standard_peripheral/Include/*.h Firmware/GD32F30x_standard_peripheral/Source/*.cUser 目录:
Firmware/Template/Keil5_project/gd32f30x_it.c Firmware/Template/Keil5_project/gd32f30x_it.h Firmware/Template/Keil5_project/main.c4.3 Keil 中创建工程
- Project → New μVision Project,保存到
Project/目录。 - 选择芯片:GigaDevice → GD32F303 → GD32F303CCT6。
- 弹出的
Manage Run-Time Environment直接点OK(我们手动添加库)。 - 点击Manage Project Items(品字形图标),添加分组:
CMSIS:添加system_gd32f30x.c和对应启动文件.sFWLIB:添加所有gd32f30x_xxx.cUser:添加main.c、gd32f30x_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_XD、GD32F30X_CL、GD32F30X_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 SPL | GD32 SPL |
|---|---|---|
| 使能时钟 | RCC_APB2PeriphClockCmd | rcu_periph_clock_enable |
| GPIO 初始化 | GPIO_Init | gpio_init |
| 设置引脚高电平 | GPIO_SetBits | gpio_bit_set |
| 串口发送 | USART_SendData | usart_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:
- 选择同封装、同资源的 STM32 型号(如 STM32F103C8T6)。
- 用 CubeMX 生成 HAL 工程。
- 将芯片型号替换为 GD32F303CCT6。
- 修改时钟宏、HSE 超时、Flash 算法。
- 重新编译下载。
但推荐长期使用 GD32 时,还是用标准库或 Embedded Builder,避免隐藏兼容性问题。
八、GD32 Embedded Builder 图形化开发(替代 CubeMX 方案)
8.1 下载与安装
官网下载GD32 Embedded Builder,解压即可使用,无需安装。
8.2 创建工程
- 打开 Embedded Builder。
- File → New → GD Project。
- 输入工程名,选择芯片型号。
- 配置引脚、时钟、外设。
- 点击生成代码,生成 HAL 库工程。
8.3 优缺点
| 优点 | 缺点 |
|---|---|
| 图形化配置,类似 CubeMX | 支持芯片型号有限 |
| 自动生成 HAL 初始化代码 | 生成的代码结构和 CubeMX 有差异 |
| 集成编译调试 | 社区资料不如 Keil + SPL 丰富 |
九、推荐学习路径
如果你只有 STM32/CubeMX 经验,建议按下面顺序:
- 第 1 天:安装 Keil + DFP,下载 Firmware Library,跑通 LED 闪烁。
- 第 2 天:写 SysTick 延时、按键输入、串口打印。
- 第 3 天:定时器中断、PWM、ADC 采集。
- 第 4 天:I2C/SPI 外设驱动(OLED、EEPROM、Flash)。
- 第 5 天:尝试 GD32 Embedded Builder 生成 HAL 工程。
- 持续:读 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 系列入门。