GD32工程创建示例手册

GD32工程创建示例手册

1.芯片包下载

官方链接:Arm Keil | Devices

1.本项目使用的是兆易创新 GD32F470IIH6 主控芯片,因此进入链接直接搜索到如下页面跳转到相应的页面搜索所使用的芯片型号且点击跳转到步骤2所示界面
GD32工程创建示例手册_第1张图片

2.点击GigaDevice,
GD32工程创建示例手册_第2张图片
3.点击CMSIS Packs,找到如下图所示的芯片型号,且点击75Device跳转到步骤4所示界面
GD32工程创建示例手册_第3张图片
4.选择Version History,选择一个你想要的版本下载即可,本项目例程使用的是3.0版本的芯片包
GD32工程创建示例手册_第4张图片

2.固件库下载

**GD官网链接:**http://www.gd32mcu.com/cn

1.点击资料下载下的应用软件
GD32工程创建示例手册_第5张图片
2.搜索栏搜索GD32F4xx,列表中找到如下图所示的文件下载
GD32工程创建示例手册_第6张图片

3.GD32固件库文件了解

GD32工程创建示例手册_第7张图片

  1. Examples

    存放的是每个外设库的参考程序

  2. Firmware

    固件库核心文件

  3. Template

    官方固件库移植示例

  4. Utilities

    第三方固件驱动

4.工程文件创建示例

注(本人使用的是VSCODE配合MDK一起开发)

1.VSCODE下如图创建文件夹
GD32工程创建示例手册_第8张图片

2.使用mdk在Project文件夹下创建工程
2.1点击New μVidion Project(路径选取我们创建好的Project工程目录下)GD32工程创建示例手册_第9张图片

工程名:GD32KeilPrj

由于我们要用到固件库,所以要勾选Core
GD32工程创建示例手册_第10张图片

2.2固件库文件移植

​ 2.2.1找到此路径下的文件…/GD32F4xx_Firmware_Library_V3.0.4\Firmware\GD32F4xx_standard_peripheral

将其中的Include文件夹和Source文件夹移植到新建项目的FW目录下

2.2 .2 ARM\System目录下 应移植内容

  • …\CMSIS\GD\GD32F4xx\Include 将其中的gd32f4xx.h文件 system_gd32f4xx.h

  • …\CMSIS\GD\GD32F4xx\Source\ARM 下的对应的启动文件startup_gd32f450_470.s 依照各开发板找到对应的启动文件即可

  • …\CMSIS\GD\GD32F4xx\Source\system_ 目录下的gd32f4xx.c文件 system_gd32f4xx.c文件

  • GD32F4xx_Firmware_Library_V3.0.4\Template 下的gd32f4xx_it.c gd32f4xx_it.h gd32f4xx_libopt.h

  • /*******************************自己编写的gd32f470x_conf.h文件 此文件内容包含工程xxxx.h头文件*******************/
    #ifndef _gd32f470_h_
    #define _gd32f470_h_
    /*********************************************************************************************************
    *                                              包含头文件
    *********************************************************************************************************/
    #include "gd32f4xx_rcu.h"
    #include "gd32f4xx_adc.h"
    #include "gd32f4xx_can.h"
    #include "gd32f4xx_crc.h"
    #include "gd32f4xx_ctc.h"
    #include "gd32f4xx_dac.h"
    #include "gd32f4xx_dbg.h"
    #include "gd32f4xx_dci.h"
    #include "gd32f4xx_dma.h"
    #include "gd32f4xx_exti.h"
    #include "gd32f4xx_fmc.h"
    #include "gd32f4xx_fwdgt.h"
    #include "gd32f4xx_gpio.h"
    #include "gd32f4xx_syscfg.h"
    #include "gd32f4xx_i2c.h"
    #include "gd32f4xx_iref.h"
    #include "gd32f4xx_pmu.h"
    #include "gd32f4xx_rtc.h"
    #include "gd32f4xx_sdio.h"
    #include "gd32f4xx_spi.h"
    #include "gd32f4xx_timer.h"
    #include "gd32f4xx_trng.h"
    #include "gd32f4xx_usart.h"
    #include "gd32f4xx_wwdgt.h"
    #include "gd32f4xx_misc.h"
    #include "gd32f4xx_enet.h"
    #include "gd32f4xx_exmc.h"
    #include "gd32f4xx_ipa.h"
    #include "gd32f4xx_tli.h"
    
    #endif
    
    

