温馨提示×

温馨提示×

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

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

STM32延时函数的方法有哪些

发布时间:2021-12-27 11:18:45 来源:亿速云 阅读:186 作者:小新 栏目:互联网科技
# STM32延时函数的方法有哪些 ## 引言 在嵌入式系统开发中,精确的时间控制是至关重要的功能。无论是LED闪烁、传感器数据采集,还是通信协议的时序控制,都需要依赖精准的延时功能。STM32作为广泛应用的ARM Cortex-M系列微控制器,提供了多种实现延时功能的方法。本文将全面剖析STM32开发中常用的延时实现方式,包括原理分析、代码实现以及各自的优缺点比较,帮助开发者根据实际需求选择最合适的方案。 ## 一、基础延时方法 ### 1.1 空循环延时 #### 实现原理 ```c void Delay(uint32_t count) { while(count--); } 

通过让CPU执行无意义的循环消耗时钟周期实现延时,延时精度取决于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 定时器延时优势分析

  • 纳秒级高精度延时
  • 可与其他功能(PWM、输入捕获)复用
  • 支持中断和非阻塞式延时

三、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延时特点

  • 非阻塞式延时提高系统效率
  • 与任务调度深度整合
  • 支持绝对时间延时(如FreeRTOS的vTaskDelayUntil)

四、低功耗模式延时

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 低功耗延时注意事项

  • 需要配置唤醒源(RTC、EXTI等)
  • 唤醒后需要重新初始化时钟和外设
  • 测量实际唤醒时间进行补偿

五、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格式,包含代码块、表格和分级标题,便于阅读和技术文档的维护。

向AI问一下细节

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

AI