文章目录

  • STM32 HAL库微秒延时函数的实现
    • 利用SysTick再实现微秒延时函数
    • 利用DWT(数据观测点)实现微秒延时函数
      • `dwt.h`文件
      • `dwt.c`文件
      • `delayMicroseconds()`函数
    • 结论

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

虽然函数参数usuint32_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:*                        opensource.org/licenses/BSD-3-Clause********************************************************************************//* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _DWT_H_
#define _DWT_H_#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:*                        opensource.org/licenses/BSD-3-Clause********************************************************************************/#include "dwt.h"#ifdef DWT_BASE
#ifdef __cplusplus
extern "C" {#endifuint32_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
#endifuint32_t lsr = DWT->LSR;if ((lsr & DWT_LSR_Present_Msk) != 0) {if (ena) {if ((lsr & DWT_LSR_Access_Msk) != 0) { //lockedDWT->LAR = 0xC5ACCE55;}} else {if ((lsr & DWT_LSR_Access_Msk) == 0) { //unlockedDWT->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的使用更加简单,大家可针对自己的需求选择。

STM32HAL库微秒延时函数的实现---DWT和SysTick相关推荐

  1. STM32HAL库微秒延时(μs)

    STM32HAL库微秒延时(μs) 单片机:STM32F407ZET6 软件版本:STM32CubeMX 4.20.1 单片机固件包:STM32Cube FW_F4 V1.15.0 本代码是我于201 ...

  2. stm32延时us寄存器_自己写一个STM32 HAL库的US微秒延时函数

    当本菜鸟开始接触STM32的时候还是看了原子哥的寄存器教程才跳坑的. 现在ST已经把HAL库推向了主流,但是令我不解的是,HAL那么强大,居然没有一个微秒级别的延时函数?! 黑人问号脸. 好了,废话不 ...

  3. stm32cubemx中文_用 STM32 通用定时器做微秒延时函数(STM32CubeMX版本)

    概述 ​ 在使用 DHT11 的时候,时序通信需要微秒来操作,STM32CubeMX 自带一个系统时钟,但是实现的是毫秒级别的.因此就自己用通用计时器实现一个. 文章目录 环境: 开发板:STM32F ...

  4. 从头开始写STM32F103C8T6驱动库(四)——编写延时函数,详解Systick

    系列文章目录 Github开源地址 从头开始写STM32F103C8T6驱动库(一)--STM32CubeMX创建并调整工程结构 从头开始写STM32F103C8T6驱动库(二)--编写系统初始化程序 ...

  5. STM32HAL库RS485-ModBus协议控制伺服电机

    STM32HAL库RS485-ModBus协议控制伺服电机 一个月前,接手了一个学长的毕设小车,小车采用rs485通信的modbus协议驱动轮毂电机,与往常我学习的pwm控制电机方法大相径庭,在这里以 ...

  6. STM32CubeMx开发之路—使用SysTick实现微妙延时函数delay_us()

    运行环境 Windows10 STM32CubeMX Version 5.4.0 Keil5(MDK5) Version 5.28.0.0 硬件开发板 F103RB-NUCLEO 简介 本例程主要讲解 ...

  7. STC12C5A60S2自主适应时钟延时函数

    快速导航 STC12已封装好的函数库 单片机延时函数的原理: 延时函数里执行的是空语句,单片机程序指针经过执行的空语句来达到延时的目的. 单片机使用延时函数的优点就是很容易就能写出软件延时程序. 但是 ...

  8. STM32单片机初学者编程之常用小程序--GPIO配置延时函数

    声明:本专题系列的博文主要是用于个人学习以及后续查阅调用,由于是这方面的初学者,所以写的比较浅陋,有喜欢的朋友可以一起学习,编程大神们请略过...... 1.以一个GPIO的初始化程序为例,以下是GP ...

  9. 延时函数delay_us

    /* void delay_us(uint32_t udelay) 定义:微秒延时函数 参数: //udelay--输入--微秒 */ void delay_us(uint32_t udelay) { ...

  10. C/C++ 延时函数 (标准库)

    曾经有一次需要只使用标准库在C语言程序里做延时功能,但是百度和google了很久都没有能得到解答.后来一个偶然的机会在某本书上看到了一个C语言的延时函数,现在把它修改一下贡献给大家. /* 函数类型: ...

最新文章

  1. 数组、字符串对象、Math对象
  2. 离不开的“微服务”架构,脱不开的RPC细节(收藏)
  3. 网站SEO文章关键词布局优化的技巧指南
  4. 很多人调用接口会阻塞吗_锻炼的真相你知道吗?这些你可能都想了解,很多人都会问的2点...
  5. SQL2005利用ROW_NUMER实现分页的两种常用方式
  6. matlab局部放大的图中图画法
  7. C/C++ 如何劫持别人家的命令||函数||程序(只能对于window而言)
  8. 继承演练 动物 狗 哮天犬 c# 1613703354
  9. 消息人士:苹果正与比亚迪宁德时代洽谈电动汽车电池供应事宜
  10. 高图壁纸网站,承包了你一年的电脑壁纸
  11. 一文详解ERP的提取原理
  12. 解决:WPS for Linux提示“系统缺失字体symbol、wingdings、wingdings 2、wingdings 3、webding”...
  13. 说说那些好用的图片调色软件
  14. jieba分词原理 ‖ 关键词抽取
  15. 邮政挂号信和包裹查询网站(非EMS)
  16. JS + shell 批量下载 喜马拉雅FM 的音频
  17. 数值最优化-KKT条件(一阶必要条件)证明总结
  18. OrangePi3开发板使用指南
  19. html网页添加背景音乐
  20. C语言讲义——错误处理

热门文章

  1. ecshop 模板设置详解
  2. html如何在搜索栏里加放大镜,css 如何在html页面上输出一个“放大镜”形状呢?...
  3. 遥感影像地图编制流程
  4. ubuntu GStreamer + QT多媒体播放器开发(二)
  5. linux光盘映像文件挂载,linux系统挂载光盘镜像ISO的方法
  6. Maven的学习与2022IDEA创建Maven的web项目的教程(这个比上一期更“啰嗦哦~,前面不想删了,整体再来一遍”)
  7. win32gui操作
  8. ​机器如何“猜你喜欢”?深度学习模型在1688的应用实践
  9. uniapp,从文件流获取图片地址,并展示图片
  10. 【ITool】excel导入导出工具