使用STM32固件库开发GD32 汇总

article/2025/8/26 2:23:53

文章目录

  • GD32与STM32异同
    • 1. 相同点
    • 2. 外围硬件区别
    • 3. 内部结构差别
    • 4. 功耗区别(以128k以下容量的作为参考)
    • 5. 内部FLASH 区别
  • 使用STM32库开发
    • 时钟配置
      • 区别
        • 1. 晶振起振区别
          • 描述
          • 解决方法
        • 2. 部分客户使用有源晶振出现问题,在 GD32F103 小容量产品,发现会在 MCU 的复 位管脚一直把电平拉到0.89V,电平不能保持在高电平
          • 描述
          • 解决方法
        • 3. GD32 MCU 主频支持 108MHz 高性能,在代码移植方面需要注意事项
      • 1. 以72MHz运行
      • 2. 以108MHz运行(方法一)
        • 原因
          • 为什么要加这样的代码
          • 为什么是+=15
      • 3. 以108MHz运行(方法二)
        • 移植的代码
      • 参考
    • Flash配置
      • 1. 芯片设置读保护用法
        • 描述
        • 解决方法
      • 2. IAP在应用中编程
        • 描述
        • 解决方法
    • 其他
  • 参考

GD32与STM32异同

来自:https://blog.csdn.net/qq_15181569/article/details/105472881

1. 相同点

  1. 外围引脚定义:
    相同型号的管脚定义相同
  2. Cortex M3 内核:
    STM32F103 内核 R1P1 版本, STM32F205 内核 R2P1,GD32 内核 R2P1 版本,此内核修复了 R1P1 的一些 bug
  3. 芯片内部寄存器,外部 IP 寄存器地址 :
    逻辑地址相同,主要是根据STM32 的寄存器和物理地址,做的正向研发.
  4. 函数库文件:
    函数库相同,优化需要更改头文件
  5. 编译工具:
    完全相同 例如:keil MDK、IAR
  6. 型号命名方式:
    有一点点不一样
/*从上面的代码可以看出,GD32和STM32的命名有点不应样,去掉了低密度产品的选择并到了中密度产品中MD,增加了超大密度的产品选择XD。MD中包含的FLASH大小为:16,32,64,128,256HD中包含的FLASH大小为:384,512,768,1024XD中包含的FLASH大小为:2018,3072CL为互联型产品:包含107和105+网络接口型系列
*/
#define GD32F10X_MD   //GD32F103C8T6

2. 外围硬件区别

  1. 电压范围(ADC):
GD32FSTM32F
外部电压2.6-3.6V2.0-3.6V
内核电压1.2V1.8V
  1. BOOT 0 管脚:
    Flash程序运行时,BOOT0在 STM32上可悬空,GD32 必须外部下拉(从 Flash 运行,BOOT0必须下拉地)

  2. ESD参数:
    STM32 人体模式 2KV,空气模式500V
    GD32 人体模式 4KV(内测5KV),空气模式 10KV(内测 15KV)

3. 内部结构差别

  1. 启动时间:
    GD32 启动时间相同,由于GD 运行稍快,需要延长上电时间配置(2ms)
  2. 主频时钟:
    GD32F10系列主频 108MHZ STM32F10 系列主频 72MHZ
  3. Flash擦除时间:
    GD32 是60ms/page,STM 30ms/page
  4. FLASH 容量:
    GD32 最大容量 3M Byte
  5. SRAM空间:
    GD32F103 系列、GD32F105\107大容量系列 SRAM 96K
  6. VB 外扩总线 FSMC:
    GD32 100PIN 配置总线输出,STM32 144PIN并且 256k 以上才配置总线输出

4. 功耗区别(以128k以下容量的作为参考)

GD32FSTM32F10X
睡眠模式 Sleep12.4mA7.5mA
深度睡眠模式Deep Sleep1.4mA2.5uA
待机模式 Stand By10.5uA3.4uA
运行功耗32.4mA/72M52mA/72M

5. 内部FLASH 区别

  1. ISP:
    擦写时间同STM32 有差异,使用新版ISP 软件
  2. IAP:
    擦写时间相同,按字写入,按页擦除
  3. 存储寿命:
    10万次擦写,数据保存 20 年以上
  4. 加密特性:
    除了常规的禁止读出和96位 ID号码加密之外,GD32 数据写入Flash 时,具有存储逻辑地址连续,物理地址不连续的特性。

