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號