STM32HAL库中的HAL_Delay()函数实现原理分析

很多初学者只是学会使用HAL_Delay()函数,但却不明白这个函数实现延时的机理,其实它本质山是利用了SysTick定时器来实现延时的,很多人后来不在使用这个函数,又是因为神马原因呢?请听我娓娓道来。

首先你要知道定时器和中断的概念:

定时器

定时器就相当于一个计数器的功能,STM32定时器分为基本定时器,通用定时器,高级定时器。

具体介绍可以参考

https://blog.csdn.net/Carbon6/article/details/107815216?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165430681016781683924561%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=165430681016781683924561&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-107815216-null-null.142^v11^control,157^v13^control&utm_term=stm32%E5%AE%9A%E6%97%B6%E5%99%A8&spm=1018.2226.3001.4187

SysTick定时器:简单理解来说,SysTick和通用定时器没有太大的区别,它是一个24位向下计数的定时器,而且属于内核外设。

中断

简单理解来说,当发生某个事件时且中断使能,程序会立即跳入到中断服务函数中去执行特定的程序之后,执行完毕后再回到原来的位置继续执行。

HAL_Delay()函数的实现就是利用了SysTick定时器的更新中断。更新中断就是SysTick计数到0后产生的中断。

下面根据具体代码来看它的实现原理:

 找到函数原型如下图,这是个弱函数,看来作者似乎已经默认了它的缺点,允许我们自定义一个延时函数。这个函数中又调用了一个 HAL_GetTick()函数,并把它的返回值赋给变量 tickstart ,然后把函数的形参(Delay即延时的毫秒数)赋给变量 wait。

接着if语句的判断wait的值是否小于HAL_MAX_DELAY(它宏定义值为 0xFFFFFFFF),

实际上,我们传入的Delay要保证小于它。进入if语句中,wait自增1。

然后进入while循环中,while循环执行的时间即为延时的时间。我们先看一下HAL_GetTick()函数的原型。

 

它就返回uwTick的值。我们uwTick,发现它在这个函数中实现了每次自增1:

 

这个函数是不是似曾相识,没错,它是固定放在SysTick_Handler()函数中的,即SysTick中断服务函数,也就是说每进行一次中断,执行一次该函数,uwTick自增1.

 

我们回到HAL_Delay()函数原型,进入到该函数,首先获取(通过HAL_GetTick())uwTick的值并且赋给变量tickstart,延时的时间(毫秒数)通过形参赋给wait,wait在if语句自增1后;进入while循环,此时只有HAL_GetTick()-tickstart>=wait才能跳出循环,即变量uwTick增加量等于wait时,延时结束。uwTick在SysTick中断每次自增一。即延时的时间等于:(SysTick中断周期)*(wait-1),即(SysTick中断周期)*Delay。实际上,SysTick中断周期默认配置为1ms。从而实现毫秒延时效果。

值得注意的是,由于HAL_Delay()函数是阻塞的,所以要慎用。

物联沃分享整理
物联沃-IOTWORD物联网 » STM32HAL库中的HAL_Delay()函数实现原理分析

发表评论