
01前言 在之前的文章在《STM32延时函数的四种方法》使用定时器延时,在《如何测量代码运行时间》中提到使用定时器外设计算代码运行时间。文中提到这种方法的明显缺点就是需要占用一个定时器,一些MCU在特定应用场景下定时器外设资源是十分稀缺的。在留言区有位大佬提到可以使用DWT,我就研究了一番。 ![]() 02DWT 在Cortex-M里面有一个外设叫DWT(DataWatchpoint andTrace),是用于系统调试及跟踪,DWT的中文名字应该是:数据观察点触发。在STM32用户手册的第32章节Debugsupport (DBG)有如下框图。 ![]() 之所以DWT可以实现延时功能,因为它有一个32的计数器CYCCNT,这是一个向上计数的计数器,当它溢出时会自动清零并重新开始向上计数,它的频率就是内核的主频。简单点说,就是内核时钟跳动一下,CYCCNT计数器就加1。 很明显DWT计数器的精度和系统主频有关,我们常用的STM32F103主频一般为72Mhz,STM32F207一般为120Mhz,STM32H7主频一般为400Mhz。以为主频最低为72Mhz的STM32F103为例,精度是1/72M= 14ns,这个精度足以满足大部分延时函数的需求,同样程序的运行时间都是微秒级别的,远远满足测量代码运行时间的要求。 03 DWT的配置 首选使用DWT前必须使能DBG的系统跟踪,控制使能位在DEMCR寄存器的bit24。注意该寄存器详细说明在STM32的用户手册上查不到,需要在CortexM3内核手册查到,在《Cortex-M3权威指南》书中也可以查到。 ![]() ![]() ![]() a.先使能DWT外设,由内核调试寄存器DEM_CR的位24控制,写1使能。 b.使能CYCCNT寄存器之前,先清0。 c.使能CYCCNT寄存器,由DWT_CTRL的位0控制,写1使能。 代码如下
从上文我们得知,我们已经获得了一个32位向上累加的计数器,溢出会自动清零并累加,频率是系统主频。那么我们简单封装下,就可以实现延时函数。以下代码在120Mhz的STM32F207测试。
![]() 实现测量代码运行时长的函数接口
本文使用DWT代替了定时器部分功能,它的优缺点如下: 1、优点是:方便移植,经过测试在M3、M4、M7内核的MCU上都可以使用。 2、缺点是:和定时器一样,都有一个延时的最大时间,测量代码运行时间的最大值。 如果项目使用MCU有空闲的定时器,且不考虑换MCU的话,我个人建议还是使用通用的定时器外设,不要使用DWT,虽然DWT方便移植,但通用定时器外设简单易懂,对于没有了解过这部分知识的小白,看到DWT的延时函数,还需要学**。 |