5.2、STM32Cube和HAL库使用初体验

5.2.1、STM32Cube和HAL库模式开发流程

    5.2.1.1、流程介绍

    (1)环境搭建:STM32CubeMX安装、STM32xxFW安装、MDK5安装、pack包安装

    (2)STM32CubeMX中创建工程、选择芯片型号、做图形化配置

    (3)生成MDK版Project

    (4)MDK5中打开Project,开始正式开发

     5.2.1.2、实战演练

       (1)打开stm32CubeMX软件后,new Project(创建工程)

       (2)MCU Selector(mcu型号选择:stm32L476RGT6),设置好后点击:Part No下面对应的型号“双击”。

       (3)四个系列设置:Pinout(引脚设置)、Clock Configuration(时钟配置)、Configuration(外设使能配置)、Power Consumption Calculator.(功耗计算)

        (4)配置好后,在菜单栏中点击“project”-“setting”

                    project Nama(工程名字)/Project Location(工程地址)/Toolchain IDE(MDK-arm V5)

        (5)生成工程项目:Generate code

     5.2.1.3、几个小细节

    (1)自动生成的Project目录结构和名字等都是既定的,最好不要改。

    (2)由CubeMX工程到MDK工程师单向的,不能逆向同步

    (3)最好在CubeMX中一次配完一个模块,在生成MDK工程,因为如果再次生成则会覆盖掉之前生成的MDK工程中同一个模块c文件,这样如果你刚好又已经编辑过了那部分就丢了

    (4)STM32CubeMX工具只是生成工程和外设初始代码,大量开发工作还是要靠自己的。

    (5)HAL库是一套体系,有自己的架构,必须理解透彻,否则会无处下爪的感觉

    (6)因为HAL库很庞大,整个编译一次很久,所以建议要点build而不是rebuild


5.2.2、STM32CubeMX生成的工程解读

     5.2.2.1、工程目录介绍

            (1)查看stm32CubeMX生成的工程文件

                    ·Drivers

                           ·CMSIS

                                ·Device

                                ·DSP_Lib

                                ·Include

                                ·Lib

                                ·RTOS

                           ·STM32L4xx_HAL_Driver

                                ·Inc

                                ·Src

                    ·Inc

                            main.h

                            stm32l4xx_hal_conf.h

                            stm32l4xx_it.h

                    ·MDK-ARM

                            ·DebugConfig

                            ·RTE

                            ·TEST

                            TEST.uvprojx

                    ·Src

                            main.c

                            stm32l4xx_hal_msp.c

                            stm32l4xx_it.c

                            system_stm32l4xx.c          

     5.2.2.2、工程配置项细节

     5.2.2.3、源码分析与学习方法

    (1)先理清条理,搞清楚是怎么从Cube配置到MDK工程的

    (2)建立SI工程,协助分析HAL库源码

    (3)先从时钟、gpio等模块学起,掌握这套体系架构

    (4)逐步扩展到其他外设模块,学习HAL库的使用

5.2.3、STM32HAL源码分析1 

     5.2.3.1、SI工程建立

     5.2.3.2、从启动代码开始

     5.2.3.3、main函数分析

*************************************************************************************************************************

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

******************************************************************************************************************

5.2.4、STM32HAL源码分析2   

    5.2.4.1、HAL_Init函数详解

*****************************************************************************************************************

HAL_StatusTypeDef HAL_Init(void)
{
  /* Configure Flash prefetch, Instruction cache, Data cache */
  /* Default configuration at reset is:                      */
  /* - Prefetch disabled                                           */
  /* - Instruction cache enabled                              */
  /* - Data cache enabled                                        */
#if (INSTRUCTION_CACHE_ENABLE == 0)
   __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();

#endif /* INSTRUCTION_CACHE_ENABLE */

#if (DATA_CACHE_ENABLE == 0)
   __HAL_FLASH_DATA_CACHE_DISABLE();
#endif /* DATA_CACHE_ENABLE */

#if (PREFETCH_ENABLE != 0)
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */

  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
  HAL_InitTick(TICK_INT_PRIORITY);

  /* Init the low level hardware */
  HAL_MspInit();

  /* Return function status */
  return HAL_OK;

}

********************************************************************************************************************

5.2.5、STM32HAL源码分析3

     5.2.5.1、SystemClock_Config

*******************************************************************************************************************

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  /**Initializes the CPU, AHB and APB busses clocks */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
  RCC_OscInitStruct.PLL.PLLM = 1;
  RCC_OscInitStruct.PLL.PLLN = 40;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);

  }

    /**Configure the main internal regulator output voltage  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time  */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

}

***************************************************************************************************************

     5.2.5.2、MX_GPIO_Init

