天天看點

使用DWT來實作系統延時

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。

使用DWT來實作系統延時
使用DWT來實作系統延時
使用DWT來實作系統延時

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

DWT_CTRL寄存器

其包含很多功能,這裡我們隻開啟其循環計數功能。

使用DWT來實作系統延時
使用DWT來實作系統延時
使用DWT來實作系統延時

CYCCNT寄存器

該寄存器位址見上圖,其描述如下:

使用DWT來實作系統延時

當DWT的CYCCNTENA位置位後,該寄存器的值與系統周期計數值保持同步,我們可以用它的值來實作一個延時的功能。

2. 延時程式編寫

直接上代碼:

延時函數源檔案:

#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 );
  }
}
           

延時函數頭檔案:

#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其它外設資源的延時函數就實作了。

繼續閱讀