GD32F103替换STM32F103

注:本文档仅针对GD32F103系列替代STM32F103系列

一、相同点**
1)、外围引脚PIN TO PIN兼容,每个引脚上的复用功能也完全相同。
2)、芯片内部寄存器、外部IP寄存器地址和逻辑地址完全相同,但是有些寄存器默认值不同,有些外设模块的设计时序上和STM32有差异,这点差异主要体现在软件上修改,详情见下文。
3)、编译工具:完全相同例如:KEIL 、IAR
4)、型号命名方式完全相同,所以替代只需找尾缀相同的型号即可,例如:STM32F103C8T6 与 GD32F103C8T6。
5)、仿真工具:JLINK STLink Ulink GDLINK

二、外围硬件区别

三、硬件替换需要注意的地方
从上面的介绍中,我们可以看出,GD32F103系列和STM32F103系列是兼容的,但也需要一些注意的地方。
1)、BOOT0必须接10K下拉或接GND,ST可悬空,这点很重要。
2)、RC复位电路必须要有,否则MCU可能不能正常工作,ST的有时候可以不要。
3)、有时候发现用仿真器连接不上。因为GD的swd接口驱动能力比ST弱,可以有如下几种方式解决:
a、线尽可能短一些;
b、降低SWD通讯速率;
c、SWDIO接10k上拉,SWCLK接10k下拉。
4)、使用电池供电等,注意GD的工作电压,例如跌落到2.0V~2.6V区间,ST还能工作,GD可能无法启动或工作异常。

四、使用ST标准库开发需要修改的地方
1)、GD对时序要求严格,配置外设需要先打开时钟,在进行外设配置,否则可能导致外设无法配置成功;ST的可以先配置在开时钟。

2)、修改外部晶振起振超时时间,不用外部晶振可跳过这步。
原因:GD与ST的启动时间存在差异,为了让GD MCU更准确复位。
修改:
将宏定义:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)
修改为:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF)

3)、GD32F10X flash取值零等待,而ST需要2个等待周期,因此,一些精确延时或者模拟IIC或SPI的代码可能需要修改。
原因:GD32采用专利技术提高了相同工作频率下的代码执行速度。
修改:如果使用for或while循环做精确定时的,定时会由于代码执行速度加快而使循环的时间变短,因此需要仿真重新计算设计延时。使用Timer定时器无影响。

4)、在代码中设置读保护,如果使用外部工具读保护比如JFLASH或脱机烧录器设置,可跳过此步骤。
在写完KEY序列后,需要读该位确认key已生效,修改如下:

总共需要修改如下四个函数:

FLASH_Status FLASH_EraseOptionBytes(void);
FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
uint32_t FLASH_GetWriteProtectionOptionByte(void);
FlagStatus FLASH_GetReadOutProtectionStatus(void);
1
2
3
4
5)、GD与ST在flash的Erase和Program时间上有差异,修改如下:

6)、需求flash大于256K注意,小于256K可以忽略这项。
与ST不同,GD的flash存在分区的概念,前256K,CPU执行指令零等待,称code区,此范围外称为dataZ区。两者在擦写操作上没有区别,但在读操作时间上存在较大差别,code区代码取值零等待,data区执行代码有较大延迟,代码执行效率比code区慢一个数量级,因此data区通常不建议运行对实时性要求高的代码,为解决这个问题,可以使用分散加载的方法,比如把初始化代码,图片代码等放到data区。

7)、ADC采集
a> ADC通道要配置成模拟输入,芯片默认是浮空输入,如果不配成模拟输入,ST的可以正常采集,GD不行
b> ADC时钟没有手动分频最大运行频率14Mhz以内,ST可以正常采集,GD不行。
c> ADC使能后需要加不少于20us延时。
d> 采样精度不如STM32f103,GD32f103存在这个问题,如果对ADC精度要求不高可以选用,可以选用PIN TO PIN 兼容F103系列的GD32E103和GD32F303系列解决。

总结:至此,经过以上修改,在不使用USB和网络能复杂协议的代码,就可以使用ST的代码操作了。

附加:
1、修改或为了区分GD32和STM32的代码,可以使用如下代码:

2、GD的主频支持108MHz,有时候需要提供主频,提供一个96MHZ的参考:

