【国民技术车规MCU N32A455开发板】基于内核DWT实现硬件延时
[复制链接]
本帖最后由 尹小舟 于 2024-2-23 17:07 编辑
在Cortex-M里面有一个外设叫DWT(DataWatchpoint andTrace),是用于系统调试及跟踪,DWT的中文名字应该是:数据观察点触发。
理论上M3,M4内核的MCU都支持的,M0不支持此功能,DWT属于DBG部分的功能。在这里我将其称之为“隐藏的定时器”,因为他可以代替定时器外设实现延时功能和测量代码运行时间的功能,DWT不能代替定时器的其他功能。
之所以DWT可以实现延时功能,因为它有一个32的计数器CYCCNT,这是一个向上计数的计数器,当它溢出时会自动清零并重新开始向上计数,它的频率就是内核的主频。简单点说,就是内核时钟跳动一下,CYCCNT计数器就加1。而单片机程序的运行时间通常都是微秒级别的,所以DWT实现延时的精度是非常高的。
如果内核时钟是120MHz,直接使用CYCCNT延时最大值为36S
要实现DWT延时的功能,总共涉及到三个内核寄存器:DEMCR、DWT_CTRL、DWT_CYCCNT,分别用 于开启DWT功能、开启CYCCNT及获得系统时钟计数值;当CYCCNT溢出之后,会清O重新开始向上计数。
1、先使能DWT外设,由内核调试寄存器DEM_CR的位24控制,写1使能。
2、使能CYCCNT寄存器之前,先清0。
3、使能CYCCNT寄存器,由DWT_CTRL的位0控制,写1使能。
#include "dwt_delay.h"
void Delaylnit(void)
{
/* 关闭 TRC */
CoreDebug->DEMCR &=~CoreDebug_DEMCR_TRCENA_Msk;
/* 打开 TRC */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
/*关闭计数功能 */
DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk;
/*打开计数功能 */
DWT->CTRL|= DWT_CTRL_CYCCNTENA_Msk;
/*计数清零 */
DWT->CYCCNT = 0;
}
void DelayNus(uint32_t nUs)
{
uint32_t tickStart = DWT ->CYCCNT;
nUs *= 144000000/1000000 ;
while((DWT->CYCCNT - tickStart) < nUs);
}
void DelayNms(uint32_t nMs)
{
uint32_t i = 0;
for(i = 0; i < nMs; i++)
{
DelayNus(1000);
}
}
int main(void)
{
/* System Clocks Configuration */
RCC_Configuration();
/* Configure the GPIO ports */
GPIO_Configuration();
/* USARTy and USARTz configuration ------------------------------------------------------*/
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTx */
USART_Init(USARTx, &USART_InitStructure);
/* Enable the USARTx */
USART_Enable(USARTx, ENABLE);
/* Output a message on Hyperterminal using printf function */
printf("\n\rUSART Printf Example: retarget the C library printf function to the USART\n\r");
Delaylnit();
while(1)
{
DelayNms(1000);
printf("\n\rDWT Delay\n\r");
}
}
实验现象
|