freertos开发空气检测仪之延迟函数设计:DWT软件实现

freertos开发空气检测仪之延迟函数设计:DWT软件实现

本篇带来空气检测仪项目之延迟函数设计

在项目中,一般都需要设计一些delay函数,比较常用,本篇设计带来DWT的软件实现。

一、引言

在空气检测仪项目的开发过程中,延迟函数是一项非常基础且重要的功能。无论是传感器数据的采集间隔控制,还是与外部设备通信时的时序要求,都离不开精确的延迟操作。在众多实现延迟函数的方法中,使用 DWT(Data Watchpoint and Trace)进行软件延迟是一种高效且精确的方式。本文将详细介绍在空气检测仪项目中如何使用 DWT 来实现延迟函数。

二、DWT 简介

2.1 什么是 DWT

DWT 是 ARM Cortex - M 系列处理器中一个非常有用的调试组件,它主要用于数据观察点和跟踪功能。不过,我们也可以利用 DWT 中的 CYCCNT(Cycle Counter)寄存器来实现高精度的延迟功能。CYCCNT 寄存器是一个 32 位的计数器,它会在处理器每执行一个时钟周期就自动加 1。

2.2 DWT 实现延迟的优势

  • 高精度:由于 CYCCNT 寄存器是根据处理器的时钟周期进行计数的,因此可以实现非常精确的延迟。
  • 灵活性:可以根据需要实现不同时长的延迟,只需要调整计数器的初始值和比较值即可。
  • 占用资源少:相比于一些硬件定时器的实现方式,DWT 实现延迟不需要额外的硬件资源。

三、具体代码

core_delay.h文件

c 复制代码
#ifndef __CORE_DELAY_H
#define __CORE_DELAY_H

#include "gd32f30x.h"

void dwt_init(void);
void dwt_delay_us(uint32_t us);
void dwt_delay_ms(uint32_t ms);
void dwt_delay_us_accurate(uint32_t us);
uint32_t dwt_ns_tick_get(void);

#endif /* __CORE_DELAY_H */

core_delay.c文件

c 复制代码
#include "core_delay.h"   

/**
 * @brief  微秒级延时函数
 * @param  us: 要延时的微秒数
 * @note   此函数基于循环计数实现延时,精度取决于系统时钟稳定性
 *         使用前请确保SystemCoreClock变量已正确初始化  感觉延迟不够好用
 */
void dwt_delay_us_accurate(uint32_t us)
{
    // 根据实际测试结果调整系数(例如除以10)
    uint32_t wait_loop_index = us * (SystemCoreClock / 1000000U) / 10;
    
    // 使用volatile防止编译器优化
    volatile uint32_t *p = &wait_loop_index;
    
    while(*p != 0U)
    {
        (*p)--;
    }
}

// 初始化DWT计数器(在系统初始化时调用一次)
void dwt_init(void)
{
    if (!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)) 
		{
        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CYCCNT = 0;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
    }
}

// 精确的微秒级延时
void dwt_delay_us(uint32_t us)
{
    uint32_t start = DWT->CYCCNT;
    uint32_t cycles = us * (SystemCoreClock / 1000000U);
    
    while ((DWT->CYCCNT - start) < cycles);
}

// ms级别延时
void dwt_delay_ms(uint32_t ms)
{
    dwt_delay_us(ms * 1000);
}

// ns级别延时获得
uint32_t dwt_ns_tick_get(void)
{
    return ((uint32_t)((DWT->CYCCNT)/ 120) * 1000);	
}

四、DWT测试代码

c 复制代码
	/* 初始化DWT计数器 */
	dwt_init();
	
	uint32_t start_tick = dwt_ns_tick_get();

	// 测试dwt延迟
	PLEDDevice ptLEDDevice;

	ptLEDDevice = GetLEDDevice(LED_ID_WHITE);
	if (ptLEDDevice != NULL) 
	{
		ptLEDDevice->Init(ptLEDDevice);
		ptLEDDevice->Control(ptLEDDevice, 1);
		dwt_delay_ms(100);
		ptLEDDevice->Control(ptLEDDevice, 0);
		dwt_delay_ms(100);
	}

	uint32_t end_tick = dwt_ns_tick_get();
	DBG_log("LED device control test time: %d ns\n", end_tick - start_tick);

五、实验现象

成功测试使用,可以看到执行了两个dwt_delay_ms(100),得到的时间也是比较可观。

六、注意事项

6.1 系统时钟频率的影响

DWT 延迟函数的精度依赖于系统时钟频率的准确性。如果系统时钟频率发生变化,延迟时间也会相应地改变。因此,在使用 DWT 延迟函数时,需要确保系统时钟频率的稳定性。

6.2 计数器溢出问题

由于 CYCCNT 是一个 32 位的计数器,当计数器值达到最大值(2^32 -1)时会发生溢出。在实现延迟函数时,需要注意避免因计数器溢出而导致延迟时间不准确的问题。一般来说,在短时间延迟的情况下,这个问题不会出现,但在长时间延迟时需要特别注意。

七、总结

通过使用 DWT 实现延迟函数,我们可以在空气检测仪项目中获得高精度、灵活且占用资源少的延迟功能。在实际应用中,同时,需要注意系统时钟频率和计数器溢出等问题,以保证延迟函数的可靠性。希望本文能给大家对延迟函数设计有所帮助。

完!!

相关推荐
两万五千个小时6 分钟前
落地实现 Anthropic Multi-Agent Research System
人工智能·python·架构
用户4815930195917 分钟前
揭秘GPT-4与LLaMA背后的加速黑科技:KV Cache、MQA、GQA、稀疏注意力与MoE全解析
人工智能
用户5191495848459 分钟前
Cisco SMA 暴露面检测工具 - 快速识别CVE-2025-20393风险
人工智能·aigc
碳基沙盒14 分钟前
AI工具的“超级外挂”:从零手把手教你搭建私人 MCP 服务器
人工智能
马腾化云东16 分钟前
Agent开发应知应会(langfuse):Langfuse Score概念详解和实战应用
人工智能·llm·ai编程
Baihai_IDP20 分钟前
HackerNews 热榜第一名:AGI 的 A,原来代表的是 Ads(广告)
人工智能·程序员·llm
ma_king21 分钟前
claude+tmux 团队模式使用
人工智能·claude
蓝桉_T1 小时前
Ollama 本地跑 DeepSeek-Coder V3 保姆级教程(Java 调用示例)
人工智能
风象南3 小时前
Token太贵?我用这个数据格式把上下文窗口扩大2倍
人工智能·后端
NAGNIP12 小时前
轻松搞懂全连接神经网络结构!
人工智能·算法·面试