/**
******************************************************************
* file core_delay.c
* author fire
* version V1.0
* date 2018-xx-xx
* [url=home.php?mod=space&uid=247401]@brief[/url] 使用内核寄存器精确延时
******************************************************************
* @attention
*
* 实验平台:野火 STM32开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :https://fire-stm32.taobao.com
*
******************************************************************
*/ #include "./delay/core_delay.h" /*
**********************************************************************
* 时间戳相关寄存器定义
**********************************************************************
*/
/*
在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 //< 0xE0001000 DWT_CTRL RW The Debug Watchpoint and Trace (DWT) unit
    #define  DWT_CYCCNT  *(__IO uint32_t *)0xE0001004 //< 0xE0001004 DWT_CYCCNT RW Cycle Count register, 
    #define  DEM_CR      *(__IO uint32_t *)0xE000EDFC //< 0xE000EDFC DEMCR RW Debug Exception and Monitor Control Register.

    #define  DEM_CR_TRCENA                   (1 << 24)  //DEMCR的DWT使能位
    #define  DWT_CR_CYCCNTENA                (1 <<  0)  //DWT的SYCCNT使能位
    /**
* @brief 初始化时间戳
* @param 无
* @retval 无
* [url=home.php?mod=space&uid=536309]@NOTE[/url] 使用延时函数前,必须调用本函数
*/
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/SysClockFreq*);
} /**
* @brief 采用CPU的内部计数实现精确延时,32位计数器
* @param us : 延迟长度,单位1 us
* @retval 无
* [url=home.php?mod=space&uid=536309]@NOTE[/url] 使用本函数前必须先调用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=; /* 在函数内部初始化时间戳寄存器, */
#if (CPU_TS_INIT_IN_DELAY_FUNCTION)
/* 初始化时间戳并清零 */
HAL_InitTick();
#endif ticks = us * (GET_CPU_ClkFreq() / ); /* 需要的节拍数 */
tcnt = ;
told = (uint32_t)CPU_TS_TmrRd(); /* 刚进入时的计数器值 */ while()
{
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**********************/
    #ifndef __CORE_DELAY_H
#define __CORE_DELAY_H #include "stm32h7xx.h" /* 获取内核时钟频率 */
#define GET_CPU_ClkFreq() HAL_RCC_GetSysClockFreq()
#define SysClockFreq (218000000)
/* 为方便使用,在延时函数内部调用CPU_TS_TmrInit函数初始化时间戳寄存器,
这样每次调用函数都会初始化一遍。
把本宏值设置为0,然后在main函数刚运行时调用CPU_TS_TmrInit可避免每次都初始化 */ #define CPU_TS_INIT_IN_DELAY_FUNCTION 0 /*******************************************************************************
* 函数声明
******************************************************************************/
uint32_t CPU_TS_TmrRd(void);
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority); //使用以下函数前必须先调用CPU_TS_TmrInit函数使能计数器,或使能宏CPU_TS_INIT_IN_DELAY_FUNCTION
//最大延时值为8秒
void CPU_TS_Tmr_Delay_US(uint32_t us);
#define HAL_Delay(ms) CPU_TS_Tmr_Delay_US(ms*1000)
#define CPU_TS_Tmr_Delay_S(s) CPU_TS_Tmr_Delay_MS(s*1000) #endif /* __CORE_DELAY_H */

上面代码的核心是:采用Cortex-M3/4内核中的跟踪组件DWT的时钟周期计数CYCCNT实现

参考链接

http://www.firebbs.cn/forum.php?mod=viewthread&tid=19059&fromuid=1

https://blog.csdn.net/linux_liulu/article/details/44998581

