GD32F4移植STM32F4

这篇具有很好参考价值的文章主要介绍了GD32F4移植STM32F4。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

近期在项目中采用了GD32F407VET6替换原项目中的STM32F407VET6,网传GD的兼容性很好,之前也用F1系统的替换了一下,按照CSND各位大佬的经验一步步改进了代码,测试直接通过,现在也一直在项目中实际应用了,一直没有出问题。
所以这SMT时,嘉立创没有STM的货果断换成了GD,可换时简单,到手之后,搜索了一大圈,并没有发现F4像F1一样有大把的经验可以抄。可能是我的搜索水平有限;也有可能是F4相较于F1,其成本优势并没有比F1强很多,替换的人就少了。
还好经过几天的摸索还是搞定了F4的程序替换,下面就个人经验分享给大家,提前声明一下,个人经验有限,本文只阐述本人的开发过程,目前程序运行正常,如果有其他不兼容的地方,还请各位网友自行解决。
另外,如果你是新开发程序,还是建议采用GD的库,毕竟原厂的库更有保障,我这里是因为程序都开发完成了,再移植到GD的库中,很多地方都有修改。

一、开发环境

本人使用Keil5,编写的程序,其他开发环境如:IAR等,可参考修改。工程模板及大部分驱动代码借鉴正点原子F4系列。

二、移植步骤

1.安装GD的支持包。

