野火STM32_HAL库版课程笔记-手动建立工程模板与CubeMX后续用法(重要)

前置介绍

为什么要手动建立工程模板?

"CubeMX 是一个开发工具, 并不是开发本身, 学会借助它的便利, 而不依赖它的结构, 这是我们迈向高级开发者的关键的一步"

新建工程简要步骤

手动建立工程

1. 新建工程文件夹
2. 拷贝文件
2.1. 参考目录, 文件结构

对于 Inc 和 Src 等文件夹直接 copy 文件夹即可, 不需要一个个 copy 里面的具体文件

复制代码
手动创建HAL库模板/
├── Doc/                           # 文档目录
│   └── readme.txt                 # 项目说明文档
│
├── Libraries/                     # 库文件目录
│   ├── CMSIS/                     # ARM Cortex-M 软件接口标准
│   │   ├── Device/
│   │   │   └── ST/
│   │   │       └── STM32F1xx/     # STM32F1 系列设备文件
│   │   │           ├── Include/   # 头文件
│   │   │           │   ├── stm32f1xx.h              # STM32F1xx 主头文件
│   │   │           │   ├── system_stm32f1xx.h       # 系统配置文件
│   │   │           │   └── stm32f103xb.h            # 具体型号头文件 (F103C8T6)
│   │   │           └── Source/
│   │   │               └── Templates/               # 启动模板
│   │   │                   ├── arm/                 # ARM 编译器启动文件
│   │   │                   ├── gcc/                 # GCC 启动文件 + 链接脚本
│   │   │                   ├── iar/                 # IAR 启动文件 + 链接脚本
│   │   │                   └── system_stm32f1xx.c   # 系统初始化文件
│   │   └── Include/               # CMSIS 核心头文件
│   │       ├── core_cm3.h         # Cortex-M3 核心定义
│   │       ├── cmsis_compiler.h   # 编译器抽象层
│   │       ├── cmsis_gcc.h        # GCC 编译器支持
│   │       └── ...                # 其他核心头文件
│   │
│   └── STM32F1xx_HAL_Driver/      # STM32 HAL 驱动库
│       ├── Inc/                   # HAL 库头文件
│       │   ├── stm32f1xx_hal.h              # HAL 库主头文件
│       │   ├── stm32f1xx_hal_conf_template.h # 配置文件模板
│       │   ├── stm32f1xx_hal_gpio.h         # GPIO 驱动
│       │   ├── stm32f1xx_hal_rcc.h          # RCC 时钟驱动
│       │   ├── stm32f1xx_hal_tim.h          # 定时器驱动
│       │   ├── stm32f1xx_hal_uart.h         # UART 驱动
│       │   ├── stm32f1xx_hal_spi.h          # SPI 驱动
│       │   ├── stm32f1xx_hal_i2c.h          # I2C 驱动
│       │   ├── stm32f1xx_hal_adc.h          # ADC 驱动
│       │   ├── stm32f1xx_hal_dma.h          # DMA 驱动
│       │   ├── stm32f1xx_hal_flash.h        # Flash 驱动
│       │   ├── stm32f1xx_hal_pwr.h          # 电源管理
│       │   ├── stm32f1xx_hal_cortex.h       # Cortex 内核驱动
│       │   ├── Legacy/                      # 传统 API 兼容头文件
│       │   └── stm32f1xx_ll_*.h             # LL 库头文件 (底层驱动)
│       │
│       └── Src/                   # HAL 库源文件
│           ├── stm32f1xx_hal.c              # HAL 核心
│           ├── stm32f1xx_hal_cortex.c       # Cortex 驱动
│           ├── stm32f1xx_hal_rcc.c          # RCC 驱动
│           ├── stm32f1xx_hal_gpio.c         # GPIO 驱动
│           ├── stm32f1xx_hal_tim.c          # 定时器驱动
│           ├── stm32f1xx_hal_uart.c         # UART 驱动
│           ├── stm32f1xx_hal_spi.c          # SPI 驱动
│           ├── stm32f1xx_hal_i2c.c          # I2C 驱动
│           ├── stm32f1xx_hal_adc.c          # ADC 驱动
│           ├── stm32f1xx_hal_dma.c          # DMA 驱动
│           ├── stm32f1xx_hal_flash.c        # Flash 驱动
│           ├── stm32f1xx_hal_pwr.c          # 电源管理
│           ├── stm32f1xx_it.c               # 中断服务函数
│           ├── system_stm32f1xx.c           # 系统初始化
│           ├── Legacy/                      # 传统 API 源文件
│           └── stm32f1xx_ll_*.c             # LL 库源文件
│
├── Project/                       # Keil 项目文件目录
│   ├── DebugConfig/               # 调试配置
│   │   └── Target_1_STM32F103C8_1.0.0.dbgconf  # 调试目标配置
│   ├── Listings/                  # 编译列表文件
│   │   └── Fire_F103.map          # 链接映射文件
│   ├── Objects/                   # 编译输出文件
│   │   ├── Fire_F103.axf          # 可执行文件
│   │   ├── Fire_F103.hex          # HEX 烧录文件
│   │   ├── Fire_F103.build_log.htm  # 编译日志
│   │   ├── *.o                    # 目标文件
│   │   ├── *.d                    # 依赖文件
│   │   └── *.crf                  # 交叉引用文件
│   ├── Fire_F103.uvprojx          # Keil 项目文件
│   ├── Fire_F103.uvoptx           # Keil 项目选项
│   └── Fire_F103.uvguix.HeartacheBoy  # Keil 用户界面配置
│
└── User/                          # 用户应用代码
    ├── main.c                     # 主程序入口
    ├── main.h                     # 主程序头文件
    ├── stm32f1xx_hal_conf.h       # HAL 库配置文件
    ├── stm32f1xx_it.c             # 中断服务函数实现
    ├── stm32f1xx_it.h             # 中断服务函数声明
    └── system_stm32f1xx.c         # 系统时钟配置
