140 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "main.h"
 | ||
| #include "core_delay.h"
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| //获取系统主频
 | ||
| uint32_t GetSysClocksFreq (void)
 | ||
| {
 | ||
| 	RCC_ClocksTypeDef t={0};
 | ||
| 	RCC_GetClocksFreq (&t);
 | ||
| 	return t.SYSCLK_Frequency;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| /*
 | ||
| **********************************************************************
 | ||
| * 时间戳相关寄存器定义
 | ||
| **********************************************************************
 | ||
| */
 | ||
| /*
 | ||
| 在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 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 读取当前时间戳
 | ||
| * @param 无
 | ||
| * @retval 当前时间戳,即DWT_CYCCNT 寄存器的值
 | ||
| */
 | ||
| uint32_t CPU_TS_TmrRd(void)
 | ||
| {
 | ||
|     return ((uint32_t)DWT_CYCCNT);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
| * @brief 读取当前时间戳
 | ||
| * @param 无
 | ||
| * @retval 当前时间戳,即DWT_CYCCNT 寄存器的值
 | ||
| */
 | ||
| uint32_t HAL_GetTick(void)
 | ||
| {
 | ||
|     return ((uint32_t)DWT_CYCCNT*1000/SysClockFreq);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * @brief   采用CPU 的内部计数实现精确延时,32 位计数器
 | ||
|  * @param   us : 延迟长度,单位1 us
 | ||
|  * @retval  无
 | ||
|  * @note    使用本函数前必须先调用CPU_TS_TmrInit 函数使能计数器,
 | ||
|  *          或使能宏CPU_TS_INIT_IN_DELAY_FUNCTION
 | ||
|  *最大延时值为8 秒,即8*1000*1000
 | ||
|  */
 | ||
| void CPU_TS_Tmr_Delay_US(uint32_t us)
 | ||
| {
 | ||
|     uint32_t ticks;
 | ||
|     uint32_t told, tnow, tcnt=0;
 | ||
| 
 | ||
|     /* 在函数内部初始化时间戳寄存器, */
 | ||
|     #if (CPU_TS_INIT_IN_DELAY_FUNCTION)
 | ||
|     /* 初始化时间戳并清零 */
 | ||
|     HAL_InitTick(5);
 | ||
|     #endif
 | ||
| 
 | ||
|     ticks = us * (GET_CPU_ClkFreq() / 1000000); /* 需要的节拍数 */
 | ||
|     tcnt = 0;
 | ||
|     told = (uint32_t)CPU_TS_TmrRd(); /* 刚进入时的计数器值 */
 | ||
| 
 | ||
|     while (1) 
 | ||
|     {
 | ||
|         tnow = (uint32_t)CPU_TS_TmrRd();
 | ||
|         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**********************/
 |