以下代码摘自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()可以永久使用。