#ifndef __GDWT_DELAY_H
#define __GDWT_DELAY_H
//#include "stm32f7xx.h"
//#include "stm32l4xx.h"
#include "stm32f1xx.h"
HAL_StatusTypeDef GHAL_InitTick(uint32_t TickPriority);
void CPU_TS_Tmr_Delay_US(uint32_t us);//最大延时值为8秒
#endif
#include "gdwt_delay.h"
/* 获取内核时钟频率 */
#define GET_CPU_ClkFreq() HAL_RCC_GetSysClockFreq()
/*
**********************************************************************
* 时间戳相关寄存器定义
**********************************************************************
*/
/*
在Cortex-M里面有一个外设叫DWT(Data Watchpoint and Trace),
该外设有一个32位的寄存器叫CYCCNT,它是一个向上的计数器,
记录的是内核时钟运行的个数,最长能记录的时间为:
10.74s=2的32次方/400000000
(假设内核频率为400M,内核跳一次的时间大概为1/400M=2.5ns)
当CYCCNT溢出之后,会清0重新开始向上计数。
使能CYCCNT计数的操作步骤:
1、先使能DWT外设,这个由另外内核调试寄存器DEMCR的位24控制,写1使能
2、使能CYCCNT寄存器之前,先清0
3、使能CYCCNT寄存器,这个由DWT_CTRL(代码上宏定义为DWT_CR)的位0控制,写1使能
*/
#define DEM_CR *(__IO uint32_t *)0xE000EDFC
#define DEM_CR_TRCENA (1 << 24)
#define DWT_CR *(__IO uint32_t *)0xE0001000
#define DWT_CYCCNT *(__IO uint32_t *)0xE0001004
#define DWT_CR_CYCCNTENA (1 << 0)
/**
* @brief 初始化时间戳
* @param 无
* @retval 无
* @note 使用延时函数前,必须调用本函数
*****注意 MX已经有了__weak这个函数*******
*/
HAL_StatusTypeDef GHAL_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 读取当前时间戳
* @param 无
* @retval 当前时间戳,即DWT_CYCCNT寄存器的值
*/
uint32_t CPU_TS_TmrRd(void)
{
return ((uint32_t)DWT_CYCCNT);
}
/**
* @brief 采用CPU的内部计数实现精确延时,32位计数器
* @param us : 延迟长度,单位1 us
* @retval 无
* @note 使用本函数前必须先调用CPU_TS_TmrInit函数使能计数器,
或使能宏CPU_TS_INIT_IN_DELAY_FUNCTION
最大延时值为8秒,即8*1000*1000
*/
uint32_t told,tnow,tcnt=0;
void CPU_TS_Tmr_Delay_US(uint32_t us)
{
uint32_t ticks;
ticks = us * (GET_CPU_ClkFreq() / 1000000); /* 需要的节拍数 */
tcnt = 0;
told = (uint32_t)CPU_TS_TmrRd(); /* 刚进入时的计数器值此时0XA6 */
while(1)
{
tnow = (uint32_t)CPU_TS_TmrRd(); //此时是0XA9
if(tnow != told)
{
/* 32位计数器是递增计数器 */
if(tnow > told)
{
tcnt += tnow - told;
}
/* 重新装载 */
else
{
tcnt += UINT32_MAX - told + tnow;
}
told = tnow;
/*时间超过/等于要延迟的时间,则退出 */
if(tcnt >= ticks)break;
}
}
}
/*********************************************END OF FILE**********************/
测试main
GHAL_InitTick(0);
while (1)
{
LEDPC78TESTE();
}
void LEDPC78TESTE(void)
{
uint32_t value ;
value = GReadGPIOOutput(GPIOC);
value ^=0X0180;
GWriteGPIOOutput(GPIOC,value);
CPU_TS_Tmr_Delay_US(1000000);
}
可以看到和HAL_DELAY(1000)效果差不多1S一次