WT 是一个调试外设,它的核心功能之一是 CYCCNT(Cycle Count),这是一个32位递增计数器,用于记录 CPU 执行的时钟周期数量。我们可以通过对这个计数器的变化来实现高精度延时。
在使用 DWT 延时之前,需要完成以下操作:
- 使能 DWT
- 使能 CYCCNT
- 清零 CYCCNT
- 基于 CYCCNT 实现延时逻辑
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #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);
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| #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)
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) { DEM_CR |= (uint32_t)DEM_CR_TRCENA; DWT_CYCCNT = (uint32_t)0u;
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
return HAL_OK; }
uint32_t HAL_GetTick(void) { return ((uint32_t)DWT_CYCCNT/(GET_CPU_ClkFreq()*1000)); }
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; } } }
|