使用STM32库开发

下面都是以 GD32F103C8t6 为例

在查找了网上的相关资料后,接下来就是选择是用GD32固件库开发还是STM32的固件库开发了。

我个人是不喜欢再花时间去了解GD32的库了,而且看了一下,貌似还挺麻烦的,而且突然也想试试自己移植一下GD32,也就是用STM32的库(做部分修改和移植)去开发GD32。

GD32官方例程和模板下载地址:http://www.gd32mcu.com/cn/download/6?kw=GD32F1

GD32F10x 标准固件库:

在这里插入图片描述

GD32F103xx 数据手册:

在这里插入图片描述

用户手册和库函数使用指南:

在这里插入图片描述

时钟配置

首先肯定是系统时钟配置了,打开GD32官方的例程,打开 start_gd32f10x_cl.s ,然后找到系统初始化函数

在这里插入图片描述

沿着这条线一直找,最后找到 static void system_clock_108m_hxtal(void) 这个函数,看名字也知道是把系统时钟初始化到108MHz。

在这里插入图片描述

其中:

/* AHB = SYSCLK */
/* APB2 = AHB/1 */
/* APB1 = AHB/2 */
/* select HXTAL/2 as clock source */
/* CK_PLL = (CK_HXTAL/2) * 27 = 108 MHz */

区别

下面说下打开要改些什么东西

1. 晶振起振区别

描述

启动时间,GD32 与 STM32 启动时间都是 2ms,实际上 GD 的执行效率快,所以ST 的

HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)

是2ms,但是这个宏定义值在GD 上时间就更加短了,所以要加大这个值的设置

解决方法

将宏定义:

#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)

修改为:

#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF)

备注:启动时间宏定义所在位置:

  1. 在V3.X 的库,其启动时间宏定义在 stm32f10x.h 头文件中
    (路径:…\Libraries\CMSIS\CM3)。(库版本的不同,所在目录也有所不同)
  2. 在 V3.0 以前的库,其启动时间宏定义在 stm32f10x_rcc.c 源文件中 (HSEStartUp_TimeOut)

其实通过看GD32的固件库代码也可以知道,在GD32中,这个数值也是 ((uint16_t)0xFFFF) 所以直接改就好了

image-20210928111749049

2. 部分客户使用有源晶振出现问题,在 GD32F103 小容量产品,发现会在 MCU 的复 位管脚一直把电平拉到0.89V,电平不能保持在高电平

描述

是由于部分有源晶振起振时间太快,复位信号还没有完成导致的

解决方法

就是在有源晶振的输入端与地之前并上一个30pf 电容

3. GD32 MCU 主频支持 108MHz 高性能,在代码移植方面需要注意事项

GD32 通过芯片内部加大缓存,提高了相同工作频率下的代码执行速度,带来 了高性能的使用体验。

因此如果代码有用到for 循环或while 循环语句做精确定时的,定时时间会由 于代码执行速度加快而使循环的时间变短。使用Timer 定时器则没有影响。

1. 以72MHz运行

只需要修改上面提到的 HSE_STARTUP_TIMEOUT 把这个从 ((uint16_t)0x0500) 改为 ((uint16_t)0xFFFF)

2. 以108MHz运行(方法一)

  1. 首先肯定是把 system_stm32f10x.c 中的宏注释掉,然后手动添加新的108MHz的宏

在这里插入图片描述

  1. 因为改了宏,下面通过宏来给 SystemCoreClock 赋值也要修改

在这里插入图片描述

  1. 然后还要修改通过宏来选择的函数,就是用来初始化系统时钟配置的,最主要的函数(这个函数是本来没有的,自己设置的)

在这里插入图片描述

  1. 同理,这个也要修改

在这里插入图片描述

  1. 最后实现108MHz的函数,可以在文件最下面实现

在这里插入图片描述

代码如下:

#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
  1. 还没结束,这样的话可以实现108MHz,但会有BUG,还需要修改
    void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
    这个函数

