STM32L475基于HAL库封装时钟管理模块

创建基于HAL库的空项目

为了更贴近实际生产的项目结构, 修改项目目录结构

创建目录结构如下:

复制代码
├─Drivers ----------------------------- 官方HAL库, SMSIS启动文件等
│  ├─CMSIS
│  │  └─Include
│  └─STM32L4xx_HAL_Driver ------------- HAL库
│      ├─Inc
│      └─Src
├─Inc  -------------------------------- 应用头文件
├─MDK-ARM ----------------------------- Keil工程及编译中间文件
└─Src --------------------------------- 应用源文件
拷贝文件

From:
stm32cubel4_v1-18-0\STM32Cube_FW_L4_V1.18.0\Drivers\CMSIS\Include

拷贝整个Include文件夹

To:
Test04\Drivers\CMSIS\Include


From:
stm32cubel4_v1-18-0\STM32Cube_FW_L4_V1.18.0\Drivers\CMSIS\Device\ST\STM32L4xx\Include

在这个目录下拷贝如下3个文件

复制代码
stm32l4xx.h
stm32l475xx.h
system_stm32l4xx.h

To:
Test04\Drivers\CMSIS\Include


From:
stm32cubel4_v1-18-0\STM32Cube_FW_L4_V1.18.0\Drivers\CMSIS\Device\ST\STM32L4xx\Source\Templates\arm\startup_stm32l475xx.s

To:
Test04\Drivers\CMSIS\Include


From:
stm32cubel4_v1-18-0\STM32Cube_FW_L4_V1.18.0\Drivers\STM32L4xx_HAL_Driver\Inc
stm32cubel4_v1-18-0\STM32Cube_FW_L4_V1.18.0\Drivers\STM32L4xx_HAL_Driver\Src

Inc和Src目录整体拷贝

To:
Test04\Drivers\STM32L4xx_HAL_Driver


From:
stm32cubel4_v1-18-0\STM32Cube_FW_L4_V1.18.0\Drivers\CMSIS\Device\ST\STM32L4xx\Source\Templates\system_stm32l4xx.c

To:

重命名为 stm32l4xx_hal_conf.h
Test05\Inc\stm32l4xx_hal_conf.h


From:
stm32cubel4_v1-18-0\STM32Cube_FW_L4_V1.18.0\Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_hal_conf_template.h

To:
Test05\Inc\stm32l4xx_hal_conf.h

编写代码

stm32-world\Test04\Inc\main.h

c 复制代码
#ifndef MAIN_H
#define MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32l4xx_hal.h"


#ifdef __cplusplus
}
#endif

#endif

stm32-world\Test04\Src\main.c

c 复制代码
#include "main.h"

int main(void) {
    HAL_Init();           // 1. 初始化HAL库(配置SysTick等)
    
    while (1) {
        
    }
}

stm32-world\Test04\Inc\stm32l4xx_it.h

c 复制代码
#ifndef __STM32L4xx_IT_H
#define __STM32L4xx_IT_H

#ifdef __cplusplus
 extern "C" {
#endif

/* 核心:SysTick 中断,每 1ms 触发一次,用于 HAL_Delay() */
void SysTick_Handler(void);

#ifdef __cplusplus
}
#endif

#endif /* __STM32L4xx_IT_H */

stm32-world\Test04\Src\stm32l4xx_it.c

c 复制代码
#include "stm32l4xx_it.h"
#include "stm32l4xx_hal.h"

void SysTick_Handler(void) {
    HAL_IncTick(); // 每1ms触发一次,增加HAL计数值
}

系统时钟初始化

使用HAL库实现前文:
STM32L475基于完全空白的项目,完成时钟树初始化配置并验证

同样的操作.

bsp_clock.c

c 复制代码
#include "bsp_clock.h"
#include "stm32l4xx_hal.h"
#include "stm32l4xx_hal_rcc.h"
#include "stm32l4xx_hal_pwr.h"
#include "stm32l4xx_hal_flash.h"

/**
 * @brief 系统时钟 HSE (8MHz) -> PLL -> 80MHz
 */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /* 1. 配置主调压器输出电压以支持 80MHz 频率 (Range 1) */
    __HAL_RCC_PWR_CLK_ENABLE();
    
    if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) {
        // TODO:: 错误处理
        // Error_Handler();
    }

    /* 2. 配置 HSE 并初始化 PLL */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 选择晶振类型为外部高速晶振
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;                   // 开启外部晶振
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;               // 开启PLL锁相环
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;       // PLL时钟源为外部晶振

    /* 8MHz(HSE) / 1(M) * 20(N) / 2(R) = 80MHz */
    RCC_OscInitStruct.PLL.PLLM = 1;
    RCC_OscInitStruct.PLL.PLLN = 20;
    RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
    RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;

    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        // TODO:: 错误处理
        // Error_Handler();
    }

    /* 3. 配置系统时钟源 (SYSCLK) 及总线分频 */
    RCC_ClkInitStruct.ClockType =   RCC_CLOCKTYPE_HCLK
                                  | RCC_CLOCKTYPE_SYSCLK
                                  | RCC_CLOCKTYPE_PCLK1
                                  | RCC_CLOCKTYPE_PCLK2;      // 指定分频操作所覆盖的总线类型
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 选择PLL为主时钟

    // 显式地设置AHB和APB预分频器对应的总线频率
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;   // 80MHz
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;    // 80MHz
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;    // 80MHz

    /* 4. 设置 Flash 等待周期 */
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
    {
        // TODO:: 错误处理
        // Error_Handler();
    }
    
}

上述代码需要注意的是, 引入头文件时有顺序要求, 先引入stm32l4xx_hal.h, 然后再引入其他, 否则会报编译错误.

bsp_clock.h

c 复制代码
#ifndef __BSP_CLOCK_H
#define __BSP_CLOCK_H

void SystemClock_Config(void);

#endif
相关推荐
悠哉悠哉愿意2 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
Lester_11012 天前
STM32霍尔传感器输入口设置为复用功能输入口时,还能用GPIO函数直接读取IO的状态吗
stm32·单片机·嵌入式硬件·电机控制
LCG元2 天前
低功耗显示方案:STM32L0驱动OLED,动态波形绘制与优化
stm32·嵌入式硬件·信息可视化
三佛科技-187366133972 天前
120W小体积碳化硅电源方案(LP8841SC极简方案12V10A/24V5A输出)
单片机·嵌入式硬件
z20348315202 天前
STM32F103系列单片机定时器介绍(二)
stm32·单片机·嵌入式硬件
古译汉书2 天前
【IoT死磕系列】Day 7:只传8字节怎么控机械臂?学习工业控制 CANopen 的“对象字典”(附企业级源码)
数据结构·stm32·物联网·http
Alaso_shuang2 天前
STM32 核心输入、输出模式
stm32·单片机·嵌入式硬件
脚后跟2 天前
AI助力嵌入式物联网项目全栈开发
嵌入式硬件·物联网·ai编程
2501_918126912 天前
stm32死锁是怎么实现的
stm32·单片机·嵌入式硬件·学习·个人开发
z20348315202 天前
STM32F103系列单片机定时器介绍(一)
stm32·单片机