2.2.3 ARM/Systick目录下 应移植内容 最原始版本,不用移植此部分内容,

Systick定时器是一个常用的内置定时器,用于生成周期性的定时中断,通常用于实现基本的系统定时功能,,Systick定时器可以用于生成循环的中断,用于时间的计数,延时,定时等操作

主要用途

  • 延迟生成 : 可以使用·Systick计数器来生成精确的延迟,用于控制各种任务的执行时间间隔
  • 系统心跳 : 可以启动系统的心跳信号,用于指示系统正常运行
  • 定时任务 : 可以设置Systick定时器来周期性的触发中断,用于执行周期性的任务,如数据采集,数据处理等

在这里我们重写Systick.c和Systick.h模块

/*********************************************************************************************************
* 模块名称:SysTick.h
* 摘    要:SysTick模块,包含SysTick模块初始化以及微秒和毫秒级延时函数
*********************************************************************************************************/
#ifndef _SYS_TICK_H_
#define _SYS_TICK_H_

/*****************************包含头文件 **********************************/
#include "gd32f470x_conf.h"

/*********************************************************************************************************
*                                              API函数声明
*********************************************************************************************************/
void  InitSysTick(void);               //初始化SysTick模块
void  DelayNus(__IO unsigned int nus); //微秒级延时函数
void  DelayNms(__IO unsigned int nms); //毫秒级延时函数
#endif

/*********************************************************************************************************
* 模块名称:SysTick.c
* 摘    要:SysTick模块,包含SysTick模块初始化以及微秒和毫秒级延时函数                                                     
*********************************************************************************************************/

/*********************************************包含头文件***************************************************/
#include "SysTick.h"

/*********************************************************************************************************
*                                              私有变量定义
*********************************************************************************************************/
static  __IO  unsigned int s_iTimDelayCnt = 0;

/*********************************************************************************************************
*                                              私有函数声明
*********************************************************************************************************/
static  void TimDelayDec(void); //延时计数

/*********************************************************************************************************
*                                              私有函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称:TimDelayDec
* 函数功能:延时计数  
* 输入参数:void
* 输出参数:void
* 返 回 值:void
* 注    意:在SysTick中断服务函数SysTick_Handler中调用
*********************************************************************************************************/
static  void TimDelayDec(void)
{
  if(s_iTimDelayCnt != 0) //延时计数器的数值不为0
  {
    s_iTimDelayCnt--;     //延时计数器的数值减1
  }
}
/*********************************************************************************************************
* 函数名称:SysTick_Handler
* 函数功能:SysTick中断服务函数 
* 输入参数:void
* 输出参数:void
* 返 回 值:void
*********************************************************************************************************/
void  SysTick_Handler(void)
{
  TimDelayDec();  //延时计数函数
}

/*********************************************************************************************************
*                                              API函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称:InitSysTick
* 函数功能:初始化SysTick模块  
* 输入参数:void  
* 输出参数:void  
* 返 回 值:void
* 创建日期:2022年01月01日
* 注    意:SystemCoreClock / 1000      1ms中断一次(计数1000次为1s,每计一次位1/1000s=1ms)
*           SystemCoreClock / 4000      0.25ms中断一次(计数4000次为1s,每计一次位1/4000s=0.25ms)
*           SystemCoreClock / 100000    10us中断一次(计数100000次为1s,每计一次位1/100000s=10us)
*           SystemCoreClock / 1000000   1us中断一次(计数1000000次为1s,每计一次位1/1000000s=1us)
*********************************************************************************************************/
void InitSysTick( void )
{
  if (SysTick_Config(SystemCoreClock / 1000U)) //配置系统滴答定时器1ms中断一次  
  { 
    while(1)  //错误发生的情况下,进入死循环
    {
      
    }
  }
}
/*********************************************************************************************************
* 函数名称:DelayNms
* 函数功能:毫秒级延时函数  
* 输入参数:nms
* 输出参数:void
* 返 回 值:void
* 创建日期:2022年01月01日
* 注    意:
*********************************************************************************************************/
void  DelayNms(__IO unsigned int nms)
{
  s_iTimDelayCnt = nms;         //将延时计数器s_iTimDelayCnt的数值赋为nms
  
  SysTick->VAL = SysTick->LOAD; //避免第一个ms不准
                              
  while(s_iTimDelayCnt != 0)    //延时计数器的数值为0时,表示延时了nms,跳出while语句
  {  
    
  }    
}
/*********************************************************************************************************
* 函数名称:DelayNus
* 函数功能:微秒级延时函数  
* 输入参数:nus
* 输出参数:void
* 返 回 值:void
* 创建日期:2022年01月01日
* 注    意:
*********************************************************************************************************/
void  DelayNus(__IO unsigned int nus)    
{
  unsigned int s_iTimCnt = nus;       //定义一个变量s_iTimCnt作为延时计数器,赋值为nus
  unsigned short i;                   //定义一个变量作为循环计数器

  while(s_iTimCnt != 0)               //延时计数器s_iTimCnt的值不为0
  {
    for(i = 0; i < 46; i++)           //空循环,产生延时功能
    {
    
    }
    
    s_iTimCnt--;                      //成功延时1us,变量s_iTimCnt减1
  }    
}

