0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【GD32 MCU 移植教程】3、从 STM32F10x 移植到 GD32E103 的移植说明

聚沃科技 2024-09-01 10:42 次阅读

1. 前言

对于使用微控制器进行产品开发的设计人员来说,因产品及功能升级,往往需要将一种微控制器替换成另一种微控制器,在保留既有功能的情况下增加新功能。为了更快地推出新产品,设计人员经常要将应用程序移植到新的微控制器。

本应用笔记旨在帮助您快速将应用程序从 STM32F10x 系列微控制器移植到 GD32E103 系列微控制器(基于 STM32F10x 标准库 V3.5.0)。

GD32E103 和 STM32F10x 系列相比,考虑软硬件兼容性,从 Flash 和 SRAM 容量,包括外设模块的增强性能上来看,GD32E103 最接近 STM32F10x 互联性。

开始前您需要安装 GD32E103 关于 KEIL 或 IAR 的插件,在工程选项的器件条目中选择 GD32E103对应型号,添加 GD32E103 的 Flash 下载算法

GD32E103 较 STM32F10x 具有以下优点:

1、更高的主频(120MHz VS 72MHz)

2、更高版本的内核(Cortex M4 VS M3)

3、更低的功耗(Run Mode:28.6mA@120MHz VS 50mA@72MHz;Sleep Mode:20.8mA@120MHz VS 30mA@72MHz )

但需要注意的是,GD32E103 较 STM32F10x 少了 SDIO 功能,如果用户使用到 SDIO 功能,从STM32F10x 到 GD32E103 的移植,显然是不合适的。

2. 引脚兼容性

STM32F10x 与 GD32E103 在相同封装下是 Pin To Pin 兼容的。但由于外设功能上的细微差别,两者引脚定义有少许不同,如表 1 所示。注意:STM32F10x 外设编号从 1 开始,GD32E103 外设编号从 0 开始,且命名有差异。

表 1 STM32F10x 系列和 GD32E103 系列引脚区别

wKgaombT0LKAbKLrAAC3yY4rAjo076.pngwKgZombT0LaADCUgAAClEzOz6OU635.pngwKgZombT0LmAcJWRAADDqZOs1YM486.png

3. 内部资源兼容性

下表给出了 STM32F10x 与 GD32E103 的资源对比总览(以 STM32F103V8、STM32F105V8 和GD32E103V8 对比为例):

表 2 STM32F105 系列和 GD32E103 系列内部资源对比总览

wKgaombT0M6AbcGHAACM7xq0RNI262.png

4. 程序移植

4.1 时钟移植

GD32E103 时钟设置与 STM32F10x 互联系列兼容,如从 STM32F103 移植到 GD32E103,IDE 需要做相关调整,具体过程如下:

(1) 使用 MDK 环境时:

在工程选项 C/C++选项卡中 Preprocessor Symbol Define 中加入 GD32F10X_CL 的宏定义;在工程选项 Device 中选择原 MCU 对应的互联性型号,或对应的 GD32E103 型号。

(2) 使用 IAR 环境时:

在 工 程 选 项 C/C++ Compiler 项 中 Preprocessor 选项卡下 Define Symbol 中加入GD32F10X_CL 的宏定义。

在工程选项 Device 中选择原 MCU 对应的互联性型号,或对应的 GD32E103 型号。

4.2 Flash 操作相关软件移植

4.2.1 FLash 编程操作

STM32F10x 系列 MCU 仅支持 16 位半字编程,而 GD32E103 仅支持 32 位字和 64 位双字编程,所以需要对 Flash 编程相关库函数进行更改。

(1) FLASH_ProgramWord 函数

wKgZombT0PKAbe4MAABbvZ4r2Ds074.png

说明:由原来的两次半字编程改为一次字编程。

(2) FLASH_EnableWriteProtection 函数

wKgZombT0QCAWnhVAAF6MklXwbI281.png

(3) FLASH_ProgramOptionByteData 函数

wKgaombT0Q6AAP7EAAA0BCgCgMI114.png

说明:由原来的半字编程改为字编程,用户需注意,选项字节需至少一次写一个字,且目标地址必须是 4 的

整数倍。

(4) FLASH_EraseOptionBytes 函数

wKgZombT0R6AHinsAAEebzlXYJA225.png

(5) FLASH_ReadOutProtection 函数

wKgaombT0TGANF3VAAE5eNnafdA842.png

(6) FLASH_UserOptionByteConfig 函数

wKgZombT0USAHz1cAAEW7Gn1Hg8407.png