image-20210928113407557

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

	/* 在读完 */if (RCC->CFGR & 0x08000000) //取27位{pllmull += 15;}

原因

为什么要加这样的代码

看cubemx的stm32f103c8t6的时钟配置,可以直观的看到整个系统时钟的结构

image-20210928115108503

在这里插入图片描述

首先我们看STM32在正常情况下(也就是用72MHz,不修改时钟,并使用GD32开发板),RCC_CFGR 寄存器的数值

在这里插入图片描述

18~21bit 是PLL的倍频系数,数值是 0111 换成十进制加2就刚好是9,和上图cubemx中PLL的倍频系数对应,(+2也和stm32固件库里面的代码处理对应)

在这里插入图片描述

然后我们再看在使用直接使用GD32的固件库下(也就是用108MHz,修改时钟,使用GD32开发板),RCC_CFGR 寄存器的数值

在这里插入图片描述

下面放到一起对比一下

//  28   24   20   16   12    8    4    00000 0000 0001 1101 0000 0100 0000 1010   //STM320000 1000 0010 1011 0000 0100 0000 1010   //GD32
//不一样的
//第27bit  |  18~21bit  |  17bit  |   
  • 27bit
    (下面会有解释,其实 “对应” 着29bit

    在这里插入图片描述

    来自GD32F103xx用户手册

    在这里插入图片描述

    来自STM32F10x中文参考手册

  • 18~21bit
    是PLL的倍频系数

    在这里插入图片描述

    来自GD32F103xx用户手册

    在这里插入图片描述

    来自STM32F10x中文参考手册

  • 17bit
    这里暂时没搞懂为什么17bit会不一样

    在这里插入图片描述

    来自GD32F103xx用户手册

    image-20210930232729920

    来自STM32F10x中文参考手册

因为在stm32的参考手册里面,RCC_CFGR 寄存器的第27位是保留的,也就是不使用的,所以stm32标准库的代码里面直接没做27位处理,而这个函数(void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) )又是usart、spi等外设用来计算时钟频率的所以,必须得做一点处理,不然就会出现串口乱码等BUG

不做处理时数值是 10101010 换成十进制加2,就刚好是12,但12不对啊,我们要的是27(GD32的PLL倍频系数)

这时候我们加上一个判断,判断第27位置是否为1,为1的话就肯定是GD32了,因为STM32的27位是保留的,然后再加上15就刚好是27,也就和GD32固件库的PLL倍频系数对应:

在这里插入图片描述

⚠️ ⚠️ ⚠️ 这里大家应该都发现了个问题,,,明明数据手册上写的是29位共同构成倍频因子,但实际上29位却根本写不进去,实际上看GD32的固件库也确实是第27位不一样,那没办法了,我们只能相信手册错了。(手册是直接在官网下载的最新版本)

image-20210928153321369

在这里卡了半天,最后终于发现了这篇文章。原来不止我一个人有这个问题。

参考:GD32F103单片机设置时钟到108MHz,串口波特率错误的问题?

为什么是+=15

如果27(其实应该是29)位为1的话,其实就是多了 0x1 0000 也就是,相当于加了 15(0x111)

最后,不出意外的话查看寄存器应该是正确的

image-20210928202751104

3. 以108MHz运行(方法二)

上面(方法一)中,是直接移植了GD32的 void SystemInit(void) 函数,然后直接在主函数开开头添加或者直接修改启动文件

image-20210930230238723

这里是把 SystemInit 改名改为 GD_SystemInit

但还是需要修改:

  • stm32f10x_rcc.c 中的 void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) 函数

  • stm32f10x.h 中的 HSE_STARTUP_TIMEOUT

修改方式和上面一样

移植的代码

其实就是把GD32 GD_SystemInit 函数相关的代码全部复制过来STM32这里了,并稍微修改了一下,(可能算不上移植吧,这种方式并不优雅,但能力有限,也就只能这样了,,)

移植代码的下载连接:https://download.csdn.net/download/K_O_R_K/26541189

在这里插入图片描述

参考

  • GD32F103 108M配置串口乱码解决
  • GD32移植到STM32开发平台_喜欢做我自己的博客-程序员宅基地

Flash配置

1. 芯片设置读保护用法

描述