2.2.4 ARM/NVIC 目录下应移植内容 关于此部分将会在后期介绍到,代码如未曾涉及到中断,可不引入此目录下文件

/*********************************************************************************************************
* 模块名称:NVIC.h
* 摘    要:NVIC模块,包含NVIC中断分组设置
*********************************************************************************************************/
#ifndef _NVIC_H_
#define _NVIC_H_

void  InitNVIC(void);  //初始化NVIC模块

#endif

/*********************************************************************************************************
* 模块名称:NVIC.c
* 摘    要:NVIC模块,包含NVIC中断分组设置
*********************************************************************************************************/

/*********************************************************************************************************
*                                              包含头文件
*********************************************************************************************************/
#include "NVIC.h"
#include "gd32f470x_conf.h"

static  void ConfigNVIC(void);  //配置NVIC
/*********************************************************************************************************
* 函数名称:ConfigNVIC
* 函数功能:配置NVIC
*********************************************************************************************************/
static  void ConfigNVIC(void)
{
  nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
}

/*********************************************************************************************************
* 函数名称:InitNVIC
* 函数功能:初始化NVIC模块 
*********************************************************************************************************/
void InitNVIC(void)
{
  ConfigNVIC();  //配置NVIC
}

2.3在工具栏中找到下图中框选到的模组

图2-3

2.4按照工程文件结构,将我们的文件添加到我们的工程中
GD32工程创建示例手册_第11张图片

2.5点击图示魔法棒

GD32工程创建示例手册_第12张图片

按图示添加宏定义,

USE_STDPERIPH_DRIVER,GD32F470,USE_USB_FS

为什么要在这么添加这三个宏定义呢? 打开工程,ctrl+f 搜索 USE_STDPERIPH_DRIVER会跳出如下代码块

/* define marco USE_STDPERIPH_DRIVER */
#if !defined  USE_STDPERIPH_DRIVER
#define USE_STDPERIPH_DRIVER
#endif 
#ifdef USE_STDPERIPH_DRIVER
#include "gd32f4xx_libopt.h"
#endif /* USE_STDPERIPH_DRIVER */

我们再跳转到:gd32f4xx_libopt.h 文件中看看,会有如下代码

/*
    Copyright (c) 2022, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/

#ifndef GD32F4XX_LIBOPT_H
#define GD32F4XX_LIBOPT_H

#if defined (GD32F450) || defined (GD32F405) || defined (GD32F407) || defined (GD32F470) || defined (GD32F425) || defined (GD32F427)
#include "gd32f4xx_rcu.h"
#include "gd32f4xx_adc.h"
#include "gd32f4xx_can.h"
#include "gd32f4xx_crc.h"
#include "gd32f4xx_ctc.h"
#include "gd32f4xx_dac.h"
#include "gd32f4xx_dbg.h"
#include "gd32f4xx_dci.h"
#include "gd32f4xx_dma.h"
#include "gd32f4xx_exti.h"
#include "gd32f4xx_fmc.h"
#include "gd32f4xx_fwdgt.h"
#include "gd32f4xx_gpio.h"
#include "gd32f4xx_syscfg.h"
#include "gd32f4xx_i2c.h"
#include "gd32f4xx_iref.h"
#include "gd32f4xx_pmu.h"
#include "gd32f4xx_rtc.h"
#include "gd32f4xx_sdio.h"
#include "gd32f4xx_spi.h"
#include "gd32f4xx_timer.h"
#include "gd32f4xx_trng.h"
#include "gd32f4xx_usart.h"
#include "gd32f4xx_wwdgt.h"
#include "gd32f4xx_misc.h"
#endif

#if defined (GD32F450) || defined (GD32F470)
#include "gd32f4xx_enet.h"
#include "gd32f4xx_exmc.h"
#include "gd32f4xx_ipa.h"
#include "gd32f4xx_tli.h"
#endif

#if defined (GD32F407) || defined (GD32F427)
#include "gd32f4xx_enet.h"
#include "gd32f4xx_exmc.h"
#endif

#endif /* GD32F4XX_LIBOPT_H */