GD的程序芯片可以选择STM32的替代,但是烧录的时候Flash必须选择GD的,所以安装支持包是必须的。
官网pack包下载链接:https://www.keil.com/dd2/pack/
1.进入KEIL官网下载pack包(链接 **https://www.keil.com/dd2/pack/)

gd32f4,stm32,单片机,嵌入式硬件,c语言
2.找到GigaDevice -> GD32F4xx pack包 -> 点击下载,等待下载完成。
gd32f4,stm32,单片机,嵌入式硬件,c语言
3. 下载完成后,点击安装包,默认安装就好了。
4. 安装完成之后可以打开工程文件,点击魔术棒\Device ,选择对应的GD的芯片就可以了。
gd32f4,stm32,单片机,嵌入式硬件,c语言
注意:重选芯片,会让工程的代码起始位置和大小变成默认值,如果你的程序有OTA或者其他更改程序起始位置和大小的设计,请自行在Target中修改。
gd32f4,stm32,单片机,嵌入式硬件,c语言
5.然后 点击魔术棒\Debug\Settings\Flash Download\Add,如果看到下图这个GD的Flash就ok了。
gd32f4,stm32,单片机,嵌入式硬件,c语言
还有,代码的起始位置和大小,按照自己的程序来改,没有修改就默认即可,我这里是BootLoader程序,所以程序大小就比默认的小很多。
gd32f4,stm32,单片机,嵌入式硬件,c语言
6. 完成上面的操作之后就重新编译一下工程即可。

2.修改32固件库的时钟

在V3.x的库,启动时间宏定义在xxx32f10x.h头文件中;在V3.0以前的库,其启动时间宏定义在xxx32f10x_rcc.c中(HSEStartUp_TimeOut)。搜索一下就找到了。

//修改前:
#define HSE_STARTUP_TIMEOUT    ((uint16_t)0x05000)   /*!< 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.FLASH修改

由于GD的Flash采用了其专利技术,所以GD 的Flash 和STM 的Flash 有些许差异。GD 的擦除时间会一些。对于Falsh的移植要重视,如果程序中有对FLASH的操作(主要是写Flash),则应该进行修改。
这里我们参考F1系列的修改。

3.1 F1的处理

在F1的移植中需要对4个函数进行修改

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;

在以上4个函数中在写完KEY 序列以后,需要读该位,确认key 已生效。所以我们在这里应该插入
While( ! (FLASH->CR & 0x200 ) ); // Wait OPTWRE 或可简单插入两个NOP。
比如,改成以下这样。

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

或者

/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
__NOP();
__NOP();

3.2 F4的Flash修改

由于我代码里对Flash的操作使用的是正点原子的驱动文件,并未使用ST官方库函数stm32f4xx_flash.c,尝试搜索key( FLASH->OPTKEYR = FLASH_KEY1;FLASH->OPTKEYR = FLASH_KEY2;),并无匹配项,于是尝试搜索FLASH_KEY1,这时匹配到下面那个函数:

//解锁STM32的FLASH
void STMFLASH_Unlock(void)
{
	FLASH->KEYR=FLASH_KEY1;	//写入解锁序列.
	FLASH->KEYR=FLASH_KEY2; 
}

于是便在其后面加了一个延时查询指令:while( ! (FLASH->CR & 0x200 ) );// Wait OPTWRE
但在后面的测试中,发现有较大概率会卡死在这个while循环中,于是只能采取加两个空延时的方式实现,具体是什么问题暂时还没有查出来。目前该函数改成以下这样:

//解锁STM32的FLASH
void STMFLASH_Unlock(void)
{
	FLASH->KEYR=FLASH_KEY1;	//写入解锁序列.
	FLASH->KEYR=FLASH_KEY2; 
	__NOP();
	__NOP();
//	while(!(FLASH->CR & 0x200));// Wait OPTWRE
}

此外在F1的帖子里,提到GD的延时时间比ST的短,出于保险起见,我在flash的操作中也延长了其等待时间,其函数的等待因为是可以break循环而提前退出,所以我也不知道这部分代码是否起到作用,但是加上应该不会有问题。我是将STMFLASH_WaitDone这个函数的参数扩大为原来的2倍,修改的函数如下:

//擦除扇区
//sectoraddr:扇区地址,范围是:0~11.
//0~3,16K扇区;4,64K扇区;5~11,128K扇区.
//返回值:执行情况
u8 STMFLASH_EraseSector(u32 sectoraddr)
{
	u8 res=0;
	//res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2s
	res=STMFLASH_WaitDone(400000);//等待上次操作结束,最大2s
	if(res==0)
	{ 
		FLASH->CR&=~(3<<8);	//清除PSIZE原来的设置
		FLASH->CR|=2<<8;	//设置为32bit宽,确保VCC=2.7~3.6V之间!!
		FLASH->CR&=~(0X1F<<3);//清除原来的设置
		FLASH->CR|=sectoraddr<<3;//设置要擦除的扇区 
		FLASH->CR|=1<<1;	//扇区擦除 
		FLASH->CR|=1<<16;	//开始擦除		  
		//res=STMFLASH_WaitDone(200000);//等待上次操作结束,最大2s
		res=STMFLASH_WaitDone(400000);//等待操作结束,最大2s  
		if(res!=1)			//非忙
		{
			FLASH->CR&=~(1<<1);//清除扇区擦除标志.
		}
	}
	return res;
}
//在FLASH指定地址写一个字
//faddr:指定地址(此地址必须为4的倍数!!)
//dat:要写入的数据
//返回值:0,写入成功
//    其他,写入失败
u8 STMFLASH_WriteWord(u32 faddr, u32 dat)
{
	u8 res;	   	  
	//res=STMFLASH_WaitDone(0xFF);
	res=STMFLASH_WaitDone(0X200);
	if(res==0)//OK
	{
		FLASH->CR&=~(3<<8);	//清除PSIZE原来的设置
		FLASH->CR|=2<<8;	//设置为32bit宽,确保VCC=2.7~3.6V之间!!
 		FLASH->CR|=1<<0;	//编程使能
		*(vu32*)faddr=dat;	//写入数据
		//res=STMFLASH_WaitDone(0XFF);//等待操作完成,一个字编程,最多100us.
		res=STMFLASH_WaitDone(0X200);//等待操作完成,一个字编程,最多100us.//0xff
		if(res!=1)//操作成功
		{
			FLASH->CR&=~(1<<0);//清除PG位.
		}
	} 
	return res;
} 

4.其他修改

本来我以为修改以上几点就可以完美兼容代码,可现实给我一个大大的教训,现在想来可能是GD的芯片代码要更加规范,所以如果移植出问题了,可能要在代码的规范上重视。
还有就是GD的MCU和ST的相比在连续串口发送的时候会多一个IDLE bit,但是在F1中,这个差异对于大多数程序并不影响执行,所以就没有重视这个问题。

4.1 函数中的变量定义

在函数中的变量必须先定义,再进行其他操作,当我的芯片改为GD之后,keil编译一遍程序之后,出现了几个报错,百度了一下,发现就是有一个变量的声明在函数的中间,将其声明改到函数前面之后就正常了。

4.2 串口发送

在串口发送数据时,要先发送再等待相应的标志位变化,如果先查询标志位那么程序就会一直在这个while循环中运行,直到我的看门狗将程序复位。
比如,我修改前的串口3发送代码如下:

/*-------------------------------------------------*/
/*函数名:串口3发送缓冲区中的数据                  */
/*参  数:data:数据                               */
/*返回值:无                                       */
/*-------------------------------------------------*/
void u3_TxData(unsigned char *data)
{
	int	i;	
	while((USART3->SR&0X40)==0);
	for(i = 1;i <= data[0];i ++){			
		USART3->DR = data[i];
		while((USART3->SR&0X40)==0);	
	}
}

修改之后为,就正常了。

/*-------------------------------------------------*/
/*函数名:串口3发送缓冲区中的数据                  */
/*参  数:data:数据                               */
/*返回值:无                                       */
/*-------------------------------------------------*/
void u3_TxData(unsigned char *data)
{
	int	i;	
//	while((USART3->SR&0X40)==0);
	for(i = 1;i <= data[0];i ++){			
//		USART3->DR = data[i];
//		while((USART3->SR&0X40)==0);	
		USART_SendData(USART3,data[i]);
    while( USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET );
	}
}

4.3 中断服务函数中不能有printf

其实这个问题,是大部分做单片机开发的一个常识,这个是我之前在ST调试时留下的一条调试信息,只输出了一个数字,(因为我也知道中断中最好不能printf),在ST中正常,后面程序就忘了删,就埋了一个雷,浪费了许多时间。
这也是我说GD的代码要规范的原因,可能他的容错性还是低于ST的,还有其他的例子,但是我一时想不起来了,只能把我记得的bug写出来,以后调试出现问题,要着重查查代码规范性。


总结

以上就是我在移植中的一个小小记录,也可以给大家一个参考。文章来源地址https://www.toymoban.com/news/detail-603089.html

到了这里,关于GD32F4移植STM32F4的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • GD32F4XX IAP升级

    这里使用的是GD32F405RG,flash 为1M(0x08000000 - 0x080FFFFF),具体参考官方手册 因为每个芯片的falsh大小不一样,地址划分根据实际flash大小和自己的设计去分配就好, 自己的址划分如下 : BOOT_ADDRESS:0x08000000 - 0x08003FFF     16k(扇区0) APP_ADDRESS:0x08004000 - 0x0807FFFF     512k-16

    2024年02月12日
    浏览(19)
  • 基于STM32F4的CANOpen移植教程(超级详细)

    本专题相关教程: 基于STM32F4的CANOpen移植教程 基于STM32F4的CANopen快速SDO通信 linux下CANopen for python的使用 基于Linux C的CANopen移植 CANopen补充–时间计算出错 CANopen补充–主站检测节点是否在线 为了在STM32F4上能够运行CANopen(CanFestival),跟着网上的教程操作,发现总是不够详细。

    2024年02月02日
    浏览(24)
  • RT-Thread GD32F4xx CAN驱动

      在RT-Thread的bsp文档中没有找到GD32F4xx的CAN驱动文件,此处参考STM32的drv_can编写CAN驱动。

    2024年02月02日
    浏览(29)
  • GD32F470 移植STM32F429工程 Keil调试笔记

    keil版本:5.25 安装 GigaDevice.GD32F4xx_DFP.3.0.4.pack Keil.STM32F4xx_DFP.2.15.0.pack 1、原项目为STM32F429 工程,切换到GD32F470 只需在 Options for Target\\\"“对话框的Device菜单中选中“GD32F470II”,重新编译即可,一般不会有编译错误。 2、将项目工程在切换回STM32F429,在 Options for Target”\\\"对话框的D

    2024年02月09日
    浏览(23)
  • RT-Thread GD32F4xx PWM设备驱动

      PWM(Pulse Width Modulation,脉冲宽度调制) 是一种对模拟信号电平进行数字编码的方法,通过不同频率的脉冲使用方波的占空比用来对一个具体模拟信号的电平进行编码,使输出端得到一系列幅值相等的脉冲。在具体的芯片中,PWM功能的实现一般定时器绑定,借助定时器的计数

    2024年02月10日
    浏览(19)
  • 单片机移植freemodbus主机(STM32、GD32、瑞萨、国民技术等)

    从github下载:https://github.com/armink/FreeModbus_Slave-Master-RTT-STM32 无法下载或者下载太慢可以用资源下载,无需积分。freeModbus主机源码下载 示例代码 参考从机代码创建 将FreeModbus主机源代码拷贝到工程中间件-第三方库-freemodbus源码库:即MiddlewaresThird_PartyFreeModbusMaster文件夹中。

    2024年02月11日
    浏览(18)
  • STM32F4单片机内部FLASH编程时间

    单片机内部的flash除了存储固件以外,经常将其分为多个区域,用来存储一些参数或存储OTA升级等待更新的固件,这时就会涉及单片机内部flash的编程和擦除操作。STM32同系列的单片机内部flash特性和扇区大小都不太一样,以下基于STM32F407VET6此型号进行简单介绍。 STM32F4xx中文参

    2024年02月03日
    浏览(29)
  • MPU6050(读取原数据、移植DMP、stm32f4、HAL库、KEIL5)

    记录一下自己遇到的问题及解决方法,希望能帮助到一些人。 第一步,读取芯片的原始数据。需要注意两点:1、对HAL库提供的IIC读取写入函数进行再包装。(千万不要觉的这步多此一举,后面移植DMP时用得到) 2、芯片的地址(这里面有俩坑)第一就是,芯片的 I2C 设备地址

    2023年04月08日
    浏览(16)
  • 单片机:STM32F4x HAL库软硬SPI驱动ST7735s 1.8寸LCD屏幕

    说明:此篇为学习记录。可能存在错误或者不足。如有问题请指出。 主控芯片:STM32F411CEU6 主控开发板:WeAct STM32F411CEU6最小系统板 TFT-LCD屏幕:合宙1.8寸TFT-LCD,驱动为ST7735s MDK版本:5,32 HAL库版本:1.27.1 STM32CubeMX版本:6.7.0 ST7735s支持8080并口,3线和4线串行接口,模块的驱动方

    2024年02月03日
    浏览(23)
  • (第48-59讲)STM32F4单片机,FreeRTOS【事件标志、任务通知、软件定时器、Tickless低功耗】【纯文字讲解】【】

    【吐血总结】FreeRTOS难点、Systick中断-滴答定时器、PendSV中断-任务切换、SVC中断-系统底层、时间片调度-时钟节拍【已完结】 (第1-8讲)STM32F4单片机,FreeRTOS基础知识总结【视频笔记、代码讲解】【正点原子】【原创】 (第9-10讲)STM32F4单片机,FreeRTOS任务创建和删除(动态方

    2024年02月01日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包