STM32移植到GD32(以32的工程为模板简单三步完成移植)_stm32f427移植到gd32-程序员宅基地

技术标签: 经验分享  stm32  单片机相关  gd32  移植  

STM32移植到GD32

一、 移植说明

最近有个项目想用GD替代原有的STM32,因为GD的成本更低。然后我就找了一些GD的资料,发现目前网上已有的一些资料都比较老,比如ST移植到GD的攻略,很多都停留在GD刚推广不久的过渡时期,目前已经不适用。就是当时有些GD的芯片官方还开发出对应的pack包或固件库,那时移植GD只能在工程里面选择STM32的芯片,然后修改32的固件库。而现在,GD的芯片都有了自己的固件库和pack包,只要安装对应的pack包就能在芯片选型那里选择对应的GD芯片。所以如果你是用GD做一个全新的项目,那么完全可以用GD官方的demo开发,不再需要将32的程序改成GD的。不过对于我这种原有32的程序已经调试完成,只需修改成GD就能用的人来说,通过修改32固件库来兼容GD是最省事的。
之前我发过一篇博文讲了STM32和GD32的区别,这里就不多讲了。STM32和GD32的型号是一一对应的,比如我测试用的STM32F103C8T6和GD32F103C8T6,引脚排列也是一模一样的,测试的时候我是直接把板子上面的STM32拆下来换成GD32的。编译软件用的是keil,以后有时间的话我会再写一篇IAR的。
好了,废话不多说,下面马上开始讲解移植的过程,移植过程中用到的所有文件我会打包上传,请在文章底部的链接下载。

二、 移植步骤

1、 安装GD的支持包。
GD的程序芯片可以选择STM32的替代,但是烧录的时候Flash必须选择GD的,所以安装支持包是必须的。我安装的pack包版本比较老,在keil官网上也没有找到最新的,所以先凑合着用。打开图1 的两个文件,安装到keil的安装目录就可以了。
注:我看到有些以前的攻略是这样做的:第一步:解压GD32F10xxx Keil IDE Config.rar压缩文件。第二步:将编程算法文件FLM file拷贝到MDK的安装路径”\Keil\ARM\Flash"文件夹下面。然而这个方法已经不适用了,因为现在我根本找不到这个压缩文件,而且官方也不再会提供这些类似的文件了,因为现在GD已经有了自己的支持包和固件库,没必要再搞这些。
在这里插入图片描述
安装完成之后可以打开工程文件,点击Flash\Configue flash Tools\Debug\Settings\Flash Download\Add,如果看到下图这几个GD的Flash就ok了。
在这里插入图片描述
2、 修改32固件库的时钟
在V3.x的库,启动时间宏定义在xxx32f10x.h头文件中;在V3.0以前的库,其启动时间宏定义在xxx32f10x_rcc.c中(HSEStartUp_TimeOut)。搜索一下就找到了。
修改前://#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500) /*!< Time out for HSE start up /
修改后:#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF) /
!< Time out for HSE start up */
修改的原因是GD和STM32的晶振部分电路设计存在一定的差异,两者对外部高速晶振的参数要求也不一样,修改HSE_STARTUP_TIMEOUT宏定义可以保证晶振能够正常起振。当然有些应用其实不修改也能照常跑,这是由于晶振的参数差异造成了,但是为了保证程序的正常运行还是修改这个宏定义比较好。

3、 软件延时时间修改。
GD的主频是108M,比ST的72M要大,代码的运行速度更快。所以如果用到了while函数或者for函数延时,延时的时间肯定是变短了,如果你程序里面有用到延时函数作为IIC或者SPI通讯的时钟线延时,可能就需要修改延时的时间了。官方给出了这么一个数据:实测下面的这一段代码:ST执行该函数的延时时间是7.4us,GD执行该函数的延时时间是5.4us。

void delay(void)
{
    
    u8 i;
	for(i=0;i<75;i++);
}

这个只是作为一个参考,随着延时时间的加长,这个差距会不一样,不能按线性计算。有示波器的话最好用示波器实测。
然后官方也给出了一段IIC的代码,你们可以看一下。
IO模拟I2C他的查应答函数的编写如下:

#define SDA_Status() GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)
void CheckACK(void)
{
    
    cAcknowledge=TRUE
    if(SDA_Status())
    {
    
        cAcknowledge=FalSE;
    }
}

这段代码在ST上面执行OK,但是在GD上面运行不正常,其实这是由于GD的执行速度更快,ACK信号还出来,语句就已经执行完成了。建议修改代码:

#define SDA_Status() GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)
void CheckACK(void)
{
    
    u8 ErrTimer=0;
    cAcknowledge=TRUE
    while(SDA_Status())
    {
    
        ucErrTime++;
 		if(ucErrTime>250)
 		{
    
 			cAcknowledge=FalSE;
 		}
    }
}