搜索USE_USB_FS 前期初级项目,我们未曾用到usb,所以在项目工程中是无法检索到的,但不妨碍我们先添加这个宏定义

/*!
    \file    usb_conf.h
    \brief   USB core driver basic configuration

    \version 2020-08-01, V3.0.0, firmware for GD32F4xx
*/

/*
    Copyright (c) 2020, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/

#ifndef __USB_CONF_H
#define __USB_CONF_H

#include 
#include "gd32f4xx.h"
//#include "gd32f450i_eval.h"

/* USB Core and PHY interface configuration */

/****************** USB FS PHY CONFIGURATION *******************************
 *  The USB FS Core supports one on-chip Full Speed PHY.
 *  The USE_EMBEDDED_PHY symbol is defined in the project compiler preprocessor
 *  when FS core is used.
*******************************************************************************/

#ifdef USE_USB_FS
    #define USB_FS_CORE
#endif

#ifdef USE_USB_HS
    #define USB_HS_CORE
#endif /* USE_USB_HS */

/*******************************************************************************
 *                      FIFO Size Configuration in Device mode
 *
 *  (i) Receive data FIFO size = RAM for setup packets + 
 *                   OUT endpoint control information +
 *                   data OUT packets + miscellaneous
 *      Space = ONE 32-bits words
 *      --> RAM for setup packets = 10 spaces
 *          (n is the nbr of CTRL EPs the device core supports)
 *      --> OUT EP CTRL info = 1 space
 *          (one space for status information written to the FIFO along with each 
 *          received packet)
 *      --> Data OUT packets = (Largest Packet Size / 4) + 1 spaces 
 *          (MINIMUM to receive packets)
 *      --> OR data OUT packets  = at least 2* (Largest Packet Size / 4) + 1 spaces 
 *          (if high-bandwidth EP is enabled or multiple isochronous EPs)
 *      --> Miscellaneous = 1 space per OUT EP
 *          (one space for transfer complete status information also pushed to the 
 *          FIFO with each endpoint's last packet)
 *
 *  (ii) MINIMUM RAM space required for each IN EP TX FIFO = MAX packet size for 
 *       that particular IN EP. More space allocated in the IN EP TX FIFO results
 *       in a better performance on the USB and can hide latencies on the AHB.
 *
 *  (iii) TXn min size = 16 words. (n:Transmit FIFO index)
 *
 *  (iv) When a TxFIFO is not used, the Configuration should be as follows:
 *       case 1: n > m and Txn is not used (n,m:Transmit FIFO indexes)
 *       --> Txm can use the space allocated for Txn.
 *       case 2: n < m and Txn is not used (n,m:Transmit FIFO indexes)
 *       --> Txn should be configured with the minimum space of 16 words
 *
 *  (v) The FIFO is used optimally when used TxFIFOs are allocated in the top 
 *      of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
 *
 *  (vi) In HS case12 FIFO locations should be reserved for internal DMA registers
 *       so total FIFO size should be 1012 Only instead of 1024
*******************************************************************************/

#ifdef USB_FS_CORE
    #define RX_FIFO_FS_SIZE                         128
    #define TX0_FIFO_FS_SIZE                        64
    #define TX1_FIFO_FS_SIZE                        128
    #define TX2_FIFO_FS_SIZE                        0
    #define TX3_FIFO_FS_SIZE                        0
#endif /* USB_FS_CORE */

