STM32之使用DWT外设编写延时函数
DWT 是一个调试外设,它的核心功能之一是 CYCCNT(Cycle Count),这是一个32位递增计数器,用于记录 CPU 执行的时钟周期数量。我们可以通过对这个计数器的变化来实现高精度延时。
在使用 DWT 延时之前,需要完成以下操作:
- 使能 DWT
- 使能 CYCCNT
- 清零 CYCCNT
- 基于 CYCCNT 实现延时逻辑
源码如下:
- dwt.delay.h文件
#ifndef __DWT_DELAY_H
#define __DWT_DELAY_H
#include "stm32g4xx.h"
/* 获取内核时钟频率 */
#define GET_CPU_ClkFreq()       HAL_RCC_GetSysClockFreq()
uint32_t CPU_TS_TmrRd(void);
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority);
//最大延时值为8秒
void dwt_delay_us(uint32_t us);
#define HAL_Delay(ms)     dwt_delay_us(ms*1000)     
#define dwt_delay_s(s)       dwt_delay_us(s*1000000)
#endif /* __DWT_DELAY_H */
- dwt_delay.c文件
#include "dwt_delay.h"
#define  DWT_CR      *(__IO uint32_t *)0xE0001000
#define  DWT_CYCCNT  *(__IO uint32_t *)0xE0001004
#define  DEM_CR      *(__IO uint32_t *)0xE000EDFC
#define  DEM_CR_TRCENA                   (1 << 24)
#define  DWT_CR_CYCCNTENA                (1 <<  0)
/**
* @brief  初始化时间戳
* @param  无
* @retval 无
* @note   使用延时函数前,必须调用本函数
*/
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)    
{
    /* 使能DWT外设 */
    DEM_CR |= (uint32_t)DEM_CR_TRCENA;
    
    /* DWT CYCCNT寄存器计数清0 */
    DWT_CYCCNT = (uint32_t)0u;
    /* 使能Cortex-M DWT CYCCNT寄存器 */
    DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
    return HAL_OK;
}
/**
* @brief  读取当前时间戳,每1ms更新一次
* @param  无
* @retval ms时间戳
*/
uint32_t HAL_GetTick(void)                              
{
    return ((uint32_t)DWT_CYCCNT/(GET_CPU_ClkFreq()*1000));
}
/**
* @brief  采用CPU的内部计数实现精确延时,32位计数器,最大延时时间8秒
* @param  us : 延迟长度,单位1 us
* @retval 无
*/
void dwt_delay_us(uint32_t us)
{
    uint32_t ticks;
    uint32_t told,tnow,tcnt=0;
    ticks = us * (GET_CPU_ClkFreq() / 1000000);  /* 需要的节拍数 */
    tcnt = 0;
    told = (uint32_t)DWT_CYCCNT;         /* 刚进入时的计数器值 */
    while(1)
    {
        tnow = (uint32_t)DWT_CYCCNT;
        if(tnow != told)
        {
            if(tnow > told)
            {
                tcnt += tnow - told;
            }
            else    /* 重新装载 */
            {
                tcnt += UINT32_MAX - told + tnow;
            }
            told = tnow;
            /*时间超过/等于要延迟的时间,则退出 */
            if(tcnt >= ticks)break;
        }
    }
}
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号