看到这篇笔记的小伙伴可能会觉得我在做无用功,明明可以通过 STM32CubeMx 软件直接生成的,还在这里慢慢的创建项目。我觉得在学习的时候最好少借助工具,当我们过度依赖工具的时候,决绝问题的能力可能就下降了,所以这是我记录此笔记的主要原因,至少要明白我们都使用了什么文件,在遇到问题的时候可以不那么慌。
由于不使用 STM32CubeMx 软件,所以在使用的时候需要下载 HAL库。
注意:此笔记中使用开发板的是 STM32F103C8T6
一、HAL 库下载
找到自己使用的芯片类型
下载自己需要的 HAL 库的版本,点击获取即可
解压后目录如下所示:
二、创建功能模板
新建一个名为 “stm32_template_hal” 的文件,并在文件中创建相应文件,如下图所示
先拷贝 HAL 库到 lib 文件中,文件在 “STM32Cube_FW_F1_V1.8.0\Drivers\STM32F1xx_HAL_Driver”,保证文件命名格式同一,这里我将文件名给为小写了,如下图所示:
注意: 其中 STM32F100xX_User_Manual.chm 是 HAL 的 API 文档,至于其中四个文档有啥区别,我还没发现在功能的 cmsis 文件中创建如下文件
将启动文件拷贝到 startup 中,文件在 “STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates”
**注意:根据自己的需要拷贝相应的启动文件,这里我使用的是 arm\startup_stm32f103xb.s,如下图所示拷贝 system_stm32f1xx.c 到工程的
stm32_template_hal\cmsis\stm32_drivers\src
文件中,文件在 “STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Source\Templates”,如下图所示:拷贝相应的头文件到功能的
stm32_template_hal\cmsis\stm32_drivers\inc
文件中,路径在 “STM32Cube_FW_F1_V1.8.0\Drivers\CMSIS\Device\ST\STM32F1xx\Include”,如下图所示:拷贝 CMSIS 所需的文件到 stm32_template_hal_aaa\cmsis\core 文件中,文件路径在 “STM32Cube_FW_F1_V1.8.4\Drivers\CMSIS\Core\Include” 文件中,如下图所示:
注意:
下载①插件时,是 STM32CubeMx 的安装插件,需要安装后才会有 “STM32Cube_FW_F1_V1.8.4\Drivers\CMSIS\Core\Include” 目录,当然步奏7的文件也可以不用拷贝,只需要在想目中添加CMSIS 组件即可
如果想要找到此步奏的文件,只需要选择②下载即可将项目 stm32_template_hal\lib\stm32f1xx_hal_driver\Inc 文件中的
stm32f1xx_hal_conf_template.h
文件复制一份到 stm32_template_hal\application 文件中,并重命名为 stm32f1xx_hal_conf.h,如下图所示:将项目 stm32_template_hal\lib\stm32f1xx_hal_driver\Src 文件中的
stm32f1xx_hal_msp_template.c
文件复制一份到 stm32_template_hal\application 文件中,并重命名为 stm32f1xx_hal_msp.c,如下图所示:在 stm32_template_hal\application 文件中创建 main.c、main.h、stm32f1xx_it.c、stm32f1xx_it.h,如下图所示:
注意:到此我们需要使用的文件已经拷贝完成了,接下来便可创建工程
三、创建 MDK 工程
打开Keil软件,创建项目,项目名为STM32F10x_Temp
添加GROUP,添加GROUP
勾选 hex 文件生成选项
设置头文件路径
添加项目所需的宏,USE_HAL_DRIVER,STM32F103xB
设置默认编译版本
四、完成程序
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) { } }
main.h
#ifndef __MAIN_H #define __MAIN_H #include "stm32f1xx_hal.h" #endif /* __MAIN_H */
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>© 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****/
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>© 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****/
五、常见问题
- 程序在 HAL_Delay 延时函数中卡死,是因为没有定义 void SysTick_Handler(void) 中断函数