#ifdef USB_HS_CORE
    #define RX_FIFO_HS_SIZE                          512
    #define TX0_FIFO_HS_SIZE                         128
    #define TX1_FIFO_HS_SIZE                         372
    #define TX2_FIFO_HS_SIZE                         0
    #define TX3_FIFO_HS_SIZE                         0
    #define TX4_FIFO_HS_SIZE                         0
    #define TX5_FIFO_HS_SIZE                         0

    #ifdef USE_ULPI_PHY
        #define USB_ULPI_PHY_ENABLED
    #endif

    #ifdef USE_EMBEDDED_PHY
        #define USB_EMBEDDED_PHY_ENABLED
    #endif

//    #define USB_HS_INTERNAL_DMA_ENABLED
//    #define USB_HS_DEDICATED_EP1_ENABLED
#endif /* USB_HS_CORE */

#define USB_SOF_OUTPUT              1
#define USB_LOW_POWER               0

//ʹÓÃÄÚ²¿48MHz¾§Õñ
#define USE_IRC48M

//#define VBUS_SENSING_ENABLED

//#define USE_HOST_MODE
#define USE_DEVICE_MODE
//#define USE_OTG_MODE

#ifndef USB_FS_CORE
    #ifndef USB_HS_CORE
        #error  "USB_HS_CORE or USB_FS_CORE should be defined!"
    #endif
#endif

#ifndef USE_DEVICE_MODE
    #ifndef USE_HOST_MODE
        #error  "USE_DEVICE_MODE or USE_HOST_MODE should be defined!"
    #endif
#endif

#ifndef USE_USB_HS
    #ifndef USE_USB_FS
        #error  "USE_USB_HS or USE_USB_FS should be defined!"
    #endif
#endif

/* In HS mode and when the DMA is used, all variables and data structures dealing
   with the DMA during the transaction process should be 4-bytes aligned */

#ifdef USB_HS_INTERNAL_DMA_ENABLED
    #if defined (__GNUC__)         /* GNU Compiler */
        #define __ALIGN_END __attribute__ ((aligned (4)))
        #define __ALIGN_BEGIN
    #else
        #define __ALIGN_END

        #if defined (__CC_ARM)     /* ARM Compiler */
            #define __ALIGN_BEGIN __align(4)  
        #elif defined (__ICCARM__) /* IAR Compiler */
            #define __ALIGN_BEGIN 
        #elif defined (__TASKING__)/* TASKING Compiler */
            #define __ALIGN_BEGIN __align(4) 
        #endif /* __CC_ARM */  
    #endif /* __GNUC__ */ 
#else
    #define __ALIGN_BEGIN
    #define __ALIGN_END
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */

/* __packed keyword used to decrease the data type alignment to 1-byte */
#if defined (__CC_ARM)         /* ARM Compiler */
    #define __packed __packed
#elif defined (__ICCARM__)     /* IAR Compiler */
    #define __packed __packed
#elif defined (__GNUC__)       /* GNU Compiler */
    #ifndef __packed
        #define __packed __attribute__ ((__packed__))
    #endif
#elif defined (__TASKING__)    /* TASKING Compiler */
    #define __packed __unaligned
#endif /* __CC_ARM */

#endif /* __USB_CONF_H */

其实 USE_STDPERIPH_DRIVER 表示的就是使用标准库的意思,GD32F470 表示我们使用的芯片型号 USE_USB_FS表示标准外设版USB驱动库 定义了主机的与外设的一个接口FIFO大小,以及接口匹配速度

D */

/* __packed keyword used to decrease the data type alignment to 1-byte */
#if defined (__CC_ARM)         /* ARM Compiler */
    #define __packed __packed
#elif defined (__ICCARM__)     /* IAR Compiler */
    #define __packed __packed
#elif defined (__GNUC__)       /* GNU Compiler */
    #ifndef __packed
        #define __packed __attribute__ ((__packed__))
    #endif
#elif defined (__TASKING__)    /* TASKING Compiler */
    #define __packed __unaligned
#endif /* __CC_ARM */

#endif /* __USB_CONF_H */

其实 USE_STDPERIPH_DRIVER 表示的就是使用标准库的意思,GD32F470 表示我们使用的芯片型号 USE_USB_FS表示标准外设版USB驱动库 定义了主机的与外设的一个接口FIFO大小,以及接口匹配速度
2.6添加相关文件的头文件到路径中
GD32工程创建示例手册_第13张图片

你可能感兴趣的:(嵌入式学系,嵌入式硬件,单片机,stm32)