打印
[STM32F1]

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

[复制链接]
1672|41
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
olivem55arlowe|  楼主 | 2024-4-30 19:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
方式一:系统滴答定时器
优点:全系列通用,只需要将宏定义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;    }}方式二:简单延时
优点: 实现简单,如果是F1系列,HAL_RCC_GetHCLKFreq()获取的值是72000000,此方式经过测试还是比较准的,如果不考虑通用性,F1系列建议使用此种方式。
缺点: 只适用F1系列72M主频。
void delay_us(uint32_t us){    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);    while (delay--)        {                ;        }}方式三:普通定时器
优点: STM32全系列通用
缺点: 占用一个定时器
该方法的思路是将定时器设置为1MHZ的计数频率,定时器计一个数就是1us,实现如下:
【F1系列】
#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);}
【F4系列】
#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);}


使用特权

评论回复
沙发
xixi2017| | 2024-4-30 21:16 | 只看该作者
默认提供的是毫秒延时,微秒的需要自己修改配置。

使用特权

评论回复
板凳
纠结的那些年| | 2024-8-31 16:17 | 只看该作者
适用于 STM32 系列微控制器,只需修改宏定义 CPU_FREQUENCY_MHZ 以匹配时钟主频。

使用特权

评论回复
地板
gygp| | 2024-9-3 15:52 | 只看该作者
HAL库中,并没有直接提供微秒(μs)级别的延时函数

使用特权

评论回复
5
jkl21| | 2024-9-3 17:44 | 只看该作者
定时器配置:

TIM2 定时器被配置为内部时钟源,预分频器设置为 84 - 1,使得计数频率为 1MHz。
计数周期设置为 1000 - 1,即每 1ms 计数器溢出一次。
微秒延时函数:

Delay_us 函数通过获取当前定时器的计数值,并在循环中等待定时器计数达到目标值来实现微秒延时。

使用特权

评论回复
6
updownq| | 2024-9-3 19:50 | 只看该作者
可以通过使用定时器来实现微秒级的延时。

使用特权

评论回复
7
caigang13| | 2024-9-3 20:23 | 只看该作者
精确延时还是要通过定时器来实现

使用特权

评论回复
8
hilahope| | 2024-9-3 20:59 | 只看该作者
void HAL_Delay_us(uint32_t Delay)
{
    uint32_t tickstart = HAL_GetTick();
    uint32_t wait = Delay;

    // 检查定时器是否正在运行
    if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK)
    {
        // 处理错误
    }

    // 设置定时器的计数器值
    __HAL_TIM_SET_COUNTER(&htim2, 0);

    // 启动定时器
    while (wait != 0)
    {
        // 等待定时器溢出中断
        if (__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE) != RESET)
        {
            // 清除更新标志
            __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);

            // 减少等待时间
            wait--;
        }
    }

    // 停止定时器
    HAL_TIM_Base_Stop_IT(&htim2);
}

使用特权

评论回复
9
youtome| | 2024-9-3 22:19 | 只看该作者
在使用STM32 HAL库进行开发时,如果需要实现微秒级的延时,通常的做法是使用系统时钟或者定时器来实现精确延时。

使用特权

评论回复
10
ccook11| | 2024-9-4 10:51 | 只看该作者
#include "stm32f1xx_hal.h"  // 根据你的STM32系列选择正确的头文件

// 假设系统时钟频率为72MHz
#define SYSTEM_CLOCK_FREQ 72000000U

// 定时器句柄
TIM_HandleTypeDef htim;

// 初始化定时器
void MicrosecondDelay_Init(void) {
    __HAL_RCC_TIM2_CLK_ENABLE();  // 使能定时器2时钟

    // 定时器基本配置
    htim.Instance = TIM2;  // 选择定时器2
    htim.Init.Prescaler = (SYSTEM_CLOCK_FREQ / 1000000) - 1;  // 预分频器设置为1MHz
    htim.Init.CounterMode = TIM_COUNTERMODE_UP;  // 向上计数模式
    htim.Init.Period = 0xFFFF;  // 自动重装载寄存器的值
    htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;  // 时钟不分频
    htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;  // 自动重装载寄存器没有预加载

    HAL_TIM_Base_Init(&htim);  // 初始化定时器
}

