stm32内核定时器的使用

之前的文章讲到过Systick定时器,其实DWT内核定时器也是很常见的,而且就是基本上arm内核的芯片都会有这个芯片,这就给我们进行移植提供了方便,关于Systick定时器的记录可以查看:Systick定时器使用以及一些问题记录

1、内核定时器介绍

在 Cortex-M 里面有一个外设叫 DWT(Data Watchpoint and Trace),是用于系统调试及跟踪, 它有一个 32 位的寄存器叫 CYCCNT,它是一个向上的计数器,记录的是内核时钟运行的个数,内核时钟跳动一次,该计数器就加 1。

从上面我们知道就是内核定时器和内核时钟有关,以 F103 系列为例,内核时钟是 72M,那精度就是 1/72M = 14ns,而程序的运行时间都是微秒级别的,所以 14ns 的精度是远远够的。最长能记录的时间为: 60s=2 的 32 次方/72000000(假设内核频率为 72M,内核跳一次的时间大概为 1/72M=14ns),而如果是 H7这种 400M 主频的芯片,那它的计时精度高达 2.5ns( 1/400000000 = 2.5)。当计数器溢出之后,会清 0 重新开始向上计数。

DWT定时器的时钟框图如下所示(图中红色框框出)

在这里插入图片描述

使用的寄存器说明:

  • 1、DEMCR 内核调试寄存器:该寄存器的24位可以决定是否使能内核定时器,写1使能
    在这里插入图片描述
  • 2、DWT_CYCCNT 使能 DWT_CYCCNT 寄存器之前,先清 0。 其基地址是 0xE0001004, 复位默认值是 0,为可读写类型。所以往 0xE0001004 这个地址写就将 DWT_CYCCNT 清 0 了
  • 3、CYCCNTENA 它是 DWT 控制寄存器的第一位,写 1 使能,则启用 CYCCNT 计数器,否则 CYCCNT计数器将不会工作。

2、使用内核定时器

首先定义下寄存器的地址:
在这里插入图片描述
下面就可以开始设置计数函数了:
在这里插入图片描述
适当修改增加ms还有s的计数函数:
在这里插入图片描述
之后就可以在主函数中进行调用了!
在这里插入图片描述

3、源码

DWT_time.c

/*
 * DWT_time.c
 *
 *  Created on: Mar 13, 2022
 *      Author: LX
 */


#include "DWT_time.h"


void vDWTDelayInit(void)
{
    
    
    DEM_CR |= DEM_CR_TRCENA;
    DWT_CYCCNT = 0;
    DWT_CR |= DWT_CR_CYCCNTENA;
}

void vDWTDelayUs(float fTime)
{
    
    
    volatile uint32_t uiTimeStop = 0u, uiTimeStart = 0;

    if(fTime < 0.1f)
        return;

    uiTimeStart = DWT_CYCCNT;
    uiTimeStop  = (uint32_t)((SystemCoreClock / 1000000u) * fTime) + uiTimeStart;

    if(uiTimeStop >= uiTimeStart)
        while((DWT_CYCCNT > uiTimeStart) && (DWT_CYCCNT < uiTimeStop));
    else
        while(!((DWT_CYCCNT > uiTimeStop) && (DWT_CYCCNT < uiTimeStart)));
}
void vDWTDelayMs(float fTime)
{
    
    
    volatile uint32_t uiTimeStop = 0u, uiTimeStart = 0;

    if(fTime < 0.01f)
        return;

    uiTimeStart = DWT_CYCCNT;
    uiTimeStop  = (uint32_t)((SystemCoreClock / 1000u) * fTime) + uiTimeStart;

    if(uiTimeStop >= uiTimeStart)
        while((DWT_CYCCNT > uiTimeStart) && (DWT_CYCCNT < uiTimeStop));
    else
        while(!((DWT_CYCCNT > uiTimeStop) && (DWT_CYCCNT < uiTimeStart)));
}
void vDWTDelayS(uint32_t uiTime)
{
    
    
    uint32_t i = 0u;

    if(uiTime < 1u)
        return;

    for(i = 0u; i < uiTime; ++i)
    {
    
    
        vDWTDelayMs(1000);
    }
}

DWT_time.h

/*
 * DWY_time.h
 *
 *  Created on: Mar 13, 2022
 *      Author: LX
 */

#ifndef DWT_TIME_H_
#define DWT_TIME_H_

#include "main.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)

void vDWTDelayInit(void);
void vDWTDelayS(uint32_t uiTime);
void vDWTDelayMs(float fTime);
void vDWTDelayUs(float fTime);

#endif /* DWT_TIME_H_ */

猜你喜欢

转载自blog.csdn.net/m0_51220742/article/details/123948622