由于 GD 的 Flash 是自己的专利技术,STM 的 Flash 是第三方提供的,所以 GD 的 Flash 和STM 的Flash 有些许差异。GD 的擦除时间会长一点

解决方法

在写完KEY 序列以后,需要读该位,确认key 已生效。 所以,这里应该插入

While( ! (FLASH->CR & 0x200 ) );    // Wait OPTWRE     /或者/__NOP();__NOP();  //简单的插入两个 __NOP();

在 ST 库中,只有:

  • FLASH_Status FLASH_EraseOptionBytes(void)

  • FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data)

  • FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages)

  • FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState)

    四个函数需要修改:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. IAP在应用中编程

描述

GD32 由于自有flash 的0 访问时序,同 STM32 在 Flash 的 Erase 和 Program 上 存在差别,GD32 的 Erase 和 Program 时间比 STM32 的稍微长些,建议对 Erase 和Program 时间进行修改。

解决方法

将宏定义

//#define EraseTimeout          ((uint32_t)0x000B0000)
//#define ProgramTimeout        ((uint32_t)0x00002000)

修改为:

#define EraseTimeout          ((uint32_t)0x000FFFFF)
#define ProgramTimeout        ((uint32_t)0x0000FFFF)

在这里插入图片描述

备注 : Erase 和 Program 时间宏定义 在 stm32f10x_flash.c 源文件中

其他

目前只测试了 FLASH 、IAP、usart、时钟,其他的没用到,所以暂时没搞

参考

  • GD32移植到STM32开发平台_喜欢做我自己的博客-程序员宅基地
  • GD32F103单片机设置时钟到108MHz,串口波特率错误的问题?
  • GD32替代STM32全过程记录
  • GD32替换STM32注意事项!!!
  • GD32移植到STM32开发平台

http://chatgpt.dhexx.cn/article/1t793Mq4.shtml

相关文章

STM32开发必备知识篇:STM32的运行机制

时间飞逝,转眼间已经硕士毕业工作第四年了,嵌入式研发成长道路上曲折坎坷,所以这也是我今年撰写博客的初心,即分享技术积累和研发经验,目前主要分为STM32和FPGA两个专辑,都包括开发必备知识篇和实战项目例程…

如何评判STM32各个MCU的性能?

很多人说STM32性能太弱,那你了解这个性能是如何得出来的吗? 1写在前面 我们经常听见某手机发布会,安兔兔跑分多少多少,其实这个跑分就是体现手机性能的一个指标。 我们使用STM32开发产品,选择MCU时,一般会综…

STM32各系列MCU性能对比及测试说明

置顶/星标公众号,不错过每一条消息! 很多人说STM32性能太弱,那你了解这个性能是如何得出来的吗? 1写在前面 我们经常听见某手机发布会,安兔兔跑分多少多少,其实这个跑分就是体现手机性能的一个指标。 我们使…

win xp虚拟机

做嵌入式,用的ADS版本太老了,在xp系统上更方便,所以昨天装了一个。 其实我是一个搬运工,主要参考了另一个人的步骤:点击打开链接 只是第一次让输序列号的时候跳过去了。 要镜像可以留邮箱,好像不能直接放在这里&…

VMware虚拟机装windows xp系统

一.准备安装所需要的软件: 1.VMware虚拟机的下载。 首先下载:VMware Workstation(虚拟机) V6.0.2 Build 59824 汉化版 2.XP的系统软件。 二.在VMware虚拟机为创建新的虚拟机 1.打开虚拟机,选择新建虚拟机: 2.下一步:…

Windows xp,Windows2003虚拟机部署(各2台)

文章目录 ISO镜像下载winxp部署a.安装winxp虚拟机b.优化虚拟机c.做快照 Windows 2003a.安装win2003b.优化c.快照 克隆虚拟机(以win2003为例) ISO镜像下载 ISO镜像下载链接 例:下载win10的操作系统 点击操作系统,选择要下载的镜像&#xff0…

VirtualBox 7.0.10 (macOS, Linux, Windows) - 开源跨平台虚拟化软件

VirtualBox 7.0.10 (macOS, Linux, Windows) - 开源跨平台虚拟化软件 Oracle VM VirtualBox 7 请访问原文链接:https://sysin.org/blog/virtualbox-7/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 2022 年 10 月…