注:以上代码中的 CR_OPTWRE_Set 的定义是 STM32 固件库中没有的,需要用户自行定义为:

#define CR_OPTWRE_Set ((uint32_t)0x00000200)

4.2.2 注意事项

STM32F10x 的互联型和大容量型(因为 GD32E103 没有大容量型,所以可不考虑)的 Flash 闪存页大小为 2K,而 GD32E103 为 1K,所以用户在调用页擦除时要注意页地址范围。

5. 外设差异性

STM32F10x 与 GD32E103 在外设上基本是兼容的,但 GD32E103 较 STM32F10x 在很多外设上增加了部分功能,用户可根据以下罗列出的外设差异性选择是否使用这些功能。

5.1 模数转换器 ADC

为减轻 CPU 的负担,GD32E103 较 STM32F10x 增加了片上硬件过采样单元。它能够处理多个转换,并将多个转换的结果取平均,得出一个 16 位宽的数据。 片上硬件过采样单元是以降低数据输出率为代价,换取较高的数据分辨率。 具体功能以及寄存器设置,请用户参考 GD32E10x 用户

手册。

另外,由于两款芯片的在 ADC 设计上的差异性,在移植到 GD32E103 时,ADC 使能之后,校准之前,需加入 1ms 的延时,以便 ADC 稳定后再进行校准。

5.2 通用同步异步收发器 USART

GD32E103 较 STM32F10x 在 USART 上增加了块模式(STM32F10x 只支持字节模式)、数据极性设置、数据位反转以及 TX、RX 引脚电平反转等功能,因此,GD32E103 多了四个寄存器,分别为:USART_CTL3、USART_RT、USART_STAT1、USART_CHC。具体功能以及寄存器设置,请用户参考 GD32E10x 用户手册。

5.3 内部集成电路总线接口 I²C

GD32E103和STM32F10x的I²C都支持标速(最高100KHz)和快速(最高400KHz),同时GD32E103可支持高速模式(最高 1MHz),要使能高速模式,需将 I2C_FMPCFG 寄存器的 FMPEN 置 1。具体功能以及寄存器设置,请用户参考 GD32E10x 用户手册。

5.4 串行外设接口/片上音频接口 SPI/I²S

GD32E103 和 STM32F10x 的 SPI/I²S 模块差异性主要表现在 GD32E103 支持 SPI TI 模式、SPI NSS 脉冲模式和 SPI 四线功能(只有 SPI1),其中 SPI 的四线模式是用于控制四线 SPI Flash 外设,此模式下,数据传输速率是普通模式下的 4 倍。具体功能以及寄存器设置,请用户参考 GD32E10x 用户手册。

5.5 通用串行总线全速设备接口 USBFS

GD32E103 和 STM32F105/107 的 USBFS 一致,同时 GD32E103 较 STM32F105/107 相比多了IRC48M 的时钟源可选择。具体功能以及寄存器设置,请用户参考 GD32E103 用户手册。

GD32E103 和 STM32F103 的 USB 模块是不兼容的,如果用户是从 STM32F103 移植而来,需要进行代码移植,具体请参考 STM32F103 与 STM32F105/107 的 USB 差异性。

6. 附录:

(Flash 更改后的程序,用户可直接复制替换原库函数)

0、在 stm32f10x_flash.c 中添加

#define CR_OPTWRE_Set ((uint32_t)0x00000200)

1、

FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data) { FLASH_Status status = FLASH_COMPLETE; __IO uint32_t tmp = 0; /* Check the parameters */ assert_param(IS_FLASH_ADDRESS(Address)); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); if(status == FLASH_COMPLETE) { FLASH->CR |= CR_PG_Set; *(__IO uint32_t*)Address = (uint32_t)Data; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); /* Disable the PG Bit */ FLASH->CR &= CR_PG_Reset; } /* Return the Program Status */ return status; }

2、

FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages) { uint16_t WRP0_Data = 0xFFFF, WRP1_Data = 0xFFFF, WRP2_Data = 0xFFFF, WRP3_Data = 0xFFFF; uint32_t temp1,temp2; FLASH_Status status = FLASH_COMPLETE; /* Check the parameters */ assert_param(IS_FLASH_WRPROT_PAGE(FLASH_Pages)); FLASH_Pages = (uint32_t)(~FLASH_Pages); WRP0_Data = (uint16_t)(FLASH_Pages & WRP0_Mask); WRP1_Data = (uint16_t)((FLASH_Pages & WRP1_Mask) >> 8); WRP2_Data = (uint16_t)((FLASH_Pages & WRP2_Mask) >> 16); WRP3_Data = (uint16_t)((FLASH_Pages & WRP3_Mask) >> 24); temp1 = (((uint32_t)WRP1_Data)<<16) | ((uint32_t)WRP0_Data); temp2 = (((uint32_t)WRP3_Data)<<16) | ((uint32_t)WRP2_Data); /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); if(status == FLASH_COMPLETE) { /* Authorizes the small information block programming */ FLASH->OPTKEYR = FLASH_KEY1; FLASH->OPTKEYR = FLASH_KEY2; while((FLASH->CR&CR_OPTWRE_Set)!=CR_OPTWRE_Set ) {} FLASH->CR |= CR_OPTPG_Set; if(temp1 != 0xFFFF) { //OB->WRP0 = temp1; *(__IO uint32_t*)0X1ffff808=temp1; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); } if((status == FLASH_COMPLETE) && (temp2 != 0xFFFF)) { //OB->WRP1 = temp2; *(__IO uint32_t*)0X1ffff80c=temp2; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); } if(status != FLASH_TIMEOUT) { /* if the program operation is completed, disable the OPTPG Bit */ FLASH->CR &= CR_OPTPG_Reset; } } /* Return the write protection operation Status */ return status; }

3、

FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint32_t Data) { FLASH_Status status = FLASH_COMPLETE; /* Check the parameters */ assert_param(IS_OB_DATA_ADDRESS(Address)); status = FLASH_WaitForLastOperation(ProgramTimeout); if(status == FLASH_COMPLETE) { /* Authorize the small information block programming */ FLASH->OPTKEYR = FLASH_KEY1; FLASH->OPTKEYR = FLASH_KEY2; while((FLASH->CR&CR_OPTWRE_Set)!=CR_OPTWRE_Set ) {} /* Enables the Option Bytes Programming operation */ FLASH->CR |= CR_OPTPG_Set; *(__IO uint32_t*)Address = Data; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); if(status != FLASH_TIMEOUT) { /* if the program operation is completed, disable the OPTPG Bit */ FLASH->CR &= CR_OPTPG_Reset; } } /* Return the Option Byte Data Program Status */ return status; }

4、

