STM32 Cube MX以及STM32 H750 XBH6新建工程,HAL库,LL库

     最近因为需要学习研究一下 F D C A N FD\quad CAN FDCAN模块,所以买了一块野火的 S T M 32 H 750 X B H 6 STM32H750XBH6 STM32H750XBH6的开发板。拿到开发板之后准备像 S T M 32 F 103 STM32F103 STM32F103开发板那样到这里先下载对应的标准库,新建一个小的工程开始。可是我却发现没有 H 7 H7 H7系列的标准库了,如图1所示,最后查找资料了解到, S T ST ST公司目前普遍已经开始使用 H A L HAL HAL库, L L LL LL库等,并且 S T ST ST公司提出了 S T M 32 C U B E STM32\quad CUBE STM32CUBE这个概念,希望通过提高软件的可重用性来减少开发时间,节约开发成本。因此在学习 S T M 32 H 750 X B H 6 STM32H750XBH6 STM32H750XBH6的开发板开发板之前,我需要简单的先了解一下以上概念,下面将是我的一个学习的记录。

 
图1.
 
图2.

     我们先来了解一下 H A L HAL HAL库和 L L LL LL库,这部分内容主要参考图2所示的文档,该文档也可以作为我们以后在使用 H 7 H7 H7系列芯片的 H A L HAL HAL库和 L L LL LL库的时候的参考文档。既然要学习,那我们还是得先把 H A L HAL HAL库和 L L LL LL库下载下载看看到底是个什么样子的,我们先定位到图3所示的页面,这时你会发现这个页面就是 S T M 32 C u b e M X STM32\quad Cube\quad MX STM32CubeMX的页面,这个不用惊奇,因为 S T M 32 C u b e M X STM32\quad Cube\quad MX STM32CubeMX H A L HAL HAL库, L L LL LL库都是属于 S T M 32 C u b e STM32\quad Cube STM32Cube的一部分。然后我们找到图4里面红圈所标示的 S T M 32 C u b e H 7 STM32CubeH7 STM32CubeH7,然后点进入就是我们所要找的 H A L HAL HAL库和 L L LL LL库的下载地址了,如图5中的红圈所示。然后选择我们所要下载的版本即可,至于图5里面的那个 P a t c h _ C u b e H 7 Patch\_CubeH7 Patch_CubeH7,我也不知道是个什么软件包,反正是和 H 7 H7 H7系列有关的,但是你把它下载下来解压之后,发现它里面的内容和 S T M 32 C u b e H 7 STM32CubeH7 STM32CubeH7里面的内容基本是一样的。

 
图3.
 
图4.
 
图5.

     这个 S T M 32 C u b e H 7 STM32CubeH7 STM32CubeH7软件包除了有 H A L HAL HAL库和 L L LL LL库,还有很多其它的内容,比如 S T M 32 STM32 STM32 H 7 H7 H7系列的相关开发板的模板工程,示例工程,如图6和图7所示。图8是 H A L HAL HAL库和 L L LL LL库的源文件所在目录。

 
图6.
 
图7.
 
