自己写一个STM32 HAL库的US微秒延时函数

当本菜鸟开始接触STM32的时候还是看了原子哥的寄存器教程才跳坑的。

现在ST已经把HAL库推向了主流,但是令我不解的是,HAL那么强大,居然没有一个微秒级别的延时函数?!

黑人问号脸。

好了,废话不多,直接上代码。

#include "delay_us.h"
/*****************************************************************
* 基于STM32F0 HAL的微秒延时函数
* @功能:实现US级延时
* @注意:精准延时范围:2~999US
*	2019-07-03	Designed By XiaoYang  https://www.pypyn.com
******************************************************************/
uint32_t CFG_VAL = 0;
void HAL_Delay_US(__IO uint32_t Delay)
{
	if(Delay < MAX_Delay_CNT && Delay > 1)
	{
		uint32_t wait = SysTick->LOAD - ((Delay - 1) * CFG_VAL);
		
	             //CFG_VAL =HAL_RCC_GetHCLKFreq()/1000U/1000U))
                     //计算出等待1US需要的计数器值
		SysTick->VAL=0UL;               //重置SysTick计数器,计数器为向下计数
		while(wait < (SysTick->VAL));	//等待时间到达
	}
}
/*****************************************************************
* 微秒延时初始化延时基数
*
* @注意:初始化必须放在SystemClock_Config();之后!!!
*
******************************************************************/
void HAL_Delay_us_Init(void)
{
	CFG_VAL = (uint32_t)HAL_RCC_GetHCLKFreq()/1000/1000;
}

2019.09.08更新:补充一下原理

HAL库的ms延时函数是通过systick计数器每隔1ms进入中断累加计数值并等待这个计数值累加完成实现的。也就是说在HAL库初始化后systick就已经被配置好了,通过代码我们不难发现:SystemClock_Config()函数包含了其中的过程并获取了当前系统的HCLK频率。
所以我的设计思路很简单,能否通过等待Systick计数器的值达到目标值来实现。所以首先我们需要知道如果等待1US时,systick定时计数器的值需要多少,因此我们可以先编写一个初始化函数来计算出这个,并把这个值保存到全局变量,避免每次调用都需要重复计算而浪费CPU时间。

HAL_RCC_GetHCLKFreq()函数可以获取当前系统的HCLK频率(48M下值是48 000 000) ,但是要注意的是一定要在 SystemClock_Config()完成之后调用,否则返回的值是一个错误的值。现在假如返回值是48 000 000,也就是48M,那么完成1us等待需要的值是48 000 000÷1000÷1000 = 48,然后我们把这个值保存起来即可。

板子使用的是STM32F030F4。
测试一下5us延时,非常准
15us,也很准
50us,也很准

存在的问题:调用该延时函数会清空systick定时器的计数值因此会不同程度影响HAL库毫秒延时HAL_Delay的精度,如果过于频繁的调用会导致systick定时器无法进入中断,使HAL库的HAL_Delay毫秒延时卡死。
欢迎访问我的博客:pypyn.com

最后,送上源码

发表评论

您的电子邮箱地址不会被公开。