一、GD32与STM32区别
1.1 内部结构区别
1.1.1 内核
GD32采用二代的M3内核,STM32主要采用一代M3内核,下图是ARM公司的M3内核勘误表,GD使用的内核只有752419这一个BUG。

1.1.2 主频时钟
使用HSE(高速外部时钟):GD32的主频最大108M,STM32的主频最大72M
使用HSI(高速内部时钟):GD32的主频最大108M,STM32的主频最大64M
主频大意味着单片机代码运行的速度会更快,GD32的_NOP()时间比STM32更加短,所以不使用定时器做延时时要注意修改,项目中如果需要进行刷屏,开方运算,电机控制等操作,GD是一个不错的选择。
1.1.3 启动时间
GD32启动时间相同,由于GD运行稍快,需要延长上电时间配置(2ms)。
1.1.4 时序要求
GD32对时序要求严格,配置外设需要先打开时钟,否则可能导致外设无法配置成功;STM32的可以先配置再开时钟。
1.1.5 供电
| GD32F | STM32F | |
|---|---|---|
| 外部电压 | 2.6-3.6V | 2.0-3.6V |
| 内核电压 | 1.2V | 1.8V |
外部供电:GD32外部供电范围是2.6-3.6V,STM32外部供电范围是2.0-3.6V。GD32的供电范围比STM32相对要窄一点。
内核电压:GD32内核电压是1.2V,STM32内核电压是1.8V。GD的内核电压比STM32的内核电压要低,所以GD的芯片在运行的时候运行功耗更低。
1.2 内部FLASH区别
1.2.1 Flash擦除时间
GD32的Flash是自主研发的,和STM32的不一样。
GD Flash执行速度:GD32 Flash中程序执行为0等待周期。
STM32 Flash执行速度:ST系统频率不访问Flash等待时间关系:0等待周期,当0
Flash擦除时间:GD32的Flash擦除时间要比STM32更长,官方给出的数据是这样的:GD32F103/101系列Flash 128KB 及以下的型号, Page Erase 典型值100ms, 实际测量60ms左右。对应的ST 产品Page Erase 典型值20~40ms。
1.2.2 Flash和RAM容量
GD32的Flash最大有3M,STM32最大只有1M。

1.3 功耗区别
功耗区别(以128k以下容量的作为参考)
| 模式 | GD32F10x | STM32F10x |
|---|---|---|
| 睡眠模式 Sleep | 12.4mA | 7.5mA |
| 深度睡眠模式 Deep Sleep | 1.4mA | 24uA |
| 待机模式 Stand By | 10.5uA | 3.4uA |
| 运行功耗 | 32.4mA/72M | 52mA/72M |

功耗上GD32的静态功耗要相对高一点。从上面的表可以看出GD的产品在相同主频情况下,GD的运行功耗比STM32小,但是在相同的设置下GD的停机模式、待机模式、睡眠模式比STM32还是要高的。
1.4 外围硬件区别
1.4.1 串口
GD在连续发送数据的时候每两个字节之间会有一个Bit的Idle,而STM32没有。
GD32的串口在发送的时候停止位只有1/2两种停止位模式。STM32有0.5/1/1.5/2四种停止位模式。

1.4.2 ADC
GD32的输入阻抗和采样时间的设置和STM32有一定差异,相同配置GD采样的输入阻抗相对来说要小。
具体情况见下表这是跑在72M的主频下,ADC的采样时钟为14M的输入阻抗和采样周期的关系:

1.4.3 FSMC
STM32只有100Pin以上的大容量(256K及以上)才有FSMC,GD32所有的100Pin 或 100Pin以上的都有FSMC。
1.4.4 SWD接口
GD32的SWD接口驱动能力比STM32弱,可以有如下几种方式解决:
线尽可能短一些;
降低SWD通讯速率;
SWDIO接10k上拉,SWCLK接10k下拉。
1.4.5 BOOT0管脚
GD32的BOOT0必须接10K下拉或接GND,STM32可悬空。
1.4.6 RC复位电路
RC复位电路必须要有,否则MCU可能不能正常工作,STM32有时候可以不要。
二、硬件替换需要注意的地方
从上面的介绍中,我们可以看出,GD32F103系列和STM32F103系列是兼容的,但也需要一些注意的地方。
BOOT0必须接10K下拉或接GND,ST可悬空,这点很重要。
RC复位电路必须要有,否则MCU可能不能正常工作,ST的有时候可以不要。
有时候发现用仿真器连接不上。因为GD的SWD接口驱动能力比ST弱,可以有如下几种方式解决:
线尽可能短一些;
降低SWD通讯速率;
SWDIO接10k上拉,SWCLK接10k下拉。
使用电池供电等,注意GD的工作电压,例如跌落到2.0V~2.6V区间,ST还能工作,GD可能无法启动或工作异常。
在GD32F103小容量产品中使用有源晶振,发现会在MCU的复位管脚一直把电平拉到0.89V,电平不能保持在高电平。是由于部分有源晶振起振时间太快,复位信号还没有完成导致的。解决方法就是在有源晶振的输入端与地之前并上一个30pF电容。
三、使用ST标准库开发需要修改的地方
3.1 时序要求
GD32对时序要求严格,配置外设需要先打开时钟,否则可能导致外设无法配置成功;STM32的可以先配置再开时钟。
3.2 修改外部晶振启动时间
不用外部晶振可跳过这步。
由于GD与ST的启动时间存在差异,为了让GD MCU更准确复位,需要对下面参数进行修改。
在 stm32f10x.h 头文件中
将宏定义:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)
修改为:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF)
3.3 修改主频
3.3.1 以72MHz运行
只需要修改上面提到的 HSE_STARTUP_TIMEOUT 把这个从 ((uint16_t)0x0500) 改为 ((uint16_t)0xFFFF)
3.3.2 以108MHz运行
打开 system_stm32f10x.c,将原有的宏注释掉,然后手动添加新的108MHz的宏

