一、背景
STM32 HAL库中有一个延时函数HAL_Delay(),可以实现毫秒级的延时,能够满足一般延时需求。在有些场合下,我们更精准的微秒级延时,HAL库中的毫秒级延时就不够用了。
二、实现法与代码
基于HAL库一般就是三个方法,测试用STM32F103VE,时钟频率设置为72M:
1、普通定时器,会占用一个定时器,资源少的话,定时器可能会不够用,全系列可用;
该方法的思路是将定时器设置为1MHZ的计数频率,定时器计一个数就是1us
#define DLY_TIM_Handle (&htim4)
void delay_us(uint16_t nus)
{
__HAL_TIM_SET_COUNTER(DLY_TIM_Handle, 0);
__HAL_TIM_ENABLE(DLY_TIM_Handle);
while (__HAL_TIM_GET_COUNTER(DLY_TIM_Handle) < nus);
__HAL_TIM_DISABLE(DLY_TIM_Handle);
}
2、滴答定时器,不占用定时器,也比较准确,要注意时钟频率,全系列可用;
#define CPU_FREQUENCY_MHZ 72 // STM32时钟主频
void delay_us(__IO uint32_t delay)
{
int last, curr, val;
int temp;
while (delay != 0)
{
temp = delay > 900 ? 900 : delay;
last = SysTick->VAL;
curr = last - CPU_FREQUENCY_MHZ * temp;
if (curr >= 0)
{
do
{
val = SysTick->VAL;
}
while ((val < last) && (val >= curr));
}
else
{
curr += CPU_FREQUENCY_MHZ * 1000;
do
{
val = SysTick->VAL;
}
while ((val <= last) || (val > curr));
}
delay -= temp;
}
}
3、通过简单延时,通过循环延时实现,最简单,只适用F1系列
void delay_us(__IO uint32_t delay)
{
delay = (HAL_RCC_GetHCLKFreq() / 8000000 * delay);
while(delay--);
}
三、测试
通过串口输出数据,利用串口调试助手里面的显示时间的方式来测试,延时函数delay_us的准确程度,延时50000微秒,50毫秒。
1、普通定时器测试结果,50毫秒,测试结果是约56毫秒。
2、滴答定时器测试结果,50毫秒,测试结果是约56毫秒。
3、循环延时测试效果,50毫秒,测试结果是约63毫秒。
三种方式对比,发现两种定时误差比较小,简单循环误差较大,通过修改时钟频率,误差也会有所不同,可以根据实际情况选用那种方式。