如果你的程序只是用到了最常用的功能,如外部中断、定时器、串口这些,那么按照上面的3点改完之后就可以用STM32 的程序烧录到GD上面了,Flash要选择容量相同的GD芯片型号,程序运行应该都没什么问题。而如果你要用到一些特殊的,比如用单片机内部的Flash存数据,使用单片机内部标准的IIC,SPI接口(我们经常是用普通IO口模拟,不会用单片机的库)。那么有些地方就需要修改了,我这里有一份官方给出的GD内部设计引起的一些bug,不过因为资料是比较老的,我也没有一一去测试,所以就不罗列出来了。我只把我测试过的依然存在的问题给大家讲一下。

三、 GD用ST库函数会出现的一些问题
1、 Flash
GD的Flash执行速度快,但是写操作慢,所以在对Flash操作的时候需要修改下面几个函数:

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);

上面这个这四个函数里面都有下面这一句代码:

key( FLASH->OPTKEYR = FLASH_KEY1;FLASH->OPTKEYR = FLASH_KEY2;

我们需要在这一句代码后添加两个__nop()语句或者是增加While( ! (FLASH->CR & 0x200 ) );// Wait OPTWRE 语句来增加等待的时间。比如改成下面这个代码:

/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
While( ! (FLASH->CR & 0x200 ) );// Wait OPTWRE

同时也要修改擦出和写的超时宏定义:

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

修改为:

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

2、 USART
GD的MCU和ST的相比在连续发送的时候会多一个IDLE bit,如下图。这一点对于应用是基本没有影响,只是会影响连续发送数据的发送时间。程序也不需要修改。
在这里插入图片描述
STM32的USART是可以发送停止位的时候是可以选择0.5bit,1bit, 1.5bit和 2bit 。而GD32 USART发送的时候只能发送1 bit或2bit停止位,代码里面如果配制成0.5bit或1bit都是发送1bit,如果配制成1.5bit或2bit则发送2bit停止位。

3、EXTI中断相应异常
EXTI配置好之后如果关闭了EXTI,IO有沿跳变,再次打开EXTI时,系统会响应EXTI关闭过程中的外部触发,为了规避这个问题,每次打开中断前都清一遍中断标志位。(小容量存在该问题,大容量没有)

好了,关于STM32移植到GD32的相关内容就讲到这里。如果你们想了解更多关于ST和GD的差异,可以看我之前发的博文,如果你想要GD的支持包或官方的固件库,可以在文章底部的链接下载,如果还有什么问题或者文章有误,请一定要联系我,谢谢!!!

GD32和STM32的差异:https://blog.csdn.net/ShenZhen_zixian/article/details/103250238
GD32支持包和固件库: https://download.csdn.net/download/ShenZhen_zixian/12004032

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ShenZhen_zixian/article/details/103299034

智能推荐

约束布局ConstraintLayout看这一篇就够了-程序员宅基地

文章浏览阅读4.2k次,点赞3次,收藏3次。真的很有必要学习约束布局和它的辅助布局,因为它可以做出很多好看的效果,且性能高;比如这个ConstraintHelper,效果如下图所示:喜欢的可以继续往下看,不夸张的说,约束布局和其辅助布局的相关的这里都有,而且很详细;引入androidx的constraintlayout的lib相对定位基本定位属性如下表,意思好比就是那一条边和那一条边对齐,比如设置B控件的属性 layout_constraintLeft_toLeftOf=“@id/A”就表示B控件的左边对齐A控件的左边,会收到这个约束。_constraintlayout

远程连接MySQL数据库服务器-程序员宅基地

文章浏览阅读115次。上文说到《[url=http://ricki.iteye.com/blog/772886]局域网内访问tomcat服务器[/url]》,主要是想在会议室内远程访问tomcat服务器,不过在演示的时候需要跑JBPM4.4官方实例的junit test,所以当把jbpm.hibernate.cfg.xml改为具体的IP地址后,会报该IP无法连接数据库服务器。 对此,以root..._客户端如何远程登录连接mysql数据库服务器,以实现远程操作mysql数据库? ( site:blog.csdn.net

#define PINT int*与typedef int *SINT的区别._c语言 sint-程序员宅基地

文章浏览阅读576次。#define PINT int* #define是预处理指令,简单的宏定义,在编译预处理时进行简单的替换,不作正确性检查,不管含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错。①#define PINT int*是,在预处理阶段就已经将PINT替换为int*了,它与int *不等价②如果有PINT a,b; //实际就是 int* a,b; _c语言 sint

JS_数据结构——字典与哈希表_js 声明一个空哈希表-程序员宅基地

文章浏览阅读272次。字典,顾名思义,就是由键:值对的形式进行存储一些值,同现实生活中,每个键对应的值是唯一的,这样才能做到精确查找某值。利用字典,我们可以快速得到键所对应的值,大大方便了我们查找某项数据。在js中,字典的实现和对象十分相似,因为对象在字典中也是采用属性值:属性名的方式进行存储,接下来看一下我所实现的字典吧~var Dictionary=function(){ var items={} //创建一个空字典 this.has=function(key) /_js 声明一个空哈希表

浙江大学计算机与软件学院2021年考研复试上机模拟练习_浙江大学计算机考研复试上机-程序员宅基地

文章浏览阅读533次。文章目录7-1 Square Friends (20 分)7-2 One Way In, Two Ways Out (25 分)7-3 Preorder Traversal (25 分)7-4 Load Balancing (30 分)7-1 Square Friends (20 分)#include <iostream>#include <deque>#include <vector>#include <climits>#include <_浙江大学计算机考研复试上机

tsp问题的拓展_TSP(旅行者问题)——动态规划详解(转)-程序员宅基地

文章浏览阅读2k次。1.问题定义TSP问题(旅行商问题)是指旅行家要旅行n个城市,要求各个城市经历且仅经历一次然后回到出发城市,并要求所走的路程最短。假设现在有四个城市,0,1,2,3,他们之间的代价如图一,可以存成二维表的形式 图一现在要从城市0出发,最后又回到0,期间1,2,3都必须并且只能经过一次,使代价最小。2.动态规划可行性设s, s1, s2, …, sp, s是从s出发的一条路径长度最短的..._游乐园tsp问题

随便推点

SpringMVC:用MultipartFile上传单个文件,多个文件_apache multipartfile-程序员宅基地

文章浏览阅读4w次,点赞11次,收藏52次。单个文件上传开发步骤:1.添加Apache文件上传jar包首先需要下载两个apache上传文件的jar包 commons-fileupload-1.3.1.jar commons-io-2.4.jar 具体使用版本,请根据项目进行选择。 2.配置MultipartResolver处理文件SpringMVC 用的是 的MultipartFile来进行文件上传 所以_apache multipartfile

基于STM32使用超声波HC-SR04模块-程序员宅基地

文章浏览阅读1.2w次,点赞22次,收藏116次。写在前面注意的几点: 1、HC-SR04模块必须使用5V供电,不能是3.3V 2、若单是测距,无需使用中断 3、Echo和Trig两个引脚可以任意接可用的GPIO,和定时器无关说一下超声波的工作原理 单片机给Trig引脚一个最少10us的高电平,然后拉低引脚,便启动了模块, 然后超声波就被发了出去,超声波遇到障碍物后返回被模块接收,Echo引脚会输出一段高电平,高电平的时间与距离成比例

Visual studio C++ MFC之点击按钮(菜单栏)生成新窗口-程序员宅基地

文章浏览阅读899次。背景当前做的APP有菜单栏,菜单栏有一项需要对下位机相关参数进行设置,则必须弹出一个窗口来实现设置操作。本篇即对点击菜单栏生成新的窗口,在新的窗口内完成相应计划后结束新窗口并返回原窗口的方法进行简述。菜单栏的实现可见另一篇博客Visual studio C++ MFC之Menu editor。正文创建一个新窗口在资源视图右击添加Dialog资源,会生成一个新的Dialog,该Dialog..._c++点按钮打开新窗口

「小白经验」浅谈“技术层面-理论层面”_论文中的技术层面是指什么-程序员宅基地

文章浏览阅读1.9k次。今天汇报的时候,被师兄dis了。一句话说的我牙口无言:你是在给我讲科普啊?这一课,让我明白了什么叫作:技术-理论汇报。技术层面看技术性网站、贴吧、论坛。理论层面看学术论文。回首一望那些年,果然是一直停留在技术层面学习,而没有进入理论研究。哪个更总要?哪个都重要。但,就研究生阶段而言,学术研究大于技术学习。因为:技术层是给别人打工的,而理论层是指挥别人工作的。你讲的理论,..._论文中的技术层面是指什么

java数组实现选择排序_java定义一个数组用选择排序排序的方法-程序员宅基地

文章浏览阅读707次。选择排序(Selection sort)是一种简单直观的排序算法。定义一个int类型无序的数组int[] nums = new int[]{3,5,2,6,7,8,1};定义一个int类型的 min ,用来存储每次比对的最小值int min = 0;嵌套循环数组因为是第一个元素比对后面的元素,所以第一个循环 i < 数组长度 -1第二个循环是取出下一个元素进行比对,所以 j = i + 1判断下一个元素是否小于上一个元素,是,则将该元素的索引赋给min进行记录 _java定义一个数组用选择排序排序的方法

flink+kafka+doris+springboot集成例子_springboot doris-程序员宅基地

文章浏览阅读2.2k次。1、springboot基于netty编写接收程序。_springboot doris

推荐文章

热门文章

相关标签