***************************************************************************************************************

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */

  __HAL_RCC_GPIOC_CLK_ENABLE();

/*

do { \
                  __IO uint32_t tmpreg; \
                  SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \
                  /* Delay after an RCC peripheral clock enabling */ \
                                                 tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \
                                                 UNUSED(tmpreg); \
                                               } while(0)

  __HAL_RCC_GPIOH_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOH, GPIO_PIN_0, GPIO_PIN_RESET);

  /*Configure GPIO pin : PC14 */
  GPIO_InitStruct.Pin = GPIO_PIN_14;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PC15 */
  GPIO_InitStruct.Pin = GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PH0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

}

do { \
                                                 __IO uint32_t tmpreg; \
                                                 SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \
                                                 /* Delay after an RCC peripheral clock enabling */ \
                                                 tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); \
                                                 UNUSED(tmpreg); \
                                               } while(0)

********************************************************************************************************

5.2.6、STM32Cube和HAL库点亮LED实战

     5.2.6.1、在CubeMX工具中的开发

        (1)查看原理图确定LED对应的GPIO号,USE_LED对应PB2

        (2)CubeMX新建工程兵配置GPIO

        (3)配置工程,并生成MDK project

     5.2.6.2、在MDK5中开发

        (1)找到main函数中的while处

        (2)查看GPIO的HAL库函数,添加LED操作代码

*******************************************************************************************************

//500ms点亮一次LED灯。

              while (1)
  {
HAL_GPIO_WritePin(USR_LED_GPIO_Port, USR_LED_Pin, GPIO_PIN_RESET);
  /* USER CODE END WHILE */
HAL_Delay(500);
  /* USER CODE BEGIN 3 */
HAL_GPIO_WritePin(USR_LED_GPIO_Port, USR_LED_Pin, GPIO_PIN_SET);
HAL_Delay(500);

  }

********************************************************************************************************

        (3)精确延时用HAL_Delay函数

*******************************************************************************************************

#define HAL_MAX_DELAY      0xFFFFFFFFU

__weak uint32_t HAL_GetTick(void)
{
      return uwTick;
}

__weak void HAL_Delay(uint32_t Delay)
{
      uint32_t tickstart = HAL_GetTick();
      uint32_t wait = Delay;

      /* Add a period to guaranty minimum wait */
      if (wait < HAL_MAX_DELAY)
      {
        wait++;
      } 
      while((HAL_GetTick() - tickstart) < wait)
      {
      }

}

*************************************************************************************************

     5.2.6.3、烧录到开发板并运行

        (1)STLINK接线(SWDIO、SWCLK、GND)

        (2)MDK中debug中配置是用STLINK调试和下载,注意选择正确的flash烧录算法

        (3)烧录并运行,注意板子供电用CROUSB或电池供电

5.2.7、STM32Cube和HAL库时钟设置实战

    5.2.7.1、实验1:更改时钟频率设置

        (1)先备份原来的main.c和其他时钟相关部分

        (2)更改主时钟到80MHz并重新生产工程,重新编译烧录运行看效果

        (3)对比新生成的时钟代码部分和以前的

        (4)额外实验:可以在main.c的while循环中各部分添加自定义代码,看哪些不会被覆盖

     5.2.7.2、实验2:使用外部晶振

        (1):打开HSE实验

        (2):打开LSE实验

5.2.8、STM32Cube和HAL库GPIO实战

    5.2.8.1、HAL库中GPIO驱动详解

********************************************************************************************************

void              HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init);
void              HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin);

/** @addtogroup GPIO_Exported_Functions_Group2 IO operation functions 

/* IO operation functions *****************************************************/
GPIO_PinState     HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void              HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
void              HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void              HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);

void              HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);

*****************************************************************************************************

    5.2.8.2、GPIO实战

    (1)保存初始MDK工程

    (2)查看原理图确定其余2个LED的引脚:SD_EN对应PA15,GPS_EN对应的PB12

    (3)在CubeMX中配置

    (4)重新生成MDK project

    (5)对比新生成的GPIO部分代码和以前的

    (6)编译烧录执行验证

5.2.9、HAL库体系的头文件包含

(1)分析main.h

(2)分析STM32L4xx_hal.h

    5.2.9.1、从main包含的头文件说起

    第一条线:main.c中包含stm32L4xx_hal.h,再包含了stm32L4xx_hal_conf.h,然后再包含了各个模块的hal库头文件。

    第二条线:只要包含了stm32L4xx.h,就会间接包含到所对应系列型号的STM32L4476xx.h

    stm32L4xx_gpio.h->stm32L4_hal_def.h->stm32L4xx.h->stm32L476xx.h

    

你可能感兴趣的:(5.2、STM32Cube和HAL库使用初体验)