/**
******************************************************************************
* @file stm32f1xx_hal.c
* @author MCD Application Team
* @brief HAL 模块驱动
* 这是 HAL 初始化的通用部分
*
@verbatim
==============================================================================
##### 如何使用本驱动 #####
==============================================================================
[..]
HAL 通用驱动包含一组通用 API,可被外设驱动和用户用于启动 HAL
[..]
HAL 包含两类 API:
(+) 通用 HAL API
(+) 服务类 HAL API
@endverbatim
******************************************************************************
* @attention
*
* <h2><center>© 版权所有 (c) 2016 STMicroelectronics.
* 保留所有权利。</center></h2>
*
* 本软件组件遵循 BSD 3-Clause 许可证协议,
* 即"许可证";除非符合许可证,否则不得使用本文件。
* 您可以在以下网址获取许可证副本:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* 包含头文件 ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/** @addtogroup STM32F1xx_HAL_Driver
* @{
*/
/** @defgroup HAL HAL
* @brief HAL 模块驱动
* @{
*/
#ifdef HAL_MODULE_ENABLED
/* 私有类型定义 -----------------------------------------------------------*/
/* 私有宏定义 ------------------------------------------------------------*/
/** @defgroup HAL_Private_Constants HAL 私有常量
* @{
*/
/**
* @brief STM32F1xx HAL 驱动版本号 V1.1.7
*/
#define __STM32F1xx_HAL_VERSION_MAIN (0x01U) /*!< [31:24] 主版本号 */
#define __STM32F1xx_HAL_VERSION_SUB1 (0x01U) /*!< [23:16] 子版本号1 */
#define __STM32F1xx_HAL_VERSION_SUB2 (0x07U) /*!< [15:8] 子版本号2 */
#define __STM32F1xx_HAL_VERSION_RC (0x00U) /*!< [7:0] 发布候选版本 */
#define __STM32F1xx_HAL_VERSION ((__STM32F1xx_HAL_VERSION_MAIN << 24)\
|(__STM32F1xx_HAL_VERSION_SUB1 << 16)\
|(__STM32F1xx_HAL_VERSION_SUB2 << 8 )\
|(__STM32F1xx_HAL_VERSION_RC))
#define IDCODE_DEVID_MASK 0x00000FFFU
/**
* @}
*/
/* 私有宏定义 -------------------------------------------------------------*/
/* 私有变量 ---------------------------------------------------------*/
/** @defgroup HAL_Private_Variables HAL 私有变量
* @{
*/
__IO uint32_t uwTick; /* 系统节拍计数器 */
uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS); /* 无效优先级 */
HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 默认 1KHz */
/**
* @}
*/
/* 私有函数原型声明 -----------------------------------------------*/
/* 导出函数 ---------------------------------------------------------*/
/** @defgroup HAL_Exported_Functions HAL 导出函数
* @{
*/
/** @defgroup HAL_Exported_Functions_Group1 初始化和反初始化函数
* @brief 初始化和反初始化函数
*
@verbatim
===============================================================================
##### 初始化和反初始化函数 #####
===============================================================================
[..] 本部分提供以下功能:
(+) 初始化 Flash 接口、NVIC 分配和初始时钟配置。当需要超时功能时初始化 SysTick,
并在启用时初始化备份域。
(+) 反初始化 HAL 通用部分
(+) 配置时基源以生成 1ms 时基,并指定滴答中断优先级
(++) 默认使用 SysTick 定时器作为时基源,但用户也可根据需要实现自己的时基源
(如通用定时器或其他时基源),需注意时基周期应保持 1ms,因为 PPP_TIMEOUT_VALUE
等宏定义以毫秒为单位处理。
(++) 时基配置函数(HAL_InitTick())会在程序启动时由 HAL_Init() 自动调用,或在时钟配置时
由 HAL_RCC_ClockConfig() 调用。
(++) 时基源被配置为定期生成中断。如果从外设 ISR 中调用 HAL_Delay(),需确保滴答中断线优先级
(数值上更低)高于外设中断,否则调用者 ISR 会被阻塞。
(++) 影响时基配置的函数声明为 __weak,以便用户在其他文件中覆盖实现。
@endverbatim
* @{
*/
/**
* @brief 初始化 HAL 库,必须是主程序中第一个执行的指令(在调用其他 HAL 函数之前)。
* 执行以下操作:
* 配置 Flash 预取缓冲
* 使用 HSI 时钟配置 SysTick 每 1 毫秒产生中断(此时时钟尚未配置,系统运行在 16MHz HSI)
* 设置 NVIC 优先级分组为 4
* 调用用户文件中的 HAL_MspInit() 回调函数进行底层硬件初始化
* @note SysTick 用作 HAL_Delay() 的时基源,应用需确保 SysTick 时基始终设置为 1 毫秒
* @retval HAL 状态
*/
HAL_StatusTypeDef HAL_Init(void)
{
/* 配置 Flash 预取 */
#if (PREFETCH_ENABLE != 0)
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
defined(STM32F102x6) || defined(STM32F102xB) || \
defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
defined(STM32F105xC) || defined(STM32F107xC)
/* 经济型设备无预取缓冲 */
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif
#endif /* PREFETCH_ENABLE */
/* 设置中断优先级分组 */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
/* 使用 SysTick 作为时基源并配置 1ms 滴答(复位后默认时钟为 HSI) */
HAL_InitTick(TICK_INT_PRIORITY);
/* 初始化底层硬件 */
HAL_MspInit();
/* 返回函数状态 */
return HAL_OK;
}
/**
* @brief 反初始化 HAL 通用部分并停止 SysTick 时基
* @note 此函数是可选的
* @retval HAL 状态
*/
HAL_StatusTypeDef HAL_DeInit(void)
{
/* 复位所有外设 */
__HAL_RCC_APB1_FORCE_RESET();
__HAL_RCC_APB1_RELEASE_RESET();
__HAL_RCC_APB2_FORCE_RESET();
__HAL_RCC_APB2_RELEASE_RESET();
#if defined(STM32F105xC) || defined(STM32F107xC)
__HAL_RCC_AHB_FORCE_RESET();
__HAL_RCC_AHB_RELEASE_RESET();
#endif
/* 反初始化底层硬件 */
HAL_MspDeInit();
/* 返回函数状态 */
return HAL_OK;
}
/**
* @brief 初始化 MSP
* @retval 无
*/
__weak void HAL_MspInit(void)
{
/* 注意:此函数不应被修改,需要时可在用户文件中实现 HAL_MspInit */
}
/**
* @brief 反初始化 MSP
* @retval 无
*/
__weak void HAL_MspDeInit(void)
{
/* 注意:此函数不应被修改,需要时可在用户文件中实现 HAL_MspDeInit */
}
/**
* @brief 配置时基源。时基源被配置为生成 1ms 时基,并指定滴答中断优先级。
* @note 此函数在 HAL_Init() 或 HAL_RCC_ClockConfig() 配置时钟时自动调用
* @note 默认实现使用 SysTick 定时器作为时基源,定期生成中断。
* 如果从外设 ISR 调用 HAL_Delay(),需确保 SysTick 中断优先级高于外设中断。
* 此函数声明为 __weak 以便用户覆盖实现。
* @param TickPriority 滴答中断优先级
* @retval HAL 状态
*/
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* 配置 SysTick 以 1ms 为周期产生中断 */
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* 配置 SysTick 中断优先级 */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
return HAL_OK;
}
/**
* @}
*/
/** @defgroup HAL_Exported_Functions_Group2 HAL 控制函数
* @brief HAL 控制函数
*
@verbatim
===============================================================================
##### HAL 控制函数 #####
===============================================================================
[..] 本部分提供以下功能:
(+) 提供毫秒级节拍值
(+) 提供阻塞式毫秒级延时
(+) 暂停时基源中断
(+) 恢复时基源中断
(+) 获取 HAL 驱动版本
(+) 获取设备标识符
(+) 获取设备修订标识符
(+) 在 SLEEP 模式启用/禁用调试模块
(+) 在 STOP 模式启用/禁用调试模块
(+) 在 STANDBY 模式启用/禁用调试模块
@endverbatim
* @{
*/
/**
* @brief 递增全局变量 "uwTick" 作为应用时基
* @note 默认实现中,该变量在 SysTick ISR 中每 1ms 递增一次
* @note 此函数声明为 __weak 以便用户覆盖实现
* @retval 无
*/
__weak void HAL_IncTick(void)
{
uwTick += uwTickFreq;
}
/**
* @brief 获取当前毫秒级节拍值
* @note 此函数声明为 __weak 以便用户覆盖实现
* @retval 节拍值
*/
__weak uint32_t HAL_GetTick(void)
{
return uwTick;
}
/**
* @brief 获取节拍中断优先级
* @retval 节拍优先级
*/
uint32_t HAL_GetTickPrio(void)
{
return uwTickPrio;
}
/**
* @brief 设置新的节拍频率
* @retval 状态
*/
HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
{
HAL_StatusTypeDef status = HAL_OK;
HAL_TickFreqTypeDef prevTickFreq;
assert_param(IS_TICKFREQ(Freq));
if (uwTickFreq != Freq)
{
prevTickFreq = uwTickFreq; // 备份当前频率
uwTickFreq = Freq; // 更新全局变量
status = HAL_InitTick(uwTickPrio); // 应用新频率
if (status != HAL_OK)
{
uwTickFreq = prevTickFreq; // 恢复原频率
}
}
return status;
}
/**
* @brief 获取当前节拍频率
* @retval 节拍周期(Hz)
*/
HAL_TickFreqTypeDef HAL_GetTickFreq(void)
{
return uwTickFreq;
}
/**
* @brief 提供基于变量递增的阻塞式延时(毫秒)
* @note 默认使用 SysTick 定时器作为时基源生成中断
* @note 此函数声明为 __weak 以便用户覆盖实现
* @param Delay 延时时间(毫秒)
* @retval 无
*/
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* 添加频率补偿以确保最小等待 */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while ((HAL_GetTick() - tickstart) < wait)
{
}
}
/**
* @brief 暂停节拍递增
* @note 默认实现中,禁用 SysTick 中断以暂停节拍
* @note 此函数声明为 __weak 以便用户覆盖实现
* @retval 无
*/
__weak void HAL_SuspendTick(void)
{
CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk); // 禁用 SysTick 中断
}
/**
* @brief 恢复节拍递增
* @note 默认实现中,启用 SysTick 中断以恢复节拍
* @note 此函数声明为 __weak 以便用户覆盖实现
* @retval 无
*/
__weak void HAL_ResumeTick(void)
{
SET_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk); // 启用 SysTick 中断
}
/**
* @brief 获取 HAL 库版本
* @retval 版本号 0xXYZR(每个十进制占 8 位,R 为候选版本)
*/
uint32_t HAL_GetHalVersion(void)
{
return __STM32F1xx_HAL_VERSION;
}
/**
* @brief 获取设备修订标识符
* @note 在部分设备上,调试寄存器 DBGMCU_IDCODE 和 DBGMCU_CR 仅在调试模式下可访问
* @retval 设备修订标识符
*/
uint32_t HAL_GetREVID(void)
{
return ((DBGMCU->IDCODE) >> DBGMCU_IDCODE_REV_ID_Pos);
}
/**
* @brief 获取设备标识符
* @note 在部分设备上,调试寄存器 DBGMCU_IDCODE 和 DBGMCU_CR 仅在调试模式下可访问
* @retval 设备标识符
*/
uint32_t HAL_GetDEVID(void)
{
return ((DBGMCU->IDCODE) & IDCODE_DEVID_MASK);
}
/**
* @brief 获取唯一设备标识符的第一字(基于 96 位的 UID)
* @retval 设备标识符
*/
uint32_t HAL_GetUIDw0(void)
{
return(READ_REG(*((uint32_t *)UID_BASE)));
}
/**
* @brief 获取唯一设备标识符的第二字
* @retval 设备标识符
*/
uint32_t HAL_GetUIDw1(void)
{
return(READ_REG(*((uint32_t *)(UID_BASE + 4U))));
}
/**
* @brief 获取唯一设备标识符的第三字
* @retval 设备标识符
*/
uint32_t HAL_GetUIDw2(void)
{
return(READ_REG(*((uint32_t *)(UID_BASE + 8U))));
}
/**
* @brief 在 SLEEP 模式启用调试模块
* @retval 无
*/
void HAL_DBGMCU_EnableDBGSleepMode(void)
{
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
}
/**
* @brief 在 SLEEP 模式禁用调试模块
* @note 部分设备在正常模式下无法访问调试寄存器
* @retval 无
*/
void HAL_DBGMCU_DisableDBGSleepMode(void)
{
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
}
/**
* @brief 在 STOP 模式启用调试模块
* @note 部分设备在正常模式下无法访问调试寄存器
* @note 如果 SysTick 中断在 Stop 模式调试期间启用,会唤醒系统
* 解决方法:调试 Stop 模式时禁用 SysTick 中断
* @retval 无
*/
void HAL_DBGMCU_EnableDBGStopMode(void)
{
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
}
/**
* @brief 在 STOP 模式禁用调试模块
* @note 部分设备在正常模式下无法访问调试寄存器
* @retval 无
*/
void HAL_DBGMCU_DisableDBGStopMode(void)
{
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
}
/**
* @brief 在 STANDBY 模式启用调试模块
* @note 部分设备在正常模式下无法访问调试寄存器
* @retval 无
*/
void HAL_DBGMCU_EnableDBGStandbyMode(void)
{
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
}
/**
* @brief 在 STANDBY 模式禁用调试模块
* @note 部分设备在正常模式下无法访问调试寄存器
* @retval 无
*/
void HAL_DBGMCU_DisableDBGStandbyMode(void)
{
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
stm32f1xx_hal.c文件的中文注释
最新推荐文章于 2025-03-11 19:05:19 发布