看到这篇笔记的小伙伴可能会觉得我在做无用功,明明可以通过 STM32CubeMx 软件直接生成的,还在这里慢慢的创建项目。我觉得在学习的时候最好少借助工具,当我们过度依赖工具的时候,决绝问题的能力可能就下降了,所以这是我记录此笔记的主要原因,至少要明白我们都使用了什么文件,在遇到问题的时候可以不那么慌。
由于不使用 STM32CubeMx 软件,所以在使用的时候需要下载 HAL库。

注意:此笔记中使用开发板的是 STM32F103C8T6

一、HAL 库下载

  1. 进入官网:https://www.st.com/content/st_com/zh.html
    STM32新建模板【HAL库】-LMLPHP

  2. 找到自己使用的芯片类型
    STM32新建模板【HAL库】-LMLPHP

  3. 下载自己需要的 HAL 库的版本,点击获取即可
    STM32新建模板【HAL库】-LMLPHP

  4. 解压后目录如下所示:
    STM32新建模板【HAL库】-LMLPHP

二、创建功能模板

  1. 新建一个名为 “stm32_template_hal” 的文件,并在文件中创建相应文件,如下图所示
    STM32新建模板【HAL库】-LMLPHP

  2. 先拷贝 HAL 库到 lib 文件中,文件在 “STM32Cube_FW_F1_V1.8.0\Drivers\STM32F1xx_HAL_Driver”,保证文件命名格式同一,这里我将文件名给为小写了,如下图所示:
    STM32新建模板【HAL库】-LMLPHP
    注意: 其中 STM32F100xX_User_Manual.chm 是 HAL 的 API 文档,至于其中四个文档有啥区别,我还没发现

  3. 在功能的 cmsis 文件中创建如下文件
    STM32新建模板【HAL库】-LMLPHP

  4. 将启动文件拷贝到 startup 中,文件在 “STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates”
    **注意:根据自己的需要拷贝相应的启动文件,这里我使用的是 arm\startup_stm32f103xb.s,如下图所示
    STM32新建模板【HAL库】-LMLPHP

  5. 拷贝 system_stm32f1xx.c 到工程的 stm32_template_hal\cmsis\stm32_drivers\src 文件中,文件在 “STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates”,如下图所示:
    STM32新建模板【HAL库】-LMLPHP

  6. 拷贝相应的头文件到功能的 stm32_template_hal\cmsis\stm32_drivers\inc 文件中,路径在 “STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Include”,如下图所示:
    STM32新建模板【HAL库】-LMLPHP

  7. 拷贝 CMSIS 所需的文件到 stm32_template_hal_aaa\cmsis\core 文件中,文件路径在 “STM32Cube_FW_F1_V1.8.4\Drivers\CMSIS\Core\Include” 文件中,如下图所示:
    STM32新建模板【HAL库】-LMLPHP
    注意:
    STM32新建模板【HAL库】-LMLPHP
    下载①插件时,是 STM32CubeMx 的安装插件,需要安装后才会有 “STM32Cube_FW_F1_V1.8.4\Drivers\CMSIS\Core\Include” 目录,当然步奏7的文件也可以不用拷贝,只需要在想目中添加CMSIS 组件即可
    如果想要找到此步奏的文件,只需要选择②下载即可

  8. 将项目 stm32_template_hal\lib\stm32f1xx_hal_driver\Inc 文件中的 stm32f1xx_hal_conf_template.h 文件复制一份到 stm32_template_hal\application 文件中,并重命名为 stm32f1xx_hal_conf.h,如下图所示:
    STM32新建模板【HAL库】-LMLPHP

  9. 将项目 stm32_template_hal\lib\stm32f1xx_hal_driver\Src 文件中的 stm32f1xx_hal_msp_template.c 文件复制一份到 stm32_template_hal\application 文件中,并重命名为 stm32f1xx_hal_msp.c,如下图所示:
    STM32新建模板【HAL库】-LMLPHP

  10. 在 stm32_template_hal\application 文件中创建 main.c、main.h、stm32f1xx_it.c、stm32f1xx_it.h,如下图所示:
    STM32新建模板【HAL库】-LMLPHP

注意:到此我们需要使用的文件已经拷贝完成了,接下来便可创建工程

