STM32的精确延时DWT

此延时用在freertos运行前和运行后 均可以,已在F407和F767上实测.

并且在不可用DWT的芯片上也能自动使用最基本的模拟延时delay_us_simulate。在freertos运行起来以后会自动切换到非堵塞的vTaskDelay上。

注意事项:

        关于DWT_Init函数开始的解锁操作,实际F4不需要此操作,因为默认没锁,但加上也没问题。但F7必须进行此操作。

//可根据有没有使用freeftos来决定是否注释掉下面的这个宏定义
#define USE_FREEFTOS	1

#ifdef USE_FREEFTOS
	#include "FreeRTOS.h"
	#include "task.h"
	#include "main.h"
	#include "cmsis_os.h"
#endif

#define DWT_CTRL   (*(volatile uint32_t *)0xE0001000)
#define DWT_CYCCNT (*(volatile uint32_t *)0xE0001004)
#define DEMCR      (*(volatile uint32_t *)0xE000EDFC)
#define DEMCR_TRCENA (1 << 24)

// DWT Lock 相关寄存器
#define DWT_LAR    (*(volatile uint32_t *)0xE0001FB0)  // Lock Access Register
#define DWT_LSR    (*(volatile uint32_t *)0xE0001FB4)  // Lock Status Register
	
static uint8_t dwt_available = 0;

void DWT_Init(void) {
	DWT_LAR = 0xC5ACCE55;  // Magic key to unlock DWT
    __DSB();
    __ISB();
	
    // 检查DWT是否可用
    if ((DWT_CTRL & 1) == 0) {
        DEMCR |= DEMCR_TRCENA;
        DWT_CYCCNT = 0;
        DWT_CTRL |= 1;
    }
    dwt_available = (DWT_CTRL & 1) ? 1 : 0;
	
	if (!dwt_available) {printf("API:DWT error");}
}

void delay_us(uint32_t us) {
    if (dwt_available) {
        uint32_t start = DWT_CYCCNT;
        uint32_t cycles = us * (SystemCoreClock / 1000000);
        while ((DWT_CYCCNT - start) < cycles);
    } 
	else {
        delay_us_simulate(1);
    }
}

void delay_ms(uint32_t ms) {
    if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
        // FreeRTOS未启动,使用DWT延时
        for (uint32_t i = 0; i < ms; i++) {
            delay_us(1000);
        }
    } 
	else {
        // FreeRTOS已启动,使用vTaskDelay
        vTaskDelay(pdMS_TO_TICKS(ms));
    }
}

// 微秒级延时(阻塞式,适用于168MHz HCLK)
void delay_us_simulate(uint16_t us) {
    volatile uint32_t cycles = us * (168 / 4);  // 168MHz下,每个循环约4周期
    while (cycles--);
}
	main.c的main()中,基本的初始化完成后:
    
    DWT_Init();
	printf("APP:start1:%d,%d\n",API_TIM7_Count,SystemCoreClock);
	delay_ms(200);
	delay_ms(200);
	printf("APP:start2:%d\n",API_TIM7_Count);

F407上运行结果:

[17:15:19.452]APP:start1:1,168000000

[17:15:20.191]APP:start2:403

解释:

API_TIM7_Count是TIM7定时器的计数值,1ms增加一次。即以上表明,延时400ms时TIM7定时器中断了406次。还是比较准确的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值