虚拟机VMware安装XP系统错误解决办法

虚拟机给我的编程工作确实带了很多方便,但是虚拟机的一个最大挑战是硬件赶不上,速度太慢了。最近一直在致力于虚拟机上Win7专业版平台上SQL Server 2005Visual Studio 2012系统开发,最初还可以,但是越到后面速度越慢。最后决定重新…

VM虚拟机安装Windows XP Professional

文章目录 安装XP下载img镜像安装激活安装VM-Tools 参考 安装XP 下载img镜像 在MSDN安装原版系统镜像-img文件,地址https://msdn.itellyou.cn/ 安装激活 新建虚拟机,选择img镜像文件,开启虚拟机,提交注册码安装即可。 安装VM-Tool…

Win10 虚拟机安装 Windows xp(professional sp3)简记(非教学)

实验系统需使用 VB6.0,任务较为复杂,win10下的vb6.0兼容问题较大。考虑win10 虚拟机安装winxp,部分重点记录如下:(资料源于网络) 虚拟机采用开源的 Oracle VM VirtualBox,(Vmware也可…

VirtualBox 免费高效开源虚拟机软件(在XP下装Linux在、Ubuntu下装Vista等)

说起虚拟机软件,相信大家都会知道VMWare和 微软的Virtual PC 了。今天异次元给大家介绍的是另外一款轻量级的虚拟机软件Virtual Box。它原本是由德国的Innotek公司开发的,后来被Sun收购了。不过呢,它从出生到现在被收购,还是一直保…

VirtualBox虚拟机安装Windows XP

Ubuntu:VirtualBox虚拟机安装Windows XP 2011-03-15 14:58:45 标签: ubuntu vbox Windows xp 虚拟机 文件共享 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。 http://…

超级小的xp虚拟机

链接: https://pan.baidu.com/s/1bpxkUdh 密码: 9d5b 只有200cm,启动超快,运行流畅。系统来自www.sdeepin.org 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇…

推荐两个好用的虚拟机、SSH 终端开源工具(Virtual Box、WindTerm)

笔者最近因一些变故,加上阳了,停更了一段时间,并提前回老家过年了。因并没有带笔记本电脑回去,故在折腾了一番老家电脑后,选择拥抱开源,使用一些开源的工具,而非习惯的 VMware Workstation 和 S…

Python 异步编程之——线程

上一篇我们讲到,进程是一个相对独立的单元。而线程则是一个进程内单一顺序的控制流,是操作系统运行调度的最小单元。因此,一个进程可以包含多个线程。比如,播放视频时,画面和声音就是不同的线程在处理。 1.创建线程 &…

深入理解Python异步编程

文章转载自: 驹说码事,内容有部分修改,仅用作学习,如有侵权,请联系删除。 很多朋友对异步编程都处于“听说很强大”的认知状态。鲜有在生产项目中使用它。而使用它的同学,则大多数都停留在知道如何使用 Tor…

Python异步编程Future对象详解

今天继续给大家介绍Python相关知识,本文主要内容是Python异步编程Future对象详解。 一、Python Future对象简介 在上文Python Task对象详解中,我们介绍到了Task对象,而Future对象是Task对象的基类,比Task更加底层。一个Future是…

Python异步编程之concurrent.futures中的Future对象详解

今天继续给大家介绍Python相关知识,本文主要内容是Python异步编程之concurrent的future对象详解。 一、concurrent.futures中Future对象简介 在前文Python异步编程Future对象详解种,我们介绍了asyncio中的Future对象。然而,在Python中&…

python网络编程实战_Python 异步网络编程实战

近年来 Python 的发展的非常迅速,“简单”、“高效”是 Python 吸引人的一大特色。在国内 Python 开发需求越来越大,Python 具有丰富强大的库,现在各个领域都在广泛使用,从 Web 开发,到运维开发,到机器学习…

Python异步编程实战入门:从概念到实战

概述 读者可前往我的博客获得更好的阅读体验 在Python中存在GIL机制,该机制保证了在Python中同时间内仅能运行一行代码,这导致了Python无法真正实现多线程,但可以通过多进程打破GIL限制,我们会在本文的最后讨论此内容。但Python…