STM32 HAL 库延时函数 HAL_Delay 解析

HAL 库有提供延时函数,只不过它只能实现简单的毫秒级别延时,没有实现 us 级别延时。
下面我们列出HAL 库实现延时相关的函数。首先是功能配置函数:

//调用 HAL_SYSTICK_Config 函数配置每隔 1ms 中断一次
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* 配置系统在 1ms 的时间基础上有中断*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* 配置 SysTick IRQ 优先级*/
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
return HAL_OK;
}
//HAL 库的 SYSTICK 配置函数:文件 stm32f1xx_hal_context.c 中定义
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
}
//内核的 Systick 配置函数,配置每隔 ticks 个 systick 周期中断一次
//文件 core_cm3.h 中
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
...//此处省略函数定义
}

上面三个函数,实际上开放给 HAL 调用的主要HAL_InitTick 函数,该函数在 HAL 库初始化函数 HAL_Init 中会被调用。
该函数通过间接调用 SysTick_Config 函数配置 Systick 定时器每隔 1ms 中断一次,永不停歇。
接下来我们来看看延时的逻辑控制代码:

//Systick 中断服务函数
void SysTick_Handler(void)
{
HAL_IncTick();
}
//下面代码均在文件 stm32l0xx_hal.c 中
static __IO uint32_t uwTick; //定义计数全局变量
__weak void HAL_IncTick(void)
{
uwTick += uwTickFreq;
}
__weak uint32_t HAL_GetTick(void) //获取全局变量 uwTick 的值
{
return uwTick;
}
//开放的 HAL 延时函数,延时 Delay 毫秒
__weak void HAL_Delay(__IO 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)
{
}
}

HAL 库实现延时功能非常简单,首先定义了一个 32 位全局变量 uwTick,在 Systick 中断服务函数 SysTick_Handler 中通过调用 HAL_IncTick 实现 uwTick 值不断增加,也就是每隔 1ms增加 1。
而 HAL_Delay 函数在进入函数之后先记录当前 uwTick 的值,然后不断在循环中读取uwTick 当前值,进行减运算,得出的就是延时的毫秒数,整个逻辑非常简单也非常清晰。

你可能感兴趣的:(蓝桥杯物联网设计与开发,stm32,单片机,嵌入式)