当前位置: 首页 > news >正文

1ms软延时,不用定时器,stm32

如果希望在不使用硬件定时器的情况下实现软延时(即通过 CPU 空操作实现延时),可以通过计算 CPU 周期数来实现 ms 和 us 级别的延时。以下是基于 216 MHz 主频的实现方法:

1. 实现原理
CPU 周期计算:在 216 MHz 的主频下,1 秒可以执行 216,000,000 个 CPU 周期。

1ms = 216,000 个 CPU 周期。

1us = 216 个 CPU 周期。

空操作延时:通过执行空操作(NOP 指令)来消耗 CPU 周期,从而实现延时。

2. 实现 ms 延时函数

void Delay_ms(uint32_t ms)
{
    uint32_t i;
    for (i = 0; i < ms; i++)
    {
        Delay_us(1000);  // 调用微秒延时函数
    }
}

3. 实现 us 延时函数

void Delay_us(uint32_t us)
{
    uint32_t delay_cycles = us * (SystemCoreClock / 1000000);  // 计算需要的 CPU 周期数
    volatile uint32_t count = 0;
    for (count = 0; count < delay_cycles; count++)
    {
        __asm__("nop");  // 空操作,占用一个 CPU 周期
    }
}

4. 完整示例
以下是一个完整的示例,展示如何使用软延时实现 ms 和 us 延时:

#include "stm32f4xx_hal.h"  // 包含 HAL 库头文件

// 微秒延时函数
void Delay_us(uint32_t us)
{
    uint32_t delay_cycles = us * (SystemCoreClock / 1000000);  // 计算需要的 CPU 周期数
    volatile uint32_t count = 0;
    for (count = 0; count < delay_cycles; count++)
    {
        __asm__("nop");  // 空操作,占用一个 CPU 周期
    }
}

// 毫秒延时函数
void Delay_ms(uint32_t ms)
{
    uint32_t i;
    for (i = 0; i < ms; i++)
    {
        Delay_us(1000);  // 调用微秒延时函数
    }
}

int main(void)
{
    // 初始化 HAL 库
    HAL_Init();

    // 配置系统时钟
    SystemClock_Config();

    // 初始化 GPIO
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 主循环
    while (1)
    {
        // 闪烁 LED(500ms 间隔)
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
        Delay_ms(500);

        // 微秒延时示例
        Delay_us(1000);  // 延时 1ms
    }
}

5. 注意事项
编译器优化:

如果编译器优化级别较高(如 -O2 或 -O3),可能会将空操作循环优化掉,导致延时失效。

解决方法:

使用 volatile 关键字修饰循环变量(如 volatile uint32_t count)。

在编译时禁用优化(如 -O0)。

精度问题:

软延时的精度受 CPU 负载和其他中断的影响,可能不够精确。

如果需要高精度延时,建议使用硬件定时器。

主频变化:

如果系统主频发生变化(如动态调整时钟频率),需要重新计算 delay_cycles。

空操作指令:

asm(“nop”) 是 GCC 编译器的内联汇编语法,表示插入一个空操作指令。

如果使用其他编译器(如 IAR 或 Keil),可能需要使用对应的语法。


文章转载自:
http://atrous.wkuuf.cn
http://chloralose.wkuuf.cn
http://abet.wkuuf.cn
http://bibliopoly.wkuuf.cn
http://alkali.wkuuf.cn
http://apres.wkuuf.cn
http://catalyzer.wkuuf.cn
http://arthur.wkuuf.cn
http://calx.wkuuf.cn
http://canthus.wkuuf.cn
http://abrader.wkuuf.cn
http://basilian.wkuuf.cn
http://bield.wkuuf.cn
http://asian.wkuuf.cn
http://axman.wkuuf.cn
http://bleep.wkuuf.cn
http://alod.wkuuf.cn
http://cavalla.wkuuf.cn
http://asymptotical.wkuuf.cn
http://alkyne.wkuuf.cn
http://carnous.wkuuf.cn
http://bushie.wkuuf.cn
http://apf.wkuuf.cn
http://bibliomaniac.wkuuf.cn
http://anschluss.wkuuf.cn
http://allusive.wkuuf.cn
http://amotivational.wkuuf.cn
http://antisubmarine.wkuuf.cn
http://carlsruhe.wkuuf.cn
http://ateliosis.wkuuf.cn
http://www.dtcms.com/a/110273.html

相关文章:

  • 智谱AutoGLM:从对话到自主操作的AI智能体革新
  • 第八章 图论
  • 06-03-自考数据结构(20331)- 查找技术-哈希表知识点
  • 【GPIO8个函数解释】
  • 1759. 统计同质子字符串的数目
  • 【深度学习】tf.math.multiply与tf.multiply有啥区别?
  • 在 .NET 8 中使用自定义令牌身份验证掌握 SignalR Hub 安全性
  • 【设计模式】设计模式六大原则
  • 《Golang高性能网络编程:构建低延迟服务器应用》
  • docker导出image再导入到其它docker中
  • openfga-spring-boot3-starter自己封装
  • SAP CEO引领云端与AI转型
  • rk3588配置静态IP和DNS
  • 运筹帷幄:制胜软件开发
  • K8s的资源管理
  • Spring Boot + MySQL + MyBatis(注解和XML配置两种方式)集成Redis的完整启用及配置详解,包含代码示例、注释说明和表格总结
  • AI设计再现新引擎,科技创新又添新动能——广东省首家行业AI设计工程中心获批成立
  • 力扣刷题——2331.计算布尔二叉树的值
  • 【AI视频】度加视频测试
  • HTML jQuery PDF Annotation plugin library free online API examples
  • 蓝桥杯常用算法介绍:动态规划(DP)
  • 自动驾驶中的实时挑战:如何优化车辆动力学模型
  • YOLO系列论文图表绘制代码
  • BFC特性,开启BFC的方法,怪异盒子模型
  • 如何用 Three.js 和 Vue 3 实现 3D 商品展示
  • Java面试黄金宝典31
  • C语言--统计字符串中最长的单词
  • [leetcode]queue的操作的回顾
  • 【CMOS输出缓冲器驱动强度】
  • 系统架构设计理论之架构风格与模式(分层、MVC、微服务、事件驱动)