OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子全套STM32开发资料,上千讲STM32视频教程,RT1052教程免费下载啦...

查看: 47|回复: 0

使用DWT来实现系统延时(我是转帖,并非我原创)

[复制链接]

  离线 

7

主题

177

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2320
金钱
2320
注册时间
2015-12-27
在线时间
411 小时
发表于 6 天前 | 显示全部楼层 |阅读模式
正点原子公众号
本帖最后由 钩月黄昏 于 2018-7-13 10:07 编辑

版权声明:原创文章,随便转载,注明出处即可。        https://blog.csdn.net/liuluqqzj/article/details/44998581

DWT,全称是The Debug Watchpoint and Trace (DWT) unit,用于系统调试及跟踪,

详细的介绍可以参考ARM官方文档:ARMv7-M Architecture Reference Manual。本文将使它来实现一个系统的延时功能。

1. 寄存器简单介绍

要实现延时的功能,总共涉及到三个寄存器:DEMCR 、DWT_CTRL、DWT_CYCCNT,分别用于开启DWT功能、开启CYCCNT及获得系统时钟计数值。


DEMCR:

其官方手册说明如下,这里我们只需要关注其第24位引脚TRCENA。



该寄存器的TRCENA位置位,使能DWT功能


DWT_CTRL寄存器

其包含很多功能,这里我们只开启其循环计数功能。



CYCCNT寄存器

该寄存器地址见上图,其描述如下:


当DWT的CYCCNTENA位置位后,该寄存器的值与系统周期计数值保持同步,我们可以用它的值来实现一个延时的功能。


2. 延时程序编写


直接上代码:

延时函数源文件:

[C] 纯文本查看 复制代码
[/p][p=26, null, left]#include "DWTDelay.h"
 
// 0xE000EDFC DEMCR RW Debug Exception and Monitor Control Register.
#define DEMCR           ( *(unsigned int *)0xE000EDFC )
#define TRCENA          ( 0x01 << 24) // DEMCR的DWT使能位
 
// 0xE0001000 DWT_CTRL RW The Debug Watchpoint and Trace (DWT) unit
#define DWT_CTRL        ( *(unsigned int *)0xE0001000 )
#define CYCCNTENA       ( 0x01 << 0 ) // DWT的SYCCNT使能位
// 0xE0001004 DWT_CYCCNT RW Cycle Count register, 
#define DWT_CYCCNT      ( *(unsigned int *)0xE0001004) // 显示或设置处理器的周期计数值
 
//#define DWT_DELAY_mS(mSec)    DWT_DELAY_uS(mSec*1000)
 
static int SYSCLK = 0;;
 
void DWT_INIT(int sys_clk)
{
  DEMCR |= TRCENA;
  DWT_CTRL |= CYCCNTENA;
  
  SYSCLK = sys_clk; // 保存当前系统的时钟周期,eg. 72,000,000(72MHz). 
}
 
// 微秒延时
void DWT_DELAY_uS(int uSec)
{
  int ticks_start, ticks_end, ticks_delay;
  
  ticks_start = DWT_CYCCNT;
  
  if ( !SYSCLK )
    DWT_INIT( MY_MCU_SYSCLK );
  
  ticks_delay = ( uSec * ( SYSCLK / (1000*1000) ) ); // 将微秒数换算成滴答数          
  
  ticks_end = ticks_start + ticks_delay;
  
  if ( ticks_end > ticks_start )
  {
    while( DWT_CYCCNT < ticks_end );
  }
  else // 计数溢出,翻转
  {
    while( DWT_CYCCNT >= ticks_end ); // 翻转后的值不会比ticks_end小
    while( DWT_CYCCNT < ticks_end );
  }
}


延时函数头文件:
[C] 纯文本查看 复制代码

#ifndef _DWTDELAY_H_
 
#define _DWTDELAY_H_
 
// 根据MCU做修改
#define MY_MCU_SYSCLK           (72000000)

void DWT_INIT(int sys_clk);
 
// 微秒延时
void DWT_DELAY_uS(int uSec);
 
#define DWT_DELAY_mS(mSec)    DWT_DELAY_uS( mSec*1000 )
 
#endif // _DWTDELAY_H_


至此,简单、好用、精准又不占用CPU其它外设资源的延时函数就实现了。




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则




关闭

"原子哥”推荐上一条 /1 下一条

QQ|联系我们|手机版|官方淘宝店|新浪微博|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-7-19 06:15

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表
/* */