在做嵌入式开发的时候,经常需要用到延时函数,STM32为我们提供了一个标准的毫秒级延时函数:HAL_Delay()。这个函数用起来很方便,括号内的数就是延时的毫秒数。
但是程序中如果需要用到看门狗的话呢,这玩意需要经常喂的,否则一旦超时就会复位。
所以很容易想到,在延时函数中增加喂狗的代码,如下:
c
void delay_ms(u32 time)
{
u32 i;
for(i=0; i<time; i++)
{
HAL_Delay(1);
HAL_IWDG_Refresh(&hiwdg);
}
}
这样当然可以运行,但是不完美,比如在程序调试的时候,我们经常需要关闭看门狗,还有就是这样一来延时会很不准确,特别是系统频繁要进中断的话,实际延时会比预期长不少。
我相信很多人都没有看过这个HAL_Delay()函数实现的代码。具体如下:
c
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while ((HAL_GetTick() - tickstart) < wait)
{
}
}
最前面的__weak表明它是一个弱函数,也就是说我们可以自己编程来实现它,把喂狗的功能集成到这个函数内,从外部看,仍然用的是HAL_Delay()这个函数名,代码风格可以和HAL库保持一致。
实现也很简单,自己建一个延时函数LL_delay.c,如下:
c
void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while ((HAL_GetTick() - tickstart) < wait)
{
HAL_IWDG_Refresh(&hiwdg); //自己添加的喂狗函数
}
}
就是在最后的while循环中增加一行喂狗的代码,再相应添加LL_delay.h,如下:
c
#ifndef _LL_DELAY_H_
#define _LL_DELAY_H_
void HAL_Delay(uint32_t Delay);
这样就几乎不用再操心喂狗的事了