STM32的HAL库提供了一个HAL_Delay函数,使用Systick中断来实现,实现过程如下:
1.首先是一个Systick中断配置函数SysTick_Config,该函数实现的是Systick中断每隔ticks中断一次。。。。。
[mw_shl_code=c,true]__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}[/mw_shl_code]
2.其次依次是:HAL_SYSTICK_Config函数和HAL_InitTick函数。。。。
HAL_InitTick函数调用之后,实际上就是配置每隔1ms中断一次,最终调用的是SysTick_Config函数进行配置。而这个函数是在HAL_Init函数中调用,在系统初始化之后会调用。
[mw_shl_code=c,true]uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
}
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/*Configure the SysTick to have interrupt in 1ms time basis*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/*Configure the SysTick IRQ priority */
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0);
/* Return function status */
return HAL_OK;
}[/mw_shl_code]
3.经过前面2步骤,开启了Systick定时器,每隔1ms中断一次。。。
而中断服务函数和相关逻辑函数是这样的:
[mw_shl_code=c,true]void SysTick_Handler(void)
{
HAL_IncTick();
}
static __IO uint32_t uwTick;
__weak void HAL_IncTick(void)
{
uwTick++;
}
__weak uint32_t HAL_GetTick(void)
{
return uwTick;
}[/mw_shl_code]
定义了一个32位的全局变量uwTick,每次中断(1ms),变量uwTick增加1.。。。
4.最后HAL_Delay函数是这样的:
[mw_shl_code=c,true]__weak void HAL_Delay(__IO uint32_t Delay)
{
uint32_t tickstart = 0;
tickstart = HAL_GetTick();
while((HAL_GetTick() - tickstart) < Delay)
{
}
}[/mw_shl_code]
通过HAL_GetTick();函数获取此时uwTick的值赋给tickstart,然后使用while循环不断调用HAL_GetTick() 函数获取当前uwTick值减掉tickstart,差值就是定时的ms数。。。
问题来了,如果32位的uwTick越界了怎么办? 32位uwTick的值,每1ms增加1,最大只有几十天就越界了。。。。
例如,如果还有1s就越界,如果此时此刻,我们调用HAL_Delay延时10s,那么肯定就乱套了。。。。
ST不应该会犯如此大的错误吧?不知道是我看少了,还是确实是一个Bug,大家讨论一下。。。。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
不是BUG,简单的写了个程序验证,模拟即将越界时的情况。打印情况如下:
0, 4294967291
1, 4294967292
2, 4294967293
3, 4294967294
4, 4294967295
5, 0
6, 1
7, 2
8, 3
9, 4
退出循环
[mw_shl_code=c,true]
uint32_t uwTick, tickstart, tmp;
void delay(uint32_t ms)
{
tickstart = 4294967296 - 5;
uwTick = tickstart;
while ((tmp = (uwTick - tickstart)) < ms)
{
printf("%u, %u ", tmp, uwTick);
uwTick++;
}
}
int main(void)
{
delay(10);
getchar();
}[/mw_shl_code]
YES,你回答得非常对。。。稍微深入研究一下代码就可以了。。。
没有问题。
一周热门 更多>