STM32HAL库微秒延时函数的实现---DWT和SysTick

STM32HAL库微秒延时函数实现---DWT和SysTick
⽂章⽬录
STM32 HAL库微秒延时函数的实现
天下苦STM32 HAL库微秒延时久已。不占⽤其他定时器资源⼜不使⽤循环的⽅式就不能实现微秒延时函数了吗?答案是否定的,我们还有⽅式实现,且还不⽌⼀种⽅法。详情且看下⽂分解:
以下两种延时⽅式来源:Arduino_Core_STM32源码delayMicroseconds(uint32_t us)函数的实现。
利⽤SysTick再实现微秒延时函数
虽然SysTick已经被配置为1ms中断⼀次的模式,但每个1ms之间SysTick的当前值寄存器是⼀直在计数的(每计⼀个数的时间友商网在线会计
是1/SytemCoreClock)我们便可以利⽤该机制实现微秒延时函数。
void delayMicroseconds(uint32_t us)
{
__IO uint32_t currentTicks = SysTick->VAL;
/* Number of ticks per millisecond */
const uint32_t tickPerMs = SysTick->LOAD +1;
/* Number of ticks to count */
const uint32_t nbTicks =((us -((us >0)?1:0))* tickPerMs)/1000;
/* Number of elapsed ticks */
uint32_t elapsedTicks =0;
__IO uint32_t oldTicks = currentTicks;
do{
currentTicks = SysTick->VAL;
elapsedTicks +=(oldTicks < currentTicks)? tickPerMs + oldTicks - currentTicks :
oldTicks - currentTicks;
oldTicks = currentTicks;
}while(nbTicks > elapsedTicks);
}
以上函数可以直接复制到⼯程中使⽤,不需要额外的任何配置。
Note
虽然函数参数us为uint32_t类型,但是延时数不能过⼤,原因⾃⼰分析。建议超过1ms的延时时间使⽤HAL_Delay()。
利⽤DWT(数据观测点)实现微秒延时函数
北京医科大学对于DWT⼤家可以搜索具体了解,这⾥我也不是很了解,就直说实现⽅法好了。
dwt.h⽂件
/**
******************************************************************************
* @file    dwt.h
* @author  Frederic Pillon
* @brief  Header for dwt.c module
******************************************************************************
* @attention
*
* Copyright (c) 2019, STMicroelectronics
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,  * the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*                        /licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _DWT_H_
#define _DWT_H_
duzhe#include"stm32f4xx.h"
#include<stdbool.h>
#ifndef UNUSED
#define UNUSED(x) (void)x
#endif
#ifdef DWT_BASE
uint32_t dwt_init(void);
#ifdef __cplusplus
extern"C"{
#endif
//uint32_t dwt_init(void);
void dwt_access(bool ena);
static inline uint32_t dwt_max_sec(void)
{
return(UINT32_MAX / SystemCoreClock);
};
static inline uint32_t dwt_max_msec(void)
{
return(UINT32_MAX /(SystemCoreClock /1000));
};
static inline uint32_t dwt_max_usec(void)
{
return(UINT32_MAX /(SystemCoreClock /1000000));
};
static inline uint32_t dwt_getCycles(void)
{
return(DWT->CYCCNT);
};
#ifdef __cplusplus
}
#endif冠东集装箱码头
#endif/* DWT_BASE */
#endif/* _DWT_H_ */
dwt.c⽂件
/
**
******************************************************************************
* @file    dwt.c
* @author  Frederic Pillon
* @brief  Provide Data Watchpoint and Trace services
******************************************************************************
* @attention
*
* Copyright (c) 2019, STMicroelectronics
* All rights reserved.
斜发沸石*
* This software component is licensed by ST under BSD 3-Clause license,  * the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*                        /licenses/BSD-3-Clause
*
******************************************************************************
*/
#include"dwt.h"
东丰县第二实验小学
#ifdef DWT_BASE
#ifdef __cplusplus
extern"C"{
#endif
uint32_t dwt_init(void)
{
/* Enable use of DWT */
if(!(CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk)){
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
}
/* Unlock */
dwt_access(true);
/* Reset the clock cycle counter value */
DWT->CYCCNT =0;
/* Enable  clock cycle counter */
DWT->CTRL |=  DWT_CTRL_CYCCNTENA_Msk;
/* 3 NO OPERATION instructions */
__asm volatile(" nop      \n\t"
" nop      \n\t"
" nop      \n\t");
/* Check if clock cycle counter has started */
return(DWT->CYCCNT)?0:1;
}
void dwt_access(bool ena)
{
#if (__CORTEX_M == 0x07U)
/
*
* Define DWT LSR mask which is (currentuly) not defined by the CMSIS.  * Same as ITM LSR one.
*/
#if !defined DWT_LSR_Present_Msk
#define DWT_LSR_Present_Msk ITM_LSR_Present_Msk
#endif
#if !defined DWT_LSR_Access_Msk
#define DWT_LSR_Access_Msk ITM_LSR_Access_Msk
#endif
uint32_t lsr = DWT->LSR;
uint32_t lsr = DWT->LSR;
if((lsr & DWT_LSR_Present_Msk)!=0){
if(ena){
if((lsr & DWT_LSR_Access_Msk)!=0){//locked
DWT->LAR =0xC5ACCE55;
}
}else{
if((lsr & DWT_LSR_Access_Msk)==0){//unlocked
DWT->LAR =0;
}
}
}
#else/* __CORTEX_M */
UNUSED(ena);
#endif/* __CORTEX_M */
}
#ifdef __cplusplus
}
#endif
#endif
delayMicroseconds()函数
void delayMicroseconds(uint32_t us)
{
#if defined(DWT_BASE) && !defined(DWT_DELAY_DISABLED)
int32_t start  =dwt_getCycles();
int32_t cycles = us *(SystemCoreClock /1000000);
while((int32_t)dwt_getCycles()- start < cycles);
#endif
}
Note:
在使⽤DWT实现的延时函数时,程序下载到单⽚机中不能直接运⾏,需要按⼀下复位键才能正常运⾏(使⽤keil-MDK环境,ST-Link下载)。
结论
对⽐上⾯两种⽅式的延时效果:DWT实现的延时精度更⾼,SysTick的使⽤更加简单,⼤家可针对⾃⼰的需求选择。

本文发布于:2024-09-21 14:39:31,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/229178.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:延时   实现   函数   复位
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议