三、创建 MDK 工程

  1. 打开Keil软件,创建项目,项目名为STM32F10x_Temp
    STM32新建模板【HAL库】-LMLPHP
    STM32新建模板【HAL库】-LMLPHP
    STM32新建模板【HAL库】-LMLPHP

  2. 添加GROUP,添加GROUP
    STM32新建模板【HAL库】-LMLPHP
    STM32新建模板【HAL库】-LMLPHP
    STM32新建模板【HAL库】-LMLPHP

  3. 勾选 hex 文件生成选项
    STM32新建模板【HAL库】-LMLPHP

  4. 设置头文件路径
    STM32新建模板【HAL库】-LMLPHP

  5. 添加项目所需的宏,USE_HAL_DRIVER,STM32F103xB
    STM32新建模板【HAL库】-LMLPHP

  6. 设置默认编译版本
    STM32新建模板【HAL库】-LMLPHP

四、完成程序

  1. main.c

    
    
    #include "main.h"
    
    
    #define USR_LED_Pin GPIO_PIN_13
    #define USR_LED_GPIO_Port GPIOC
    
    
    void Error_Handler(void);
    
    /**
      * @brief 系统时钟配置
      * @retval None
      */
    void SystemClock_Config(void)
    {
    	RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    	RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    	/* 根据 RCC_OscInitTypeDef 结构中的指定参数初始化RCC振荡器 */
    	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    	RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    	RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    	RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    	RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    	{
    		Error_Handler();
    	}
    	/* 初始化CPU、AHB和APB总线时钟 */
    	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_DIV2;
    	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
    	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    	{
    		Error_Handler();
    	}
    }
    
    /**
     * @brief GPIO初始化功能
     * @param  None
     * @retval None
     */
    static void MX_GPIO_Init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    	/* GPIO Ports Clock Enable */
    	__HAL_RCC_GPIOA_CLK_ENABLE();
    	__HAL_RCC_GPIOB_CLK_ENABLE();
    	__HAL_RCC_GPIOC_CLK_ENABLE();
    	__HAL_RCC_GPIOD_CLK_ENABLE();
    
    	/*Configure GPIO pin Output Level */
    	HAL_GPIO_WritePin(USR_LED_GPIO_Port, USR_LED_Pin, GPIO_PIN_RESET);
    
    	/*Configure GPIO pin : USR_LED_Pin */
    	GPIO_InitStruct.Pin = USR_LED_Pin;
    	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    	GPIO_InitStruct.Pull = GPIO_NOPULL;
    	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    	HAL_GPIO_Init(USR_LED_GPIO_Port, &GPIO_InitStruct);
    
    }
    
    
    
    
    /**
     * @brief  主程序
     * @param  None
     * @retval None
     */
    int main(void)
    {
    	/* 重置所有外围设备,初始化Flash接口和Systick */
    	HAL_Init();
    	
    	/* 配置系统时钟 */
    	SystemClock_Config();
    	
    	/* 初始化GPIO引脚 */
    	MX_GPIO_Init();
    	
    	while (1)
    	{
    		/* 将 LED 灯的状态进行取反 */
    		HAL_GPIO_TogglePin(USR_LED_GPIO_Port, USR_LED_Pin);
    		HAL_Delay(1000);
    	}
    }
    
    
    /**
     * @brief  此功能在发生错误时执行
     * @retval None
     */
    void Error_Handler(void)
    {
    	/* 可以添加自己的实现来报告HAL错误返回状态 */
    	__disable_irq();
    	while (1)
    	{
    		
    	}
    }
    
    
  2. main.h

    
    #ifndef __MAIN_H
    #define __MAIN_H
    
    #include "stm32f1xx_hal.h"
    
    #endif /* __MAIN_H */
    
    
  3. stm32f1xx_it.c

    /**
      ******************************************************************************
      * @file    Templates/Src/stm32f1xx.c
      * @author  MCD Application Team
      * @brief   Main Interrupt Service Routines.
      *          This file provides template for all exceptions handler and 
      *          peripherals interrupt service routine.
      ******************************************************************************
      * @attention
      *
      * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
      * All rights reserved.</center></h2>
      *
      * This software component is licensed by ST under BSD 3-Clause license,
      * the "License"; You may not use this file except in compliance with the
      * License. You may obtain a copy of the License at:
      *                        opensource.org/licenses/BSD-3-Clause
      *
      ******************************************************************************
      */
    
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "stm32f1xx_it.h"
       
    /** @addtogroup STM32F1xx_HAL_Examples
      * @{
      */
    
    /** @addtogroup Templates
      * @{
      */
    
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    
    /* Private function prototypes -----------------------------------------------*/
    /* Private functions ---------------------------------------------------------*/
    
    /******************************************************************************/
    /*            Cortex-M3 Processor Exceptions Handlers                         */
    /******************************************************************************/
    
    /**
      * @brief   This function handles NMI exception.
      * @param  None
      * @retval None
      */
    void NMI_Handler(void)
    {
    }
    
    /**
      * @brief  This function handles Hard Fault exception.
      * @param  None
      * @retval None
      */
    void HardFault_Handler(void)
    {
      /* Go to infinite loop when Hard Fault exception occurs */
      while (1)
      {
      }
    }
    
    /**
      * @brief  This function handles Memory Manage exception.
      * @param  None
      * @retval None
      */
    void MemManage_Handler(void)
    {
      /* Go to infinite loop when Memory Manage exception occurs */
      while (1)
      {
      }
    }
    
    /**
      * @brief  This function handles Bus Fault exception.
      * @param  None
      * @retval None
      */
    void BusFault_Handler(void)
    {
      /* Go to infinite loop when Bus Fault exception occurs */
      while (1)
      {
      }
    }
    
    /**
      * @brief  This function handles Usage Fault exception.
      * @param  None
      * @retval None
      */
    void UsageFault_Handler(void)
    {
      /* Go to infinite loop when Usage Fault exception occurs */
      while (1)
      {
      }
    }
    
    /**
      * @brief  This function handles SVCall exception.
      * @param  None
      * @retval None
      */
    void SVC_Handler(void)
    {
    }
    
    /**
      * @brief  This function handles Debug Monitor exception.
      * @param  None
      * @retval None
      */
    void DebugMon_Handler(void)
    {
    }
    
    /**
      * @brief  This function handles PendSVC exception.
      * @param  None
      * @retval None
      */
    void PendSV_Handler(void)
    {
    }
    
    /**
      * @brief  This function handles SysTick Handler.
      * @param  None
      * @retval None
      */
    void SysTick_Handler(void)
    {
      HAL_IncTick();
    }
    
    /******************************************************************************/
    /*                 STM32F1xx Peripherals Interrupt Handlers                   */
    /*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
    /*  available peripheral interrupt handler's name please refer to the startup */
    /*  file (startup_stm32f1xx.s).                                               */
    /******************************************************************************/
    
    /**
      * @brief  This function handles PPP interrupt request.
      * @param  None
      * @retval None
      */
    /*void PPP_IRQHandler(void)
    {
    }*/
    
    
    /**
      * @}
      */ 
    
    /**
      * @}
      */
    
    /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    
  4. stm32f1xx_it.h

    /**
      ******************************************************************************
      * @file    Templates/Inc/stm32f1xx_it.h
      * @author  MCD Application Team
      * @brief   This file contains the headers of the interrupt handlers.
      ******************************************************************************
      * @attention
      *
      * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
      * All rights reserved.</center></h2>
      *
      * This software component is licensed by ST under BSD 3-Clause license,
      * the "License"; You may not use this file except in compliance with the
      * License. You may obtain a copy of the License at:
      *                        opensource.org/licenses/BSD-3-Clause
      *
      ******************************************************************************
      */
    
    /* Define to prevent recursive inclusion -------------------------------------*/
    #ifndef __STM32F1xx_IT_H
    #define __STM32F1xx_IT_H
    
    #ifdef __cplusplus
     extern "C" {
    #endif 
    
    /* Includes ------------------------------------------------------------------*/
    /* Exported types ------------------------------------------------------------*/
    /* Exported constants --------------------------------------------------------*/
    /* Exported macro ------------------------------------------------------------*/
    /* Exported functions ------------------------------------------------------- */
    
    void NMI_Handler(void);
    void HardFault_Handler(void);
    void MemManage_Handler(void);
    void BusFault_Handler(void);
    void UsageFault_Handler(void);
    void SVC_Handler(void);
    void DebugMon_Handler(void);
    void PendSV_Handler(void);
    void SysTick_Handler(void);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* __STM32F1xx_IT_H */
    
    /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
    
    

五、常见问题

  1. 程序在 HAL_Delay 延时函数中卡死,是因为没有定义 void SysTick_Handler(void) 中断函数
04-13 03:41