M3中使用DWT进行精确延时(STM32和GD32)

[复制链接]
8383|7
手机看帖
扫描二维码
随时随地手机跟帖
sunmeat|  楼主 | 2014-11-10 18:50 | 显示全部楼层 |阅读模式
本帖最后由 sunmeat 于 2014-11-10 18:56 编辑

这个代码由网友@zkcaptain 找到的,未测试版本,但是应该是可行的,和利用systick不占用中断精确延时一个道理,稍后进行测试
#define  DWT_CR      *(volatile u32 *)0xE0001000

#define  DWT_CYCCNT  *(volatile u32 *)0xE0001004

#define  DEM_CR      *(volatile u32 *)0xE000EDFC

#define  DEM_CR_TRCENA                   (1 << 24)

#define  DWT_CR_CYCCNTENA                (1 <<  0)




#define Delayms(msec)         Delayus(msec*1000)  //对于延时毫秒级的只需要定义一个宏

static u32 cpuclkfeq;     //用于保存cpu运行频率,可运行时动态修改



//初始化延时系统,参数为CPU频率

void DelayInit(u32 clk)
{

    cpuclkfeq = clk;
//打开CYCCNT功能,并把计数器清零,最后打开计数器对cpu时钟进行向上计数

    DEM_CR         |=  DEM_CR_TRCENA;

//    DWT_CYCCNT      = 0u;    //根据需要如果调试,或其他程序要使用CYCCNT时注释掉,否则可直接清零

    DWT_CR         |= DWT_CR_CYCCNTENA;

}



//延时函数,参数为需要延时的微秒数
void Delayus(u32 usec)

{

     u32 startts,endts,ts;

  //保存进入函数时的计数器值

     startts = DWT_CYCCNT;

     ts =  usec * (cpuclkfeq /(1000*1000) );        //计算达到所需延时值的cpu时钟数,^-^如果想要更精确此处可以减去运行前面代码所需的时钟数。

     endts = startts + ts;           //计算达到所需延时时间的DWT_CYCCNT计数值,超过32bit所能表达的最大值2的32次方-1是自动绕回丢弃进位

      if(endts > startts)            //判断是否跨越最大值边界

      {

          while(DWT_CYCCNT < endts);        //等到计数到所需延时值的cpu时钟数值

       }

       else

      {

           while(DWT_CYCCNT > endts);       //等待跨域32bit的最大值,2的32次方-1

           while(DWT_CYCCNT < endts);        //等到计数到所需延时值的cpu时钟数值

      }



}

sunmeat|  楼主 | 2014-11-10 20:10 | 显示全部楼层
经测试,没有错误,上面的代码复制过程中有个括号有问题,经更正为放在.h和.c文件中。DWT_Delay.h中的代码如下
#ifndef __DWT_DELAYG_H_
#define __DWT_DELAYG_H_

#include "stm32f10x_conf.h"

#define  DWT_CR      *(volatile u32 *)0xE0001000

#define  DWT_CYCCNT  *(volatile u32 *)0xE0001004

#define  DEM_CR      *(volatile u32 *)0xE000EDFC

#define  DEM_CR_TRCENA                   (1 << 24)

#define  DWT_CR_CYCCNTENA                (1 <<  0)




#define Delayms(msec)         Delayus(msec*1000)  //对于延时毫秒级的只需要定义一个宏

void DelayInit(u32 clk);
void Delayus(u32 usec);
#endif

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
zkcaptain + 3 感谢楼主
sunmeat|  楼主 | 2014-11-10 20:10 | 显示全部楼层
DWT_Delay.c中的代码如下

#include "DWT_Delay.h"



static u32 cpuclkfeq;     //用于保存cpu运行频率,可运行时动态修改



//初始化延时系统,参数为CPU频率

void DelayInit(u32 clk)
{

    cpuclkfeq = clk;
//打开CYCCNT功能,并把计数器清零,最后打开计数器对cpu时钟进行向上计数

    DEM_CR         |=  DEM_CR_TRCENA;

//    DWT_CYCCNT      = 0u;    //根据需要如果调试,或其他程序要使用CYCCNT时注释掉,否则可直接清零

    DWT_CR         |= DWT_CR_CYCCNTENA;

}



//延时函数,参数为需要延时的微秒数
void Delayus(u32 usec)

{

     u32 startts,endts,ts;

  //保存进入函数时的计数器值

     startts = DWT_CYCCNT;

     ts =  usec * (cpuclkfeq /(1000*1000));        //计算达到所需延时值的cpu时钟数,^-^如果想要更精确此处可以减去运行前面代码所需的时钟数。

     endts = startts + ts;           //计算达到所需延时时间的DWT_CYCCNT计数值,超过32bit所能表达的最大值2的32次方-1是自动绕回丢弃进位

      if(endts > startts)            //判断是否跨越最大值边界

      {

          while(DWT_CYCCNT < endts);        //等到计数到所需延时值的cpu时钟数值

       }

       else

      {

           while(DWT_CYCCNT > endts);       //等待跨域32bit的最大值,2的32次方-1

           while(DWT_CYCCNT < endts);        //等到计数到所需延时值的cpu时钟数值

      }



}

使用特权

评论回复
评分
参与人数 1威望 +3 收起 理由
zkcaptain + 3 感谢楼主
陈子建| | 2015-1-17 22:02 | 显示全部楼层
这个程序运行的前提有没有区分CPU是使用哪一个时钟呢?是72MHz的主频还是8MHz的?

使用特权

评论回复
陈子建| | 2015-1-17 22:29 | 显示全部楼层
//我搞错了,这个函数应该是这么用的。
#include "stm32f10x.h"
#include "usart1.h"
#include "DWT_Delay.h"

/*
* 函数名:main
* 描述  :主函数,使用串口打印出数据
* 输入  :无
* 输出  :无
*/
int main(void)
{       
        int i=0;
        int j;
        /* USART1 config 115200 8-N-1 */
        USART1_Config();    //串口配置
        DelayInit(SystemCoreClock);      //延时函数初始化,讲CPU的主频给DelayInit函数,主频在system_stm32f10x.c中
        for(j=0;j<20;j++)               //循环打印20次,每次间隔1m打印一个数后换行
        {
                printf("%d",i);
                printf("\r\n");
                Delayms(1000);
                i=i+1;
        }
}

使用特权

评论回复
jpaekeo| | 2018-1-15 20:58 | 显示全部楼层
给大神点赞,精神可嘉。

使用特权

评论回复
poikjhmng| | 2018-1-24 14:51 | 显示全部楼层
能否做一个宏,来了应对不同的主频

使用特权

评论回复
lsz318| | 2018-5-19 10:21 | 显示全部楼层

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

208

主题

2132

帖子

13

粉丝