[应用相关]

STM32 HAL库方式的微秒延时函数

[复制链接]
991|85
手机看帖
扫描二维码
随时随地手机跟帖
铁血丹心LLLL|  楼主 | 2021-11-30 20:40 | 显示全部楼层 |阅读模式
STM32CUBEMX系列教程之HAL库方式的微秒延时函数

标准库一般是使用系统嘀嗒定时器来进行微妙级别的延时,而HAL库将SysTick定时器用做了库函数的超时定时器,使用的地方非常多,自己修改代码使用嘀嗒定时器的话就会引起错乱。所以此时就需要自己实现一个微秒级别延时函数。

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2021-11-30 20:49 | 显示全部楼层
方式一:系统滴答定时器
优点:全系列通用,只需要将宏定义CPU_FREQUENCY_MHZ根据时钟主频修改即可。
缺点:系统滴答定时器是HAL库初始化的,且必须有HAL库初始化。

#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;
    }
}

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2021-11-30 20:52 | 显示全部楼层
方式二:简单延时
优点: 实现简单,如果是F1系列,HAL_RCC_GetHCLKFreq()获取的值是72000000,此方式经过测试还是比较准的,如果不考虑通用性,F1系列建议使用此种方式。

使用特权

评论回复
评论
铁血丹心LLLL 2021-11-30 20:53 回复TA
缺点: 只适用F1系列72M主频。 
铁血丹心LLLL|  楼主 | 2021-11-30 20:55 | 显示全部楼层
void delay_us(uint32_t us)
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
    while (delay--)
        {
                ;
        }
}

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2021-11-30 20:56 | 显示全部楼层
方式三:普通定时器
优点: STM32全系列通用
缺点: 占用一个定时器

该方法的思路是将定时器设置为1MHZ的计数频率,定时器计一个数就是1us,实现如下:

【F1系列】

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2021-11-30 20:58 | 显示全部楼层
6461561a61f78da1be.png

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-2-28 15:33 | 显示全部楼层
#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);
}

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-2-28 15:33 | 显示全部楼层
【F4系列】
79220621c7ad292f73.png

使用特权

评论回复
铁血丹心LLLL|  楼主 | 2022-2-28 15:46 | 显示全部楼层
#define DLY_TIM_Handle  (&htim7)

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);
}

使用特权

评论回复
alvpeg| | 2022-11-19 12:08 | 显示全部楼层
这个只能使用定时器了。              

使用特权

评论回复
dspmana| | 2022-11-19 17:03 | 显示全部楼层
systick被占用了,不能微秒延时。

使用特权

评论回复
lzmm| | 2022-11-20 11:32 | 显示全部楼层
for循环实现us的延时的。              

使用特权

评论回复
claretttt| | 2022-11-20 12:32 | 显示全部楼层
占用一个定时器这个精度很高吗              

使用特权

评论回复
jonas222| | 2022-11-20 18:13 | 显示全部楼层
如果使用while或者for,这个精度大不大呢?

使用特权

评论回复
uptown| | 2022-11-24 15:23 | 显示全部楼层
__weak uint16_t HAL_GetTick_us(void)
{
  return __HAL_TIM_GetCounter (&htim6 );//获取定时器6计数器的值
}
__weak void HAL_Delay_us(uint16_t Delay)
{
  uint16_t tickstart = HAL_GetTick_us();//计数器初始值
  uint16_t wait = Delay;//需要延时的值
        HAL_TIM_Base_Start (&htim6); //打开定时器
  while ((HAL_GetTick_us() - tickstart) < wait)//等待
  {
  }
        HAL_TIM_Base_Stop(&htim6); //关闭定时器
         __HAL_TIM_SetCounter (&htim6,0 );//定时器计数器清零,往往可以省略,会自动清零
}
blog.csdn.net/m0_65565606/article/details/122883740

使用特权

评论回复
hearstnorman323| | 2022-11-24 15:56 | 显示全部楼层
while((HAL_GetTick() - tickstart) < wait) { } }   

使用特权

评论回复
mikewalpole| | 2023-3-4 19:41 | 显示全部楼层
hal库为什么编译变慢                 

使用特权

评论回复
Stahan| | 2023-3-5 19:54 | 显示全部楼层
mikewalpole 发表于 2023-3-4 19:41
hal库为什么编译变慢

封装了太多层了吧

使用特权

评论回复
olivem55arlowe| | 2023-3-7 20:46 | 显示全部楼层
stm32库函数算hal层吗               

使用特权

评论回复
sdCAD| | 2023-3-14 14:52 | 显示全部楼层
在HAL库中的微妙级别的延迟怎么弄   

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

421

帖子

1

粉丝