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

完!!

相关推荐
触底反弹3 分钟前
🔥 2026 大模型选择指南:别再只看 Benchmark 了,这些维度才是关键!
人工智能·面试
神奇霸王龙22 分钟前
GB/T 46886 闭环屠夫:5 旗舰多模态 LLM 工业质检实测
人工智能·计算机视觉·ai·开源·ai编程·本地部署
南讯股份Nascent39 分钟前
洽洽全域会员项目启动会圆满召开
大数据·人工智能
大郭鹏宇43 分钟前
基于 LangGraph 构建智能分诊系统(一):项目概述与环境搭建
大数据·人工智能·microsoft·langchain
小林ixn1 小时前
大模型的“高考成绩单”:读懂Benchmark,选对真·生产力模型
人工智能·llm·测试
冬奇Lab1 小时前
AI 评测系列(04):RAG 评测——RAGAS 四指标实战与一个反直觉发现
人工智能·llm·agent
三声三视1 小时前
uni-app 鸿蒙端传参变成 [object Object]?顺着源码追到 ArkTS router 底层才搞明白
人工智能·ai·uni-app·aigc·ai编程·harmonyos
fthux2 小时前
“装闭”,让装修套路“装”不下去
人工智能·ai·开源·github·open source
andxe2 小时前
安科士 AndXe 技术博客:400G QSFP112 SR4 光模块|AI 算力与超算短距互联最优方案
网络·人工智能·光模块·光通信
计算机魔术师3 小时前
Karpathy:用语音与LLM长谈可提升理解效率
人工智能·ai编程