FLASH_Status FLASH_EraseOptionBytes(void) { uint16_t temp_spc = RDP_Key; uint32_t temp; FLASH_Status status = FLASH_COMPLETE; /* Get the actual read protection Option Byte value */ if(FLASH_GetReadOutProtectionStatus() != RESET){ temp_spc = 0xbb; } /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(EraseTimeout); if(status == FLASH_COMPLETE){ /* Authorize the small information block programming */ FLASH->OPTKEYR = FLASH_KEY1; FLASH->OPTKEYR = FLASH_KEY2; while((FLASH->CR&CR_OPTWRE_Set)!=CR_OPTWRE_Set ) {} /* if the previous operation is completed, proceed to erase the option bytes */ FLASH->CR |= CR_OPTER_Set; FLASH->CR |= CR_STRT_Set; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(EraseTimeout); if(status == FLASH_COMPLETE) { /* if the erase operation is completed, disable the OPTER Bit */ FLASH->CR &= CR_OPTER_Reset; /* Enable the Option Bytes Programming operation */ FLASH->CR |= CR_OPTPG_Set; /* Restore the last read protection Option Byte value */ // OB->RDP = (uint16_t)rdptmp; temp = ((uint32_t)temp_spc)|0xffff0000; *(__IO uint32_t*)0X1ffff800=temp; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); if(status != FLASH_TIMEOUT) { /* if the program operation is completed, disable the OPTPG Bit */ FLASH->CR &= CR_OPTPG_Reset; } } else{ if (status != FLASH_TIMEOUT){ /* Disable the OPTPG Bit */ FLASH->CR &= CR_OPTPG_Reset; } } } /* Return the erase status */ return status; }

5、

FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState) { uint16_t temp_spc; uint32_t temp; FLASH_Status status = FLASH_COMPLETE; /* Check the parameters */ assert_param(IS_FUNCTIONAL_STATE(NewState)); status = FLASH_WaitForLastOperation(EraseTimeout); if(status == FLASH_COMPLETE) { /* Authorizes the small information block programming */ FLASH->OPTKEYR = FLASH_KEY1; FLASH->OPTKEYR = FLASH_KEY2; while((FLASH->CR&CR_OPTWRE_Set)!=CR_OPTWRE_Set ) {} FLASH->CR |= CR_OPTER_Set; FLASH->CR |= CR_STRT_Set; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(EraseTimeout); if(status == FLASH_COMPLETE) { /* if the erase operation is completed, disable the OPTER Bit */ FLASH->CR &= CR_OPTER_Reset; /* Enable the Option Bytes Programming operation */ FLASH->CR |= CR_OPTPG_Set; if(NewState != DISABLE){ temp_spc = 0xBB; temp = ((uint32_t)temp_spc)|0xffff0000; } else{ temp_spc = (uint16_t)RDP_Key; temp = ((uint32_t)temp_spc)|0xffff0000; } *(__IO uint32_t*)0x1ffff800=temp; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(EraseTimeout); if(status != FLASH_TIMEOUT){ FLASH->CR &= CR_OPTPG_Reset; } } else { if(status != FLASH_TIMEOUT){ /* Disable the OPTER Bit */ FLASH->CR &= CR_OPTER_Reset; } } } /* Return the protection operation Status */ return status; }

6、

FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG,uint16_t OB_STOP, uint16_t OB_STDBY) { FLASH_Status status = FLASH_COMPLETE; uint16_t temp_spc = RDP_Key; uint32_t temp; /* Get the actual read protection Option Byte value */ if(FLASH_GetReadOutProtectionStatus() != RESET) { temp_spc = 0xbb; } /* Check the parameters */ assert_param(IS_OB_IWDG_SOURCE(OB_IWDG)); assert_param(IS_OB_STOP_SOURCE(OB_STOP)); assert_param(IS_OB_STDBY_SOURCE(OB_STDBY)); /* Authorize the small information block programming */ FLASH->OPTKEYR = FLASH_KEY1; FLASH->OPTKEYR = FLASH_KEY2; while((FLASH->CR&CR_OPTWRE_Set)!=CR_OPTWRE_Set ) {} /* if the previous operation is completed, proceed to erase the option bytes */ FLASH->CR |= CR_OPTER_Set; FLASH->CR |= CR_STRT_Set; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); if(status == FLASH_COMPLETE) { /* if the erase operation is completed, disable the OPTER Bit */ FLASH->CR &= CR_OPTER_Reset; /* Enable the Option Bytes Programming operation */ FLASH->CR |= CR_OPTPG_Set; temp =OB_IWDG | (uint16_t)(OB_STOP | (uint16_t)(OB_STDBY | ((uint16_t)0xF8))); temp=temp<<16; temp = ((uint32_t)temp|temp_spc); *(__IO uint32_t*)0x1ffff800=temp; /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); if(status != FLASH_TIMEOUT) { /* if the program operation is completed, disable the OPTPG Bit */ FLASH->CR &= CR_OPTPG_Reset; } } /* Return the Option Byte program Status */ return status; }

教程GD32 MCU方案商聚沃科技原创发布,了解更多GD32 MCU教程,关注聚沃科技官网

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6037

    文章

    44558

    浏览量

    635388
  • 嵌入式
    +关注

    关注

    5082

    文章

    19126

    浏览量

    305277
  • STM32
    +关注

    关注

    2270

    文章

    10900

    浏览量

    356083
  • 开发板
    +关注

    关注

    25

    文章

    5052

    浏览量

    97493
  • GD32
    +关注

    关注

    7

    文章

    403

    浏览量

    24355
