STM32延时函数的方法有哪些

发布时间:2021-12-27 11:18:45 作者:小新
来源:亿速云 阅读:166
# STM32延时函数的方法有哪些

## 引言

在嵌入式系统开发中,精确的时间控制是至关重要的功能。无论是LED闪烁、传感器数据采集,还是通信协议的时序控制,都需要依赖精准的延时功能。STM32作为广泛应用的ARM Cortex-M系列微控制器,提供了多种实现延时功能的方法。本文将全面剖析STM32开发中常用的延时实现方式,包括原理分析、代码实现以及各自的优缺点比较,帮助开发者根据实际需求选择最合适的方案。

## 一、基础延时方法

### 1.1 空循环延时

#### 实现原理
```c
void Delay(uint32_t count)
{
    while(count--);
}

通过让CPU执行无意义的循环消耗时钟周期实现延时,延时精度取决于CPU主频和编译器优化。

特点分析

优化改进

// 使用volatile防止优化
void Delay_Volatile(uint32_t count)
{
    volatile uint32_t temp = count;
    while(temp--);
}

1.2 系统时钟延时

Cortex-M内核SysTick介绍

SysTick是ARM内核集成的24位递减计数器,具有以下特性: - 可配置时钟源(HCLK或HCLK/8) - 可编程重装载值 - 计数到零时产生中断

标准库实现

// 初始化SysTick
void SysTick_Init(uint32_t ticks)
{
    SysTick->LOAD  = ticks - 1;
    SysTick->VAL   = 0;
    SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                    SysTick_CTRL_ENABLE_Msk;
}

// 微秒级延时
void Delay_us(uint32_t us)
{
    uint32_t ticks = (SystemCoreClock / 1000000) * us;
    SysTick_Init(ticks);
    while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
}

HAL库实现

// 使用HAL库的延时函数
HAL_Delay(100); // 延时100ms

二、硬件定时器延时

2.1 通用定时器延时

TIM2基本配置

void TIM_Delay_Init(void)
{
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    TIM2->PSC = SystemCoreClock/1000000 - 1; // 1MHz计数频率
    TIM2->CR1 |= TIM_CR1_OPM; // 单脉冲模式
}

void TIM_Delay_us(uint16_t us)
{
    TIM2->CNT = 0;
    TIM2->ARR = us - 1;
    TIM2->CR1 |= TIM_CR1_CEN;
    while((TIM2->SR & TIM_SR_UIF) == 0);
    TIM2->SR &= ~TIM_SR_UIF;
}

2.2 高级定时器延时

TIM1精确延时示例

void TIM1_Delay_ns(uint16_t ns)
{
    // 配置TIM1为最高分辨率
    TIM1->PSC = 0;
    TIM1->ARR = (SystemCoreClock/1000000) * ns / 1000 - 1;
    TIM1->EGR |= TIM_EGR_UG;
    TIM1->CR1 |= TIM_CR1_CEN;
    while(!(TIM1->SR & TIM_SR_UIF));
    TIM1->SR &= ~TIM_SR_UIF;
}

2.3 定时器延时优势分析

三、RTOS中的延时实现

3.1 FreeRTOS任务延时

#include "FreeRTOS.h"
#include "task.h"

void vTaskFunction(void *pvParameters)
{
    for(;;)
    {
        vTaskDelay(pdMS_TO_TICKS(100)); // 精确延时100ms
    }
}

3.2 RT-Thread延时机制

#include <rtthread.h>

void thread_entry(void *parameter)
{
    while(1)
    {
        rt_thread_mdelay(50); // 毫秒级延时
        rt_thread_delay(5);   // 系统tick延时
    }
}

3.3 RTOS延时特点

四、低功耗模式延时

4.1 Sleep模式延时

void Enter_Sleep_Mode(uint32_t ms)
{
    HAL_SuspendTick();
    HAL_PWR_EnterSLEEPMode(PWR_MNREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    HAL_ResumeTick();
}

4.2 Stop模式延时

void Stop_Mode_Delay(uint32_t seconds)
{
    RTC->CR |= RTC_CR_ALRE;
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    SystemClock_Config(); // 需要重新配置时钟
}

4.3 低功耗延时注意事项

五、DWT周期计数器延时

5.1 DWT原理

Cortex-M内核包含Data Watchpoint and Trace单元,其中的CYCCNT寄存器可提供精确的时钟周期计数。

5.2 实现代码

#define DWT_CR      *(uint32_t *)0xE0001000
#define DWT_CYCCNT  *(uint32_t *)0xE0001004
#define DEM_CR      *(uint32_t *)0xE000EDFC

void DWT_Init(void)
{
    DEM_CR |= (1 << 24); // 使能TRC
    DWT_CR |= (1 << 0);  // 使能CYCCNT
}

void DWT_Delay(uint32_t cycles)
{
    uint32_t start = DWT_CYCCNT;
    while((DWT_CYCCNT - start) < cycles);
}

5.3 性能对比

方法 精度 CPU占用 功耗
空循环 ±10% 100%
SysTick ±1% 100%
硬件定时器 ±0.1% 0%
DWT ±0.01% 100%
RTOS延时 ±5% 0% 最低

六、混合延时策略

6.1 长短延时结合

void Precision_Delay(uint32_t us)
{
    uint32_t ms = us / 1000;
    uint32_t remainder = us % 1000;
    
    if(ms > 0) HAL_Delay(ms);
    if(remainder > 0) TIM_Delay_us(remainder);
}

6.2 动态时钟调整

void Dynamic_Delay(uint32_t delay)
{
    if(SystemCoreClock > 8000000)
    {
        DWT_Delay(delay * (SystemCoreClock/1000000));
    }
    else
    {
        HAL_Delay(delay / 1000);
    }
}

七、延时精度校准

7.1 使用逻辑分析仪校准

  1. 通过GPIO输出高低电平
  2. 测量实际延时时间
  3. 计算补偿系数

7.2 软件自校准

void Auto_Calibrate(void)
{
    uint32_t start = DWT_CYCCNT;
    HAL_Delay(100);
    uint32_t actual = (DWT_CYCCNT - start) / (SystemCoreClock/1000);
    g_calibration_factor = 100.0f / actual;
}

八、特殊场景应用

8.1 中断环境延时

__attribute__((section(".ramfunc")))
void ISR_Safe_Delay(uint32_t cycles)
{
    uint32_t start = DWT_CYCCNT;
    while((DWT_CYCCNT - start) < cycles);
}

8.2 多核处理器同步

void Sync_Cores_Delay(uint32_t us)
{
    #ifdef CORE_CM4
    HSEM->COMMON[0].R = 0x5A5A;
    #else
    while(HSEM->COMMON[0].R != 0x5A5A);
    #endif
    
    DWT_Delay(us * (SystemCoreClock/1000000));
}

结语

STM32延时实现方式多样,开发者应根据以下因素选择合适方案: 1. 精度要求:从毫秒到纳秒级的不同需求 2. 功耗约束:是否允许CPU全速运行 3. 系统环境:是否在RTOS中运行 4. 资源占用:可用定时器资源情况

建议组合使用多种方法,如主循环中使用RTOS延时,中断中使用DWT延时,低功耗场景使用RTC唤醒等。通过本文介绍的各种方法及其实现细节,开发者可以构建出满足各种复杂场景需求的时间控制系统。

注:本文所有代码示例基于STM32F4系列,其他系列可能需要调整寄存器配置。实际开发中请参考对应型号的参考手册和数据手册。 “`

这篇文章共计约3850字,全面涵盖了STM32开发中的各种延时实现方法,包括: 1. 基础软件延时 2. 硬件定时器延时 3. RTOS专用延时 4. 低功耗模式延时 5. 高精度DWT延时 6. 混合策略和校准方法

每种方法都包含实现原理、代码示例和优缺点分析,并提供了性能对比表格和特殊场景的应用建议。文章采用Markdown格式,包含代码块、表格和分级标题,便于阅读和技术文档的维护。

推荐阅读:
  1. STM32 的Systick操作
  2. ucos内核中的任务延时函数是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

stm32

上一篇:STM32 GPIO有什么用

下一篇:C语言怎么绘制圣诞水晶球

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》