static void SetSysClockTo96(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOC,ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOC,!ENABLE);
    
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
for(StartUpCounter=0;StartUpCounter<0x1fff;StartUpCounter++);
  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /* 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;

#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
    
   
    /* PLL configuration: PLLCLK = PREDIV1 * 12 = 96 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL12); 
#else    
#if 0
    /*  PLL configuration: PLLCLK = HSE * 12 = 96 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
                                                                                for(StartUpCounter=0;StartUpCounter<0x1fff;StartUpCounter++);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL12);
#else
//    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
//                                        RCC_CFGR_PLLMULL));
                                                                                
    //RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE|(1<<17));
    //RCC->CFGR &= ~(RCC_CFGR_PLLMULL);
    //RCC->CFGR |= (uint32_t)(1<<27u);
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | (1<<27)|(7<<18)|(1<<17));
#endif
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    for(StartUpCounter=0;StartUpCounter<0x1fff;StartUpCounter++);
    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    
        for(StartUpCounter=0;StartUpCounter<0x200;StartUpCounter++);
        for(StartUpCounter=0;StartUpCounter<0x1fff;StartUpCounter++);
    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  }
}
————————————————
版权声明:本文为CSDN博主「笙歌君独忧」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_23852045/article/details/109206536

  • 0
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: gd32f103可以替换stm32f103,因为它们都是基于ARM Cortex-M3内核的微控制器,具有相似的架构和功能。但是,由于它们来自不同的制造商,它们的外设和开发工具可能会有所不同。因此,在替换时需要注意一些细节,例如需要重新编译和调试代码,以确保其在新的芯片上正常运行。 ### 回答2: GD32F103是一款适用于嵌入式系统的工业级芯片,其在硬件结构上与STM32F103无明显区别,但通过长时间使用和改进,GD32F103在性能、处理速度、功耗等方面都具有优势,有着更高的性价比和更好的适用性。 首先,GD32F103芯片品质稳定可靠。它采用IST才能够生产,拥有更严格的质量管控标准和更完善的后续服务和技术支持。此外,由于其内存和FLASH的容量较大,在数据存储和处理方面具有闪存容量更大、内存更加充足等优势,更加适用于大型嵌入式系统的需求。 其次,GD32F103在使用方面也比STM32F103更加方便。其配备更多的接口,支持USB、CAN和以太网等多种通信技术,使其能够进行更复杂、更高速的数据交换和传输。此外,还可以使用gd32-dfu-tool之类的开发工具,对其进行更加快捷方便的固件升级。 此外,GD32F103还可以采用与STM32F103相同的编程方式进行开发,出厂时已经预装了一些由ST公司提供的标准库,并且可以在Keil、IAR等主流开发平台中使用,提高用户的开发体验。 总的来说,GD32F103可以作为STM32F103的替代品,其具备的优点都使其可以更加适应嵌入式系统对芯片的要求。同时,由于其优秀的性价比,在逐渐高涨的嵌入式市场中,GD32F103将成为消费者的重要选择。 ### 回答3: GD32F103STM32F103都是基于Cortex-M3内核的微处理器,它们的硬件资源和开发环境都十分相似。因此,在选择这两款芯片时,考虑到成本和供货等方面的因素,我建议可以替换GD32F103。 首先,从成本角度来看,GD32F103STM32F103具有相似的性能和功能,但价格却更加亲民。通过对比市场价格,GD32F103的价格相对更低廉一些,在批量采购时可以实现成本控制。而STM32F103价格则略高一些。 其次,从供货角度来看,GD32F103也具有一定的优势。由于GD32F103是国产芯片,因此其供应链更加稳定可靠,可以在紧急情况下更容易地获得紧急供货。而针对STM32F103,在欧美市场供应较为丰富,但在国内可能存在一些瓶颈,导致供货速度较慢。 最后,从软件角度来看,GD32F103STM32F103的兼容性很高,基本上可以互换,即用STM32F103的驱动程序和应用程序可以无需或做很少修改直接在GD32F103上运行。另外,GD32F103在软件开发方面提供了官方的支持和更新,可以及时处理问题和优化软件体验。 总的来说,选择GD32F103替换STM32F103,除了相对较低的成本和更稳定的供货之外,还具有更加可靠的软件支持,可以更加灵活地适应项目需求。当然,具体的选择还需要根据实际情况进行综合考虑和权衡。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值