收藏 人收藏

    评论

    相关推荐

    GD32 MCU 移植教程】1、 GD32F10x 移植 GD32F30x

    应用程序移植新的微控制器。本应用笔记旨在帮助您快速将应用程序 GD32F10x 系列微控制器移植
    的头像 发表于 08-30 09:52 1572次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>移植</b>教程】1、<b class='flag-5'>从</b> <b class='flag-5'>GD32F10x</b> <b class='flag-5'>移植</b><b class='flag-5'>到</b> <b class='flag-5'>GD32F30x</b>

    STM32F10x系列软件移植GD32F1x0系列操作说明

    本文档介绍了STM32F10x系列到GD32F1x0系列软件移植操作。
    发表于 08-28 16:12 54次下载

    STM32F10x系列移植GD32F10x系列电子版

    STM32F10x系列移植GD32F10x系列电子版
    发表于 05-31 09:22 0次下载

    GD32移植STM32开发平台

    GD32移植STM32开发平台
    发表于 12-02 14:51 28次下载
    <b class='flag-5'>GD32</b><b class='flag-5'>移植</b><b class='flag-5'>到</b><b class='flag-5'>STM32</b>开发平台

    STM32F10x系列移植GD32F10x系列指导文档

    STM32F10x系列移植GD32F10x系列指导文档
    发表于 12-03 16:29 7次下载

    AN047 GD32E103&C103系列移植GD32F30x系列

    AN047 GD32E103&C103系列移植GD32F30x系列
    发表于 02-23 18:59 0次下载
    AN047 <b class='flag-5'>GD32E103</b>&C<b class='flag-5'>103</b>系列<b class='flag-5'>移植</b><b class='flag-5'>到</b><b class='flag-5'>GD32F30x</b>系列

    AN047 GD32E103&C103移植GD32F30x

    兆易创新AN047GD32E103&C103系列移植GD32F30x系列AN047GD32E103&C103系列
    发表于 10-19 17:26 3次下载

    AN011 GD32F10x系列移植GD32F30x系列

    兆易创新AN011GD32F10x系列移植GD32F30x系列AN011GD32F10x系列移植
    发表于 10-19 17:26 3次下载

    GD32 MCU 移植教程】2、 GD32F303 移植 GD32F503

    GD32E503 系列是 GD 推出的 Cortex_M33 系列产品,该系列资源上与 GD32F303 兼容度非常高,本应用笔记旨在帮助您快速将应用程序
    的头像 发表于 08-31 09:36 1476次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>移植</b>教程】2、<b class='flag-5'>从</b> <b class='flag-5'>GD32F</b>303 <b class='flag-5'>移植</b><b class='flag-5'>到</b> <b class='flag-5'>GD32F</b>503

    GD32 MCU 移植教程】5、GD32E230 系列移植 GD32F330 系列

    移植 GD32F330 系列的需求,本文 档专门针对既有的 GD32E230 代码如何移植
    的头像 发表于 09-03 10:05 1148次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>移植</b>教程】5、<b class='flag-5'>GD32E</b>230 系列<b class='flag-5'>移植</b><b class='flag-5'>到</b> <b class='flag-5'>GD32F</b>330 系列

    GD32 MCU 移植教程】6、GD32F1x0和GD32F3x0移植GD32E230

    和低成本,所以在存量客户 中可能会有越来越多的客户会有 GD32F1x0 和 GD32F3x0 移植
    的头像 发表于 09-04 09:38 583次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>移植</b>教程】6、<b class='flag-5'>从</b><b class='flag-5'>GD32F1x</b>0和<b class='flag-5'>GD32F3x</b>0<b class='flag-5'>移植</b><b class='flag-5'>到</b><b class='flag-5'>GD32E</b>230

    GD32 MCU 移植教程】7、 GD32F10x 移植 GD32E103

    本应用笔记旨在帮助您快速将基于 GD32F10x 2.0 版本及以上固件库开发的应用程序GD32F10x 系列微控制器移植
    的头像 发表于 09-05 09:40 517次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>移植</b>教程】7、<b class='flag-5'>从</b> <b class='flag-5'>GD32F10x</b> <b class='flag-5'>移植</b><b class='flag-5'>到</b> <b class='flag-5'>GD32E103</b>

    GD32 MCU 移植教程】8、 STM32F4xx 系列移植 GD32F4xx 系

    、外设及性能对比以及 STM32F4xx 移植 GD32F4xx 的移植步骤,旨在让开发者能
    的头像 发表于 09-06 09:40 1298次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>移植</b>教程】8、<b class='flag-5'>从</b> <b class='flag-5'>STM32F</b>4xx 系列<b class='flag-5'>移植</b><b class='flag-5'>到</b> <b class='flag-5'>GD32F</b>4xx 系

    GD32 MCU 移植教程】9、 STM32F10x 系列移植 GD32F30x 系列

    对比、外设及性能对比以及 STM32F10x 移植 GD32F30x移植步骤,旨在让开发
    的头像 发表于 09-07 09:57 728次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>移植</b>教程】9、<b class='flag-5'>从</b> <b class='flag-5'>STM32F10x</b> 系列<b class='flag-5'>移植</b><b class='flag-5'>到</b> <b class='flag-5'>GD32F30x</b> 系列

    GD32 MCU 移植教程】10STM32F030系列移植GD32E230系列

    GD32E230 对比 STM32F030 有着很好的兼容性和更高的性价比,内核和外设都有所增强。本人曾做过产品的 MCU 替换,将基于 STM32F0xx 1.5.0 固件库的应用程
    的头像 发表于 09-07 10:24 674次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>移植</b>教程】<b class='flag-5'>10</b>、<b class='flag-5'>从</b><b class='flag-5'>STM32F</b>030系列<b class='flag-5'>移植</b><b class='flag-5'>到</b><b class='flag-5'>GD32E</b>230系列