【转】STM32 不占用定时器(包括SysTick)实现精确延时(巧用DWT)的更多相关文章

  1. 使用系统定时器SysTick实现精确延时微秒和毫秒函数

    SysTick定时器简介 SysTick定时器是存在于系统内核的一个滴答定时器,只要是ARM Cortex-M0/M3/M4/M7内核的MCU都包含这个定时器,它是一个24位的递减定时器,当计数到 0 ...

  2. STM32时钟系统之利用 systick 定时器来实现准确的延时。

    本篇文章带着大家来认识一下 STM32 的时钟系统,以及利用 systick 定时器来实现一个比较准确的延时. 我们首先从时钟说起,时钟在MCU中的作用,就好比于人类的心脏一样不可或缺.STM32 的 ...

  3. STM32学习笔记——定时器中断(向原子哥学习)

    定时器中断 STM32 的定时器功能十分强大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和TIME7 等基本定时器.在本章中,我们将利 ...

  4. 实现流水灯以间隔500ms的时间闪烁(系统定时器SysTick实现的精确延时)

    /** ****************************************************************************** * @file main.c * ...

  5. STM32 TIM高级定时器死区时间的计算

    STM32 TIM高级定时器的互补PWM支持插入死区时间,本文将介绍如何计算以及配置正确的死区时间. 文章目录 什么是死区时间? 数据手册的参数 如何计算合理的死区时间? STM32中配置死区时间 什 ...

  6. STM32 TIM1高级定时器RCR重复计数器的理解

    STM32 TIM1高级定时器RCR重复计数器的理解 TIMx_RCR重复计数器寄存器,重复计数器只支持高级定时器TIM1和TIM8,下面看标准外设库的TIM结构体的封装: typedef struc ...

  7. 基于Systick系统时钟延时的LED闪烁灯

    1.回顾我们的51 单片机编程,当我们需要做系统延迟的时候,最常采用的一种方式就是使用for 循环的空语句等待来实现. 当然,在STM32 里面也可以这么实现.但是在STM32 的Cortex 内核里 ...

  8. stm32之Cortex系统定时器(SysTick)

    转载自:http://www.21ic.com/app/mcu/201811/781135.htm   SysTick时钟,俗称“嘀嗒定时器”,它能按设定的时间产生一次中断.控制工程代码中随处可见形如 ...

  9. [stm32] STM32的通用定时器TIMx系统了解

    通用定时器(TIMx) 一.TIMx简介 二.TIMx主要功能 三.TIMx功能描述 3.1 时基单元 3.2 计数器模式 3.3 时钟选择 3.4 捕获/比较通道 3.5 输入捕获模式 3.6 PW ...

随机推荐

  1. admin-2

    Linux是一种服务器操作系统 操作系统:一堆软件的集合,可以让计算机硬件正常工作 • UNIX诞生,1970-1-1(Linux系统时间的起点) • Linux之父,Linus Torwalds 内 ...

  2. java设计模式概述

    java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模 ...

  3. centos7镜像文件

    1.打开网址https://www.centos.org/download/2.点击Minimall ISO 按钮  3.选择aliyun地址 4.centos版本介绍 在CentOS官方网站上,Ce ...

  4. Mysql--基础(一)

    MySQL基础 一.数据库的操作 1.SQL分类: DDL(数据定义语言)   :数据定义语言 - Data Definition Language,用来定义数据库的对象,如数据表.视图.索引等.常用 ...

  5. 视频信号中xyz的提取

    视频信号中xyz的提取 `timescale 1ns / 1ps /////////////////////////////////////////////////////////////////// ...

  6. office 32-bit components 2010 的卸载

    卸载方法:MsiExec.exe /X {90140000-0043-0000-1000-0000000FF1CE}

  7. 【C++】智能指针简单剖析

    转自 http://www.cnblogs.com/lanxuezaipiao/p/4132096.html 导读 最近在补看<C++ Primer Plus>第六版,这的确是本好书,其中 ...

  8. RTP协议

    RTP协议格式: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+ ...

  9. python3学习笔记11(函数)

    函数 python提供了许多内建函数,例如print(). 自己创建的函数,叫做用户自定义函数. 定义一个由自己想要功能的函数,以下是简单的规则: 函数代码块以 def 关键词开头,后接函数标识符名称 ...

  10. 删除DataTable的指定行(Lambda)

    DataTable dtTcu = GetAllTcuInfoBySdId(sdId); DataTable dtToesm = GetAllToesmBySdId(sdId); foreach (D ...