新聞中心
1 前言
在之前的文章在《STM32延時函數(shù)的四種方法》使用定時器延時,在《如何測量代碼運行時間》中提到使用定時器外設(shè)計算代碼運行時間。文中提到這種方法的明顯缺點就是需要占用一個定時器,一些MCU在特定應(yīng)用場景下定時器外設(shè)資源是十分稀缺的。在留言區(qū)有位大佬提到可以使用DWT,我就研究了一番。

邕寧ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!
2 DWT
在Cortex-M里面有一個外設(shè)叫DWT(DataWatchpoint andTrace),是用于系統(tǒng)調(diào)試及跟蹤,DWT的中文名字應(yīng)該是:數(shù)據(jù)觀察點觸發(fā)。在STM32用戶手冊的第32章節(jié)Debugsupport (DBG)有如下框圖。
明顯DWT屬于DBG部分的功能,從上圖的標題可以看出DWT屬于CortexM3內(nèi)核的,理論上M3內(nèi)核的MCU都支持的,這個下文會說明。在這里我將其稱之為“隱藏的定時器”,因為他可以代替定時器外設(shè)實現(xiàn)上文提到延時功能和測量代碼運行時間的功能,DWT不能代替定時器的其他功能。
之所以DWT可以實現(xiàn)延時功能,因為它有一個32的計數(shù)器CYCCNT,這是一個向上計數(shù)的計數(shù)器,當(dāng)它溢出時會自動清零并重新開始向上計數(shù),它的頻率就是內(nèi)核的主頻。簡單點說,就是內(nèi)核時鐘跳動一下,CYCCNT計數(shù)器就加1。
很明顯DWT計數(shù)器的精度和系統(tǒng)主頻有關(guān),我們常用的STM32F103主頻一般為72Mhz,STM32F207一般為120Mhz,STM32H7主頻一般為400Mhz。以為主頻最低為72Mhz的STM32F103為例,精度是1/72M= 14ns,這個精度足以滿足大部分延時函數(shù)的需求,同樣程序的運行時間都是微秒級別的,遠遠滿足測量代碼運行時間的要求。
3 DWT的配置
首選使用DWT前必須使能DBG的系統(tǒng)跟蹤,控制使能位在DEMCR寄存器的bit24。注意該寄存器詳細說明在STM32的用戶手冊上查不到,需要在CortexM3內(nèi)核手冊查到,在《Cortex-M3權(quán)威指南》書中也可以查到。
在使能CYCCNT計數(shù)器前,必須先將其清零。下圖是從ARM的官方手冊《Cortex-M3Technical Reference Manual》中查到的。
使能CYCCNT計數(shù)器,其控制位是DWT控制寄存器的第一位,寫1使能,則啟用CYCCNT計數(shù)器,否則CYCCNT計數(shù)器將不會工作。
總結(jié)一下:
a.先使能DWT外設(shè),由內(nèi)核調(diào)試寄存器DEM_CR的位24控制,寫1使能。
b.使能CYCCNT寄存器之前,先清0。
c.使能CYCCNT寄存器,由DWT_CTRL的位0控制,寫1使能。
代碼如下
- //寄存器基地址
- #define DWT_CR *(uint32_t*)0xE0001000
- #define DWT_CYCCNT *(uint32_t*)0xE0001004
- #define DEM_CR *(uint32_t*)0xE000EDFC
- //定義需使能位
- #define DEM_CR_TRCENA (1<<24)
- #define DWT_CR_CYCCNTENA (1<<0)
- //DWT init
- void DWT_init(void)
- {
- DEM_CR |= (uint32_t)DEM_CR_TRCENA;
- DWT_CYCCNT = (uint32_t)0u;
- DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA;
- }
- //get DWT count
- uint32_t DWT_TS_GET(void)
- {
- return((uint32_t)DWT_CYCCNT);
- }
4 代碼
從上文我們得知,我們已經(jīng)獲得了一個32位向上累加的計數(shù)器,溢出會自動清零并累加,頻率是系統(tǒng)主頻。那么我們簡單封裝下,就可以實現(xiàn)延時函數(shù)。以下代碼在120Mhz的STM32F207測試。
- //使用DWT延時time_ms毫秒
- void DWT_Delay_Ms(uint32_t time_ms)
- {
- uint32_t old_counter,current_counter;
- uint32_t delay_ms;
- old_counter = DWT_TS_GET();
- current_counter = DWT_TS_GET();
- delay_ms = 0;
- while(delay_ms
- {
- current_counter = DWT_TS_GET();
- if(current_counter > old_counter)
- delay_ms = (current_counter - old_counter)/(SystemCoreClock/1000);
- else
- delay_ms = (current_counter + 0XFFFFFFFF - old_counter)/(SystemCoreClock/1000);
- }
- }
使用之前的文章《如何測量代碼運行時間》測量延時函數(shù)是否準確。
- DWT_Delay_Ms(100);//延時100ms
- time_ms=Time_Difference_ms();
如下圖,延時函數(shù)精確延時,沒有問題
實現(xiàn)測量代碼運行時長的函數(shù)接口
- //使用DWT測量函數(shù)運行時間
- float DTW_Time_Difference_ms(void)
- {
- static uint32_t old_counter;
- uint32_t counter,couter_current;
- couter_current = DWT_TS_GET();
- if(couter_current > old_counter)
- counter = couter_current - old_counter;
- else
- counter = couter_current + 0XFFFFFFFF - old_counter;
- old_counter = couter_current;
- return (counter / (SystemCoreClock/1000));
- }
使用之前的文章《STM32延時函數(shù)的四種方法》精確延時,然后使用DWT測量延時時間。
- delay_ms(300);//延時300ms
- time_ms=DTW_Time_Difference_ms();
如下圖,可以精確測量代碼運行時間,沒有問題。
5 后記
本文使用DWT代替了定時器部分功能,它的優(yōu)缺點如下:
1、優(yōu)點是:方便移植,經(jīng)過測試在M3、M4、M7內(nèi)核的MCU上都可以使用。
2、缺點是:和定時器一樣,都有一個延時的最大時間,測量代碼運行時間的最大值。
如果項目使用MCU有空閑的定時器,且不考慮換MCU的話,我個人建議還是使用通用的定時器外設(shè),不要使用DWT,雖然DWT方便移植,但通用定時器外設(shè)簡單易懂,對于沒有了解過這部分知識的小白,看到DWT的延時函數(shù),還需要學(xué)習(xí)下。
本文轉(zhuǎn)載自微信公眾號「知曉編程」
分享標題:STM32“隱藏的定時器”-DWT
瀏覽地址:http://www.5511xx.com/article/dpcdoeh.html


咨詢
建站咨詢