代码如下:
#define SYSCLK_FREQ_108MHz 108000000
因为改了宏,下面通过宏来给 SystemCoreClock 赋值也要修改

代码如下:
#elif defined SYSCLK_FREQ_108MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_108MHz; /*!< System Clock Frequency (Core Clock) */
然后还要修改通过宏来选择的函数,就是用来初始化系统时钟配置的,最主要的函数(这个函数是本来没有的,自己设置的)

代码如下:
#elif defined SYSCLK_FREQ_108MHz static void SetSysClockTo108(void);
同理,SetSysClock() 也要修改

代码如下:
#elif defined SYSCLK_FREQ_108MHz SetSysClockTo108();
最后实现108MHz的函数 SetSysClockTo108(),可以在文件最下面实现,注释掉上面一行的 #endif

代码如下:
#elif defined SYSCLK_FREQ_108MHz
/**
* @brief 使用内部时钟倍频到108MHz
* @note This function should be used only after reset.
* @param None
* @retval None
*/
#define RCC_CFGR_PLLMULL27 ((uint32_t)0x08280000)
static void SetSysClockTo108(void)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
/* PLL configuration: PLLCLK = HSI * 27 = 108 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLMULL27);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
#endif
还没结束,这样的话可以实现108MHz,但会有串口波特率错误的BUG,还需要以下修改。
3.4 修改RCC文件
时钟改为108MHz后如果不修改RCC文件会导致串口不合适,需要修改 stm32f10x_rcc.c 文件。具体不懂可以参考GD的手册。
打开 stm32f10x_rcc.c,找到 RCC_GetClocksFreq() 函数

增加一段这样的代码就可以了

代码如下:
/**
* @brief Returns the frequencies of different on chip clocks.
* @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold
* the clocks frequencies.
* @note The result of this function could be not correct when using
* fractional value for HSE crystal.
* @retval None
*/
void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0;
#ifdef STM32F10X_CL
uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
uint32_t prediv1factor = 0;
#endif
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & CFGR_SWS_Mask;
switch (tmp)
{
case 0x00: /* HSI used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
break;
case 0x04: /* HSE used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;
break;
case 0x08: /* PLL used as system clock */
/* Get PLL clock source and multiplication factor ----------------------*/
pllmull = RCC->CFGR & CFGR_PLLMull_Mask; //倍频系数 & 0x003C0000(取18~21)
pllsource = RCC->CFGR & CFGR_PLLSRC_Mask; //时钟源
#ifndef STM32F10X_CL
pllmull = ( pllmull >> 18) + 2; //看手册里面寄存器描述
if (RCC->CFGR & 0x08000000) //取27位
{
pllmull += 15;
}
if (pllsource == 0x00)
{/* HSI oscillator clock divided by 2 selected as PLL clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
}
else
{
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
/* HSE oscillator clock selected as PREDIV1 clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;
#else
/* HSE selected as PLL clock entry */
if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET)
{/* HSE oscillator clock divided by 2 */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull;
}
else
{
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull;
}
#endif
}
#else
pllmull = pllmull >> 18;
if (pllmull != 0x0D)
{
pllmull += 2;
}
else
{ /* PLL multiplication factor = PLL input clock * 6.5 */
pllmull = 13 / 2;
}
if (pllsource == 0x00)
{/* HSI oscillator clock divided by 2 selected as PLL clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
}
else
{/* PREDIV1 selected as PLL clock entry */
/* Get PREDIV1 clock source and division factor */
prediv1source = RCC->CFGR2 & CFGR2_PREDIV1SRC;
prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
if (prediv1source == 0)
{ /* HSE oscillator clock selected as PREDIV1 clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;
}
else
{/* PLL2 clock selected as PREDIV1 clock entry */
上一篇:vscode + PlatformIO嵌入式芯片开发环境搭建
下一篇:ST-Link v2 下载 出现target dll has been cancelled 的错误的解决方法及详解
推荐阅读最新更新时间:2026-03-21 11:56
- LM2904DMR2G 函数发生器运算放大器的典型应用
- DEMO9RS08KA2: DEMO9RS08KA2 Demonstration Board
- MCP73871EV,MCP73871 锂离子电池充电器评估板
- STEVAL-IHM039V1,采用 STM32F415 微控制器的双电机控制演示板
- LTC1606CG 演示板、16 位、250ksps ADC
- RT8086B 3.5A、1.2MHz、同步降压转换器的典型应用
- TS4999EIJT 典型应用 免滤波器立体声 2.8 W D 类音频功率放大器,可选择 3D 音效
- LTM4615,采用 15mm-15mm 封装的完整双路和三路输出负载点模块稳压器
- LTC2415-1IGN 24 位 ADC 的典型应用电路使用电阻器阵列在励磁放大器中提供精确匹配
- 使用 Analog Devices 的 LTC1450LIN 的参考设计



CANopen移植工程(源代码)
智能车平衡轮腿
uCOS-II移植到STM32的详细步骤
现代雷达系统的信号设计
BFR340T






京公网安备 11010802033920号