图8.

     从图8中可以看出, H A L HAL HAL库和 L L LL LL库通过文件名里面的 _ h a l _ \_hal\_ _hal_ _ l l _ \_ll\_ _ll_来进行区别,还可以看到的是有些外设的 H A L HAL HAL库驱动不止一个源文件,比如 s t m 32 h 7 x x _ h a l _ s p i . c stm32h7xx\_hal\_spi.c stm32h7xx_hal_spi.c s t m 32 h 7 x x _ h a l _ s p i _ e x . c stm32h7xx\_hal\_spi\_ex.c stm32h7xx_hal_spi_ex.c,按照官方文档的描述带有 e x ex ex后缀的源文件是外设或模块驱动的扩展文件,它里面包含了某些特定家族或系列芯片所特有功能的驱动,它也有可能包含了对某些通用驱动文件的重写。不带有 e x ex ex后缀的源文件驱动是通用的驱动且对于所有的系列都一样,都适用,具有很高的可移植性。 H A L HAL HAL库综上来说被分为了两类,通用驱动和扩展驱动。还有就是针对通用驱动或扩展驱动,对应的驱动源文件也不止一个,比如我们知道 U S A R T USART USART模块有智能卡的功能,在图8中我们可以看到针对 U S A R T USART USART模块的智能卡功能,还专门有驱动源文件 s t m 32 h 7 x x _ h a l _ s m a r t c a r d . c stm32h7xx\_hal\_smartcard.c stm32h7xx_hal_smartcard.c s t m 32 h 7 x x _ h a l _ s m a r t c a r d _ e x . c stm32h7xx\_hal\_smartcard\_ex.c stm32h7xx_hal_smartcard_ex.c对应。 L L LL LL库就没有通用驱动和扩展驱动之分, L L LL LL库和 H A L HAL HAL库相比没有那么高的抽象性, L L LL LL库都是直接操作寄存器,因此需要对硬件有比较深的了解,可以说是面向专家级别的,因此 L L LL LL库和 H A L HAL HAL库相比移植性也较差。并不是每一种模块或外设都提供了 L L LL LL库,对于那些优化不是关键特性,或者需要大量软件配置,或者需要上层协议栈的模块或外设就没有对应的 L L LL LL库。

/** @defgroup I2C_Configuration_Structure_definition I2C Configuration Structure definition
  * @brief  I2C Configuration Structure definition
  * @{
  */
typedef struct
{
  uint32_t Timing;              /*!< Specifies the I2C_TIMINGR_register value.
                                     This parameter calculated by referring to I2C initialization section
                                     in Reference manual */

  uint32_t OwnAddress1;         /*!< Specifies the first device own address.
                                     This parameter can be a 7-bit or 10-bit address. */

  uint32_t AddressingMode;      /*!< Specifies if 7-bit or 10-bit addressing mode is selected.
                                     This parameter can be a value of @ref I2C_ADDRESSING_MODE */

  uint32_t DualAddressMode;     /*!< Specifies if dual addressing mode is selected.
                                     This parameter can be a value of @ref I2C_DUAL_ADDRESSING_MODE */

  uint32_t OwnAddress2;         /*!< Specifies the second device own address if dual addressing mode is selected
                                     This parameter can be a 7-bit address. */

  uint32_t OwnAddress2Masks;    /*!< Specifies the acknowledge mask address second device own address if dual addressing
                                     mode is selected.
                                     This parameter can be a value of @ref I2C_OWN_ADDRESS2_MASKS */

  uint32_t GeneralCallMode;     /*!< Specifies if general call mode is selected.
                                     This parameter can be a value of @ref I2C_GENERAL_CALL_ADDRESSING_MODE */

  uint32_t NoStretchMode;       /*!< Specifies if nostretch mode is selected.
                                     This parameter can be a value of @ref I2C_NOSTRETCH_MODE */

} I2C_InitTypeDef;

     上面的结构体定义是我从文件 s t m 32 h 7 x x _ h a l _ i 2 c . h stm32h7xx\_hal\_i2c.h stm32h7xx_hal_i2c.h里面复制过来的,用过标准库的应该还是有一种似曾相识的感觉,在标准库中我们就是用这种结构体来对整个模块或外设进行初始化,但是 H A L HAL HAL库相对于标准库具有更高的抽象性,更高的可移植性,为了做到这一点, H A L HAL HAL库在上面这种结构体的基础之上又包装了一层结构体( G P I O , S Y S T I C K , N V I C , P W R , R C C , F L A S H GPIO,SYSTICK , NVIC, PWR,RCC, FLASH GPIOSYSTICKNVICPWRRCCFLASH等模块没有这种结构体):

/** @defgroup I2C_handle_Structure_definition I2C handle Structure definition
  * @brief  I2C handle Structure definition
  * @{
  */
