STM32 HAL库的 HAL_Delay() 详解

本文深入解析了STM32 HAL库中的ms延时函数HAL_Delay的工作原理,探讨了其输入参数限制及有效性问题,通过实验验证了即使在uwTick值接近最大时,该函数仍能正常工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、实现原理

以下代码摘自cubeMX自动生成的部分

/*stm32f1xx_it.c*/
//sysTick中断函数
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}



/*stm32f1xx_hal.c*/
//SysTick 初始化函数 (HAL_Init()调用此函数)
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }

  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);//设置中断
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}
//中断函数会调用一次改函数,将uwTick增1
__weak void HAL_IncTick(void)
{
  uwTick += uwTickFreq;
}
//获取uwTick值
__weak uint32_t HAL_GetTick(void)
{
  return uwTick;
}
//本次讨论的主角,ms延时函数
__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();//先记录当前uwTick值
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY) //HAL_MAX_DELAY为0xffffffff,一般这条不会有问题
  {
    wait += (uint32_t)(uwTickFreq); //uwTickFreq一般定义为0x01
  }

//由于systick中断会不断修改uwTick值,所以在uwTick值比刚开始记录的uwTick值大到wait值也就是ms值就会跳出whlie循环,然后返回
  while ((HAL_GetTick() - tickstart) < wait) 
  {
  }
}

二、输入参数限制

如果对uwTickFreq有改动,则需要注意。下面默认uwTickFreq未改动,且值是1。

在引入下面的问题之前,在合理的判断下可以输入的值应该是(0xffffffff - 当前uwTick)。那么,如果当uwTick即将计至最大值时,HAL_Delay()还可以继续使用吗?带着这个问题,我简单的做了一个实验。

三、有效期问题

无符号32位整数数值最大值为0xffffffff 十进制是4294967295,从0ms计至4294967295ms需要4294967.295 s,1193小时,也就是49天多。为了实验验证有效期问题,在这49天之后,uwTick会重新从0开始计数,如果在之前调用了HAL_Delay(),则tickstart 是一个接近最大值的值,而此后uwTick再与tickstart 进行比较时是否一直都是小于wait值呢?会不会因此进入一个无限循环呢?

下面做一个实验:

uint32_t testn;
uint32_t tickss;//用于debug时查看uwTick的值

testn=0xfffffffe;//模拟uwTick值已经计至末端
tickss=0;
while ((tickss - testn) < 100)//延时100ms
{
	tickss = HAL_GetTick();
}

实验后发现,tickss值为98时,会退出while循环。 意味着 (tickss - testn) 也就是(0x62 - 0xfffffffe)小于 100 不成立。

这是为什么呢?

用计算器算一遍(PC 是64位,所以减去 0xffff ffff ffff fffe):

也就是说,相减以后,内存中还是以无符号32位数值进行存储,数值为100。

其实熟悉无符号整数存储机制,可想而知。

由此可见 HAL_Delay()可以永久使用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值