3. 新建工程框架
4. 添加分组及文件
5. 魔术棒设置
5.1.1. Target
5.1.2. Output
5.1.3. Listing
5.1.4. C/C++
5.1.5. Debug

工程代码部分

复制代码
/**
  * @brief  模板
  */

#include "main.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* Private functions ---------------------------------------------------------*/

int main(void)
{
  
  HAL_Init(); // 初始化 HAL 库

  SystemClock_Config(); // 配置系统时钟, 设置为 72MHz 
    
  while (1)
  {
    
  }
}

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 72000000
  *            HCLK(Hz)                       = 72000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            HSE Frequency(Hz)              = 8000000
  *            HSE PREDIV1                    = 1
  *            PLLMUL                         = 9
  *            Flash Latency(WS)              = 2
  * @param  None
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef clkinitstruct = {0};
  RCC_OscInitTypeDef oscinitstruct = {0};
  
  /* Enable HSE Oscillator and activate PLL with HSE as source */
  oscinitstruct.OscillatorType  = RCC_OSCILLATORTYPE_HSE;
  oscinitstruct.HSEState        = RCC_HSE_ON;
  oscinitstruct.HSEPredivValue  = RCC_HSE_PREDIV_DIV1;
  oscinitstruct.PLL.PLLState    = RCC_PLL_ON;
  oscinitstruct.PLL.PLLSource   = RCC_PLLSOURCE_HSE;
  oscinitstruct.PLL.PLLMUL      = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK)
  {
    /* Initialization Error */
    while(1);
  }

  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
  clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;  
  if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK)
  {
    /* Initialization Error */
    while(1);
  }
}

修改完之后, 编译, 下载.

如果下载成功, 说明配置成功.

点灯测试

写个简单的点灯程序测试能否正常运行.

复制代码
/**
  * @brief  模板
  */

#include "main.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* Private functions ---------------------------------------------------------*/

int main(void)
{
  
  HAL_Init(); // 初始化 HAL 库

  SystemClock_Config(); // 配置系统时钟, 设置为 72MHz 
  
  __HAL_RCC_GPIOA_CLK_ENABLE();
  
  GPIO_InitTypeDef GPIO_PIN_LED_G;
  GPIO_PIN_LED_G.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_PIN_LED_G.Pin = GPIO_PIN_2;
  GPIO_PIN_LED_G.Speed = GPIO_SPEED_FREQ_HIGH;
  
  HAL_GPIO_Init(GPIOA, &GPIO_PIN_LED_G);
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);

  while (1)
  {
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2);
    HAL_Delay(500);
  }
}

/**
  * @brief  System Clock Configuration
  *         The system Clock is configured as follow : 
  *            System Clock source            = PLL (HSE)
  *            SYSCLK(Hz)                     = 72000000
  *            HCLK(Hz)                       = 72000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            HSE Frequency(Hz)              = 8000000
  *            HSE PREDIV1                    = 1
  *            PLLMUL                         = 9
  *            Flash Latency(WS)              = 2
  * @param  None
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef clkinitstruct = {0};
  RCC_OscInitTypeDef oscinitstruct = {0};
  
  /* Enable HSE Oscillator and activate PLL with HSE as source */
  oscinitstruct.OscillatorType  = RCC_OSCILLATORTYPE_HSE;
  oscinitstruct.HSEState        = RCC_HSE_ON;
  oscinitstruct.HSEPredivValue  = RCC_HSE_PREDIV_DIV1;
  oscinitstruct.PLL.PLLState    = RCC_PLL_ON;
  oscinitstruct.PLL.PLLSource   = RCC_PLLSOURCE_HSE;
  oscinitstruct.PLL.PLLMUL      = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK)
  {
    /* Initialization Error */
    while(1);
  }

  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 
     clocks dividers */
  clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
  clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;  
  if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK)
  {
    /* Initialization Error */
    while(1);
  }
}

这里有个注意点:

在STM32中,为了降低功耗,所有外设(包括GPIO端口)的时钟在默认情况下都是关闭的。

必须先手动开启对应端口的时钟,才能对其进行配置和操作。

例如: 使用 GPIOA , 那么就要使用 __HAL_RCC_GPIOA_CLK_ENABLE();

测试程序现象
相关推荐
可乐鸡翅好好吃6 小时前
UUID----私有服务与公有服务
嵌入式硬件
Wave8456 小时前
Freertos中PendSV与sysTick
单片机·嵌入式硬件
Ztopcloud极拓云视角6 小时前
Gemini 3.1 Pro vs GPT-5.4 Pro:API成本1/3、性能差多少?选型实测笔记
人工智能·笔记·gpt·ai·语言模型
jghhh016 小时前
带红外抄板和LCD显示的单相电能表设计
stm32·单片机·嵌入式硬件
wggmrlee7 小时前
GD32 vs STM32
单片机·嵌入式硬件
czhaii8 小时前
STM32 F103 Altium一键下载PCB图
stm32·单片机·嵌入式硬件
雾削木8 小时前
基于STM32F411RET6 + 双路MB85RS2MT的铁电U盘
stm32·单片机·嵌入式硬件
笨笨饿8 小时前
33_顺序表(待完善)
linux·服务器·c语言·嵌入式硬件·算法·学习方法
点灯小铭8 小时前
基于单片机的多路温湿度采集与WIFI智能报警控制系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业