typedef struct __I2C_HandleTypeDef
{
  I2C_TypeDef                *Instance;      /*!< I2C registers base address                */

  I2C_InitTypeDef            Init;           /*!< I2C communication parameters              */

  uint8_t                    *pBuffPtr;      /*!< Pointer to I2C transfer buffer            */

  uint16_t                   XferSize;       /*!< I2C transfer size                         */

  __IO uint16_t              XferCount;      /*!< I2C transfer counter                      */

  __IO uint32_t              XferOptions;    /*!< I2C sequantial transfer options, this parameter can
                                                  be a value of @ref I2C_XFEROPTIONS */

  __IO uint32_t              PreviousState;  /*!< I2C communication Previous state          */

  HAL_StatusTypeDef(*XferISR)(struct __I2C_HandleTypeDef *hi2c, uint32_t ITFlags, uint32_t ITSources);
  /*!< I2C transfer IRQ handler function pointer */

  DMA_HandleTypeDef          *hdmatx;        /*!< I2C Tx DMA handle parameters              */

  DMA_HandleTypeDef          *hdmarx;        /*!< I2C Rx DMA handle parameters              */

  HAL_LockTypeDef            Lock;           /*!< I2C locking object                        */

  __IO HAL_I2C_StateTypeDef  State;          /*!< I2C communication state                   */

  __IO HAL_I2C_ModeTypeDef   Mode;           /*!< I2C communication mode                    */

  __IO uint32_t              ErrorCode;      /*!< I2C Error code                            */

  __IO uint32_t              AddrEventCount; /*!< I2C Address Event counter                 */

#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
  void (* MasterTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Master Tx Transfer completed callback */
  void (* MasterRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Master Rx Transfer completed callback */
  void (* SlaveTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Slave Tx Transfer completed callback  */
  void (* SlaveRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Slave Rx Transfer completed callback  */
  void (* ListenCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Listen Complete callback              */
  void (* MemTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Memory Tx Transfer completed callback */
  void (* MemRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Memory Rx Transfer completed callback */
  void (* ErrorCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Error callback                        */
  void (* AbortCpltCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Abort callback                        */

  void (* AddrCallback)(struct __I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode);
  /*!< I2C Slave Address Match callback */

  void (* MspInitCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Msp Init callback                     */
  void (* MspDeInitCallback)(struct __I2C_HandleTypeDef *hi2c);
  /*!< I2C Msp DeInit callback                   */

#endif  /* USE_HAL_I2C_REGISTER_CALLBACKS */
} I2C_HandleTypeDef;

     这种结构体被称之为 H a n d l e Handle Handle,可以看到这种 H a n d l e Handle Handle结构体把模块寄存器结构体,模块初始化结构体都包含在这个结构体之中,当然还有 D M A DMA DMA的相关结构体。还有就是 H A L HAL HAL库里面已经为我们实现了中断函数的初始版本,我们需要在 I 2 C x _ E V _ I R Q H a n d l e r I2Cx\_EV\_IRQHandler I2Cx_EV_IRQHandler I 2 C x _ E R _ I R Q H a n d l e r I2Cx\_ER\_IRQHandler I2Cx_ER_IRQHandler等函数中调用下面的初始版本函数。 H A L HAL HAL库里面也有大量的回调函数,至于这种回调函数的具体使用,我现在也不是太清楚,只有在具体使用过 H A L HAL HAL库之后才能对这一机制有比较清晰的了解,我只知道这种回调函数主要在中断机制中被调用。文件 s t m 32 h 7 x x _ h a l _ i 2 c . h stm32h7xx\_hal\_i2c.h stm32h7xx_hal_i2c.h中,初始版本的中断函数以及回调函数声明如图9所示。还有这些回调函数一般都是被声明为 _ _ w e a k \_\_weak __weak属性,如图10所示,也就是用户可以定义一个同名的函数,且最后调用这个名字的函数时,如果用户重新定义了这个函数,则实际调用的是用户定义的这个函数。

void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c);
void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c);
 
图9.
 
图10.

     图11是 H A L HAL HAL库中头文件的包含结构示意图。虽然 H A L HAL HAL库和 L L LL LL库的头文件和源文件都各自的在同一个文件夹中,但是 H A L HAL HAL库和 L L LL LL库都是相互独立的,相互之间没有依赖关系。虽然如此, H A L HAL HAL库和 L L LL LL库都可以各自独立使用,但是也可以结合使用。我们前面提到过 L L LL LL库基本都是直接操作寄存器的,有朋友可能会想到 L L LL LL库是不是就是和标准库差不多,但是等你打开 L L LL LL库的源文件和头文件之后你就不会有这样的想法了。文件 s t m 32 h 7 x x _ l l _ i 2 c . c stm32h7xx\_ll\_i2c.c stm32h7xx_ll_i2c.c里面只有和初始化和恢复默认值的几个接口函数,如图12所示,但是我看单独使用 L L LL LL库的例子中基本可以不用这几个函数。然后其它的接口函数都定义在文件 s t m 32 h 7 x x _ l l _ i 2 c . h stm32h7xx\_ll\_i2c.h stm32h7xx_ll_i2c.h中,且这些接口都是直接操作寄存器的,并都定义为 _ _ i n l i n e \_\_inline __inline,即内联,函数类型。如图13所示。

 
图11.
 
图12.
 
图13.

      S T M 32 C u b e STM32\quad Cube STM32Cube S T ST ST公司的一项原始创新,这一项原始创新通过减少开发成本,时间来提高开发者的效率。 S T M 32 C u b e STM32\quad Cube STM32Cube基本上涵盖了所有的 S T ST ST公司的系列信号芯片。 S T M 32 C u b e STM32\quad Cube STM32Cube包含几部分内容, S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX S T M 32 C u b e STM32\quad Cube STM32Cube其中的一部分, S T M 32 C u b e STM32\quad Cube STM32Cube所包含的内容如图14所示。

 
图14.
 
图15.
 
图16.

      S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX是一种图形化工具,我开始听说它的时候,我以为从此之后 S T M 32 STM32 STM32所有的代码开发都可以通过简单的点点鼠标就可以了,但是通过我的了解之后我还是觉得我想多了。下面我对 S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX的介绍都是基于图15的文档。 S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX具有图16所示的特性,但是向我们这种初学者话,用的比较多的可能就是图16中红圈中的功能,也就是构建初始化工程,以及生成时钟配置函数(这里要注意的是 H A L HAL HAL库在芯片上电复位调用的 v o i d S y s t e m I n i t ( v o i d ) void\quad SystemInit (void) voidSystemInit(void)函数里面是没有调用像标准库里面那样的配置时钟的函数, v o i d S e t S y s C l o c k ( v o i d ) void\quad SetSysClock (void) voidSetSysClock(void),的,这种时钟配置函数要么我们自己实现或者使用 S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX来生成,当然使用 S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX来生成还是方便很多)。

 
图17.
 
图18.

      S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX的下载地址如图18所示,选择相应的版本下载就可以。这里因为我也是初学,我就不详细的去介绍 S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX,具体的细节可以参考图15的文档。下面我直接介绍一下一个最基础的构建工程模板的过程。 S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX打开之后的界面如图19所示,这时可以通过点击红框中的 A C C E S S T O M C U S E L E C T O R ACCESS\quad TO\quad MCU\quad SELECTOR ACCESSTOMCUSELECTOR F i l e File File下拉菜单的 N e w P r o j e c t New\quad Project NewProject来开始新建 S T M 32 C u b e M X STM32\quad CubeMX STM32CubeMX工程。之后的页面如图20所示,这时我们需要根据自己的芯片型号来选择对应的芯片型号,图20左边的是搜索你的预期芯片的一些过滤选项,设置好之后就会出现相关的芯片型号,如图20的右下角所示,因为我这边的开发板的芯片的型号为 S T M 32 H 750 X B H 6 STM32H750XBH6 STM32H750XBH6,所以我这里点击选中该型号(注意这里鼠标一定要点击,不然右上角的 S t a r t P r o j e c t Start\quad Project StartProject将会是灰色的),然后点击 S t a r t P r o j e c t Start\quad Project StartProject

 
图19.
 
图20.

     接下来将会出现图21所示的界面,这个提示应该是和 M P U MPU MPU相关的,这里关系应该不太大,选 Y e s Yes Yes N o No No应该都可以,但是它建议你选择 Y e s Yes Yes。接下来就会出现图22所示的界面,这时我们先点击一下 P r o j e c t M a n a g e r Project\quad Manager ProjectManager配置一下工程的名字,存放位置,生成的模板工程使用的 I D E IDE IDE(这里我使用的是 K E I L KEIL KEIL,因此这里我选择的是 M D K − A R M MDK-ARM MDKARM),模板工程堆和栈空间的大小等等,当然还有其它一些选项,大家可以参考图15的文档。

 
图21.
 
图22.
 
图23.

     接下来我们来配置一下系统的时钟,因为我们这里准备使用 H S E HSE HSE作为时钟源,因此这里我们首先要在图23所在的 P i n o u t C o n f i g u r a t i o n Pinout\quad Configuration PinoutConfiguration界面使能 H S E HSE HSE,然后我们切换到图25所示的时钟配置界面,因为野火的开发板的 H S E HSE HSE时钟为 25 M H Z 25MHZ 25MHZ,因此这里 H S E HSE HSE时钟的输入频率方框我们填 25 M H Z 25MHZ 25MHZ。我们这里配置 H S E HSE HSE时钟5分频,然后160倍频之后再除以2, P L L PLL PLL时钟源选择 H S E HSE HSE,系统时钟源选择 P L L PLL PLL,因此配置的系统时钟, S Y S C L K SYSCLK SYSCLK,的频率为 400 M H Z 400MHZ 400MHZ H C L K HCLK HCLK的频率为 200 M H Z 200MHZ 200MHZ A P B 1 APB1 APB1 A P B 2 APB2 APB2 A P B , 3 APB,3 APB,3 A P B 4 APB4 APB4的频率都为 100 M H Z 100MHZ 100MHZ。这里的模板工程我想用简单的 U S A R T USART USART模块的通信来验证,因此这里我在图25的界面也简单的配置了一下 U S A R T 1 USART1 USART1模块,这些配置好之后,我们点击一下图25中右上角的 G E N E R A T E C O D E GENERATE\quad CODE GENERATECODE就可以生成我们的模板工程了。

 
图24.
 
图25.

     当然我们也可以自己手动构建模板工程。这个过程其实和 S T M 32 F 103 STM32F103 STM32F103的标准库的手动构建工程模板的工程基本一样,可以参考一下我的这篇文章,只是在细节上会有一些差别。首先我们还是先新建一些文件夹来把需要的各个源文件放置好,我们首先将图26的文件夹中的所有文件放在一个新建的名字位 c o r e core core的文件夹中,这个文件夹里面基本都是和内核有关的文件,虽然这里面有很多文件,但是实际的工程里面用到可能就几个而已,但是为了方便我这里把他们全部都放进来了。然后新建一个叫 u s e r user user的文件夹,然后找到 H 750 H750 H750的模板工程,并将图26和图27里面的 m a i n . c main.c main.c m a i n . h main.h main.h文件复制到这个文件夹里面,当然你也可以自己生成这两个文件。然后新建一个叫 h a l hal hal的文件夹,将图28里面的 I n c Inc Inc文件夹和 S r c Src Src文件夹放到这个文件夹里面,这两个文件夹里面分别是 H A L HAL HAL库和 L L LL LL库的头文件和源文件。然后新建一个叫做 s t a r t _ u p start\_up start_up的文件夹并将图29中红圈标示的启动文件放在这个文件夹里面。然后分别新建 p r o j e c t project project o b j _ o u t p u t obj\_output obj_output以及 l i s t i n g listing listing三个文件夹,这三个文件夹分别用来放项目配置文件,编译输出的中间文件以及 l i s t list list文件。然后新建一个 s t m stm stm文件夹,这个文件夹里面又新建了两个文件夹, I n c l u d e Include Include S o u r c e Source Source,然后将图30和图31的头文件放到 I n c l u d e Include Include文件夹里面。然后将图32里面的三个红圈标示的源文件放到 S o u r c e Source Source文件夹里面。图31和图32的目录和前面取 m a i n . c main.c main.c m a i n . h main.h main.h文件得目录都是同一个模板工程。

的文件也是 S T ST ST公司提供的一个模板工程的目录里面。但是其实这里

 
图26.
 
图27.
 
图28.
 
图29.
 
图30.
 
图31.
 
图32.

     因为 m a i n . c main.c main.c m a i n . h main.h main.h文件这两个文件是我们从模板工程里面复制出来的,可能编译会有错误,因此我们需要根据自己的需求做相应的修改。还有就是图33中的 s t m 32 h 7 x x _ h a l _ m s p _ t e m p l a t e . c stm32h7xx\_hal\_msp\_template.c stm32h7xx_hal_msp_template.c,这个文件在使用的时候需要去掉 t e m p l a t e template template关键字,然后复制到对应的目录并根据需求做相应的修改,从这个文件的名字我们也可以看出,这是一个模板文件,由于我们已经从模板工程里面获取了这个文件,因此这个文件就不要参与编译了,同样图34中那几个红圈中的文件名带有 t e m p l a t e template template关键字的文件也都不要参与编译了,否则可能会有错误,在有相应需求的时候再把它们修改之后再参与编译。另外还要注意一下 s y s t e m s t m 32 h 7 x x . c system_stm32h7xx.c systemstm32h7xx.c这个文件,前面也提到过了这个文件是从 S T M 32 C u b e H 7 STM32CubeH7 STM32CubeH7固件包里面的 H 750 H750 H750模板工程复制过来的, S T M 32 C u b e H 7 STM32CubeH7 STM32CubeH7固件包里面 有很多的 H 750 有很多的H750 有很多的H750示例工程,每一个工程里面都有这个文件,如果你仔细去看的话有些工程的这个文件与其它的工程有一定的差异,主要是 v o i d S y s t e m I n i t ( v o i d ) void\quad SystemInit (void) voidSystemInit(void)这个函数,比如 Q S P I QSPI QSPI的示例工程,或者是从外部存储器启动的示例工程,这应该是这些工程的特殊目的造成的,所以如果我们有相应的特殊需求的时候 s y s t e m s t m 32 h 7 x x . c system_stm32h7xx.c systemstm32h7xx.c这个文件可以参考相应的工程,对于一般的工程我们直接从图32的模板工程里面去取。这里要注意的是在我构建的这个模板工程中,文件 s y s t e m s t m 32 h 7 x x . c system_stm32h7xx.c systemstm32h7xx.c中的 v o i d S y s t e m I n i t ( v o i d ) void\quad SystemInit (void) voidSystemInit(void)函数的一个位置需要注意一下,如图35所示,这里有一个宏需要定义一下,这个宏定义了你预期的程序代码放置的首地址,因为我这里预期从内部 F L A S H FLASH FLASH启动,所以在图36中这个宏我定义位内部 F L A S H FLASH FLASH的起始地址 0 x 08000000 0x08000000 0x08000000,在图36里面的 P r e p r o c e s s o r S y m b o l s Preprocessor\quad Symbols PreprocessorSymbols的位置我还加上了宏 U S E _ H A L _ D R I V E R USE\_HAL\_DRIVER USE_HAL_DRIVER U S E _ F U L L _ L L _ D R I V E R USE\_FULL\_LL\_DRIVER USE_FULL_LL_DRIVER以及 S T M 32 H 750 x x STM32H750xx STM32H750xx因为这样就可以同时使用 H A L HAL HAL库和 L L LL LL库,当然你也可以根据你自己的需求定义宏 U S E _ H A L _ D R I V E R USE\_HAL\_DRIVER USE_HAL_DRIVER和宏 U S E _ F U L L _ L L _ D R I V E R USE\_FULL\_LL\_DRIVER USE_FULL_LL_DRIVER中的一个。因为我这里使用的芯片是 S T M 32 H 750 X B H 6 STM32H750XBH6 STM32H750XBH6,因此需要定义宏 S T M 32 H 750 x x STM32H750xx STM32H750xx。有了以上准备再参考一下我用 S T M 32 F 103 STM32F103 STM32F103的标准库的手动构建工程模板的流程,看这里,基本上建立一个工程模板是没有问题的。我的模板工程在这里。

 
图34.
 
图35.
 
图36.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qqssss121dfd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值