// 微秒级延时函数
void MicrosecondDelay(uint16_t us) {
    __HAL_TIM_SET_COUNTER(&htim, 0);  // 设置定时器计数器值为0
    HAL_TIM_Base_Start(&htim);  // 启动定时器
    while (__HAL_TIM_GET_COUNTER(&htim) < us);  // 等待定时器计数到us
    HAL_TIM_Base_Stop(&htim);  // 停止定时器
}

int main(void) {
    HAL_Init();  // 初始化HAL库
    // ... 其他初始化代码 ...

    MicrosecondDelay_Init();  // 初始化微秒延时

    while (1) {
        // 使用延时函数
        MicrosecondDelay(1000);  // 延时1000微秒
        // ... 其他代码 ...
    }
}

使用特权

评论回复
11
modesty3jonah| | 2024-9-4 13:53 | 只看该作者
获取当前的系统滴答计数,然后设置定时器的计数器值为0,并启动定时器。接着,我们进入一个循环,等待定时器产生更新事件(即计数器溢出),每当发生更新事件时,我们就减少等待时间,并清除更新标志。当等待时间减少到0时,我们停止定时器。

使用特权

评论回复
12
olivem55arlowe|  楼主 | 2024-9-4 16:55 | 只看该作者
定时器的配置和延时函数的实现可能会受到系统时钟和其他外设的影响。

使用特权

评论回复
13
延时函数HAL库直接使用

使用特权

评论回复
14
lzbf| | 2024-9-5 08:33 | 只看该作者
HAL库中的延时函数通常是基于系统时钟和定时器来实现的,可以提供相对准确的延时时间。然而,HAL库并没有直接提供微秒级别的延时函数,因为它依赖于系统时钟频率,而且微秒级别的精确延时很难实现,尤其是在多任务环境中。

使用特权

评论回复
15
kmzuaz| | 2024-9-5 10:23 | 只看该作者
在STM32的HAL库中,没有直接提供微秒级的延时函数

使用特权

评论回复
16
linfelix| | 2024-9-5 12:00 | 只看该作者
使用系统滴答定时器SysTick

使用特权

评论回复
17
pmp| | 2024-9-5 13:36 | 只看该作者
#include "stm32f1xx_hal.h"

void HAL_Delay_microseconds(uint32_t Delay_microseconds)
{
    // 假设系统时钟为72MHz,我们使用TIM2定时器
    __HAL_RCC_TIM2_CLK_ENABLE(); // 启用TIM2时钟
    TIM_HandleTypeDef htim2;

    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 7199; // 预分频器设置为7199,使得定时器时钟为1MHz
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = Delay_microseconds - 1; // 自动重载值设置为所需的微秒数减1
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_Base_Init(&htim2); // 初始化定时器
    HAL_TIM_Base_Start(&htim2); // 启动定时器

    while(HAL_TIM_ReadCapturedValue(&htim2) < Delay_microseconds);

    HAL_TIM_Base_Stop(&htim2); // 停止定时器
    __HAL_RCC_TIM2_CLK_DISABLE(); // 关闭TIM2时钟
}

使用特权

评论回复
18
sanfuzi| | 2024-9-5 15:13 | 只看该作者
对于需要较高精度但又不希望占用硬件资源的场景,可以通过对指令延时进行精确测量和优化来实现微秒级别的延时。

使用特权

评论回复
19
zerorobert| | 2024-9-5 17:03 | 只看该作者
#include "stm32fxxx_hal.h"

void delay_us(uint32_t us)
{
    uint32_t startTick = HAL_GetTick();
    uint32_t delayTicks = us * (SystemCoreClock / 1000000);
    while ((HAL_GetTick() - startTick) < delayTicks);
}

使用特权

评论回复
20
pl202| | 2024-9-6 15:41 | 只看该作者
这个函数通过记录开始时间(HAL_GetTick()获取当前系统滴答定时器的值),然后计算出需要等待的滴答数(根据系统时钟频率和要延迟的微秒数计算),不断检查当前时间与开始时间的差值,直到满足等待的时间。

使用特权

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

本版积分规则

16

主题

1284

帖子

0

粉丝