【STM32】通过 DWT 实现毫秒级延时

目录

  • 零、前言
  • 一、DWT
    • 1、DEMCR
    • 2、DWT_CTRL
    • 3、DWT_CYCCNT
  • 二、实现代码
  • 三、测试


零、前言

在 FreeRTOS 中,SysTick 被用于作为调度器的一部分进行任务调度,那么如果我需要使用软件模拟通信,例如软件 I2C,需要使用 delay,就无法使用 SysTick 实现的 delay。

因此,这里提供一种基于 DWT 实现的 delay。

一、DWT

在实现我们的代码之前,如果你没有了解过 DWT,那就先来看一下:

这里只介绍待会儿会用到的延时相关的内容



在 Cortex-M 内核内核中里面有一个外设叫 DWT(Data Watchpoint and Trace),是用于系统调试及跟踪。

它有一个 32 位的寄存器叫 CYCCNT,它是一个向上的计数器,记录的是内核时钟运行的个数,内核时钟跳动一次,该计数器就加 1。

它的精度非常高,取决于内核的频率是多少,如果是 F103 系列,内核时钟是 72M,那精度就是 1 / 72 M = 14 n s 1/72M = 14ns 1/72M=14ns,而程序的运行时间都是微秒级别的,所以 14ns 的精度是远远够的。最长能记录的时间为: 60 s = 2 32 / 72000000 60s = 2^{32}/72000000 60s=232/72000000 (假设内核频率为72M,内核跳一次的时间大概为 1 / 72 M = 14 n s 1/72M=14ns 1/72M=14ns),而如果是 H7 这种 400M 主频的芯片,那它的计时精度高达 2.5ns( 1 / 400000000 = 2.5 1/400000000 = 2.5 1/400000000=2.5)。

CYCCNT 溢出之后,会清 0 重新开始向上计数。

要实现延时的功能,总共涉及到三个寄存器:DEMCRDWT_CTRLDWT_CYCCNT,分别用于开启 DWT 功能、开启 CYCCNT 及获得系统时钟计数值。下面就来看一下这几个寄存器吧。

1、DEMCR

参照权威指南:

配置的时候,将 TRCENA 设置为 1 就行了。

2、DWT_CTRL


CYCCNTENA 使能位置 1 即可。

3、DWT_CYCCNT


使用 DWT_CYCCNT 寄存器之前,先清 0。

综上所述,要使用 DWT 的 CYCCNT 配置步骤如下:

  1. 使能 DWT 外设,这个由内核调试寄存器 DEMCR 的位 24 TRCENA 控制,写 1 使能
  2. 使能 CYCCNT 寄存器之前,先清 0。
  3. 使能 CYCCNT 寄存器,这个由 DWT 控制寄存器的 CYCCNTENA 位控制,也就是 DWT 控制寄存器的位 0 控制,写 1 使能

二、实现代码

#define  DWT_CYCCNT  *(volatile unsigned int *)0xE0001004
#define  DWT_CR      *(volatile unsigned int *)0xE0001000
#define  DEM_CR      *(volatile unsigned int *)0xE000EDFC#define  DEM_CR_TRCENA               (1 << 24)
#define  DWT_CR_CYCCNTENA            (1 <<  0)/******************************************************************************* @brief  初始化 DWT* @return none
******************************************************************************/
void bsp_dwt_init(void)
{DEM_CR         |= (unsigned int)DEM_CR_TRCENA;   /* Enable Cortex-M4's DWT CYCCNT reg.  */DWT_CYCCNT      = (unsigned int)0u;DWT_CR         |= (unsigned int)DWT_CR_CYCCNTENA;
}/******************************************************************************* @brief      * @param[in]  _delay_time    :    延时时间  * @return     none
******************************************************************************/
void bsp_dwt_delay(uint32_t _delay_time)
{uint32_t cnt, delay_cnt;uint32_t start;cnt = 0;delay_cnt = _delay_time;  /* 需要的节拍数 */ 		      start = DWT_CYCCNT;       /* 刚进入时的计数器值 */while(cnt < delay_cnt){cnt = DWT_CYCCNT - start; /* 求减过程中,如果发生第一次32位计数器重新计数,依然可以正确计算 */	}
}/******************************************************************************* @brief      这里的延时采用CPU的内部计数实现,32位计数器*             OSSchedLock(&err);*			   bsp_DelayUS(5);*			   OSSchedUnlock(&err); 根据实际情况看看是否需要加调度锁或选择关中断* @param[in]  _delay_time    :    延迟长度,单位1 us* @return     none* @note       1. 主频168MHz的情况下,32位计数器计满是2^32/168000000 = 25.565秒*                建议使用本函数做延迟的话,延迟在1秒以下。  *             2. 实际通过逻辑分析仪测试,微妙延迟函数比实际设置实际多运行0.25us左右的时间。*             3. 测试硬件:STM32F407VET6
******************************************************************************/
void bsp_delay_us(uint32_t _delay_time)
{uint32_t cnt, delay_cnt;uint32_t start;start = DWT_CYCCNT;                                     /* 刚进入时的计数器值 */cnt = 0;delay_cnt = _delay_time * (SystemCoreClock / 1000000);	 /* 需要的节拍数 */ 		      while(cnt < delay_cnt){cnt = DWT_CYCCNT - start; /* 求减过程中,如果发生第一次32位计数器重新计数,依然可以正确计算 */	}
}/******************************************************************************* @brief      为了让底层驱动在带RTOS和裸机情况下有更好的兼容性*             专门制作一个阻塞式的延迟函数,在底层驱动中ms毫秒延迟主要用于初始化,并不会影响实时性。 * @param[in]  _delay_time    :    延迟长度,单位1 ms* @return     none
******************************************************************************/
void bsp_delay_ms(uint32_t _delay_time)
{bsp_delay_us(1000 * _delay_time);
}

三、测试

下面通过一个简单的 demo 测试一下 us 级的延时函数,通过翻转 PC0 的电平状态,再通过逻辑分析仪查看延时效果:

int main(void)
{/******* 系统及外设初始化函数*****/bsp_dwt_init();/* 使用PC0测试时间 */{GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;	/* 输出类型为推挽 */GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	/* 内部上拉电阻使能 */GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;	/* 复用模式 */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);		}while (1){GPIOC->BSRR = (uint32_t)GPIO_Pin_0;bsp_delay_us(1);GPIOC->BSRR = (uint32_t)GPIO_Pin_0 << 16;bsp_delay_us(1);}return 0;
}

bsp_delay_us(10)

由于本人使用的逻辑分析仪精度较低,只能看个大概数据,大致要比实际设置的时间多运行 0.25 us

bsp_delay_us(1)

注意事项

在烧录运行程序的时候,由于下载器的问题,早期用的 D 版 JLINK,不能正常复位 DWT。所以 DWT 时钟计数器容易出现不运行的情况,而调试状态或者重新上电都不存在问题,使用的时候要注意。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/462236.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在Linux系统中使用Ansible进行自动化部署

如何在Linux系统中使用Ansible进行自动化部署 Ansible简介 安装Ansible 在Debian/Ubuntu系统中安装 在CentOS/RHEL系统中安装 启动Ansible服务 Ansible基本概念 Inventory Playbook Module 配置Ansible 测试Ansible配置 执行Ansible Playbook Ansible模块 文件模块 包管理模块…

「Mac畅玩鸿蒙与硬件20」鸿蒙UI组件篇10 - Canvas 组件自定义绘图

Canvas 组件在鸿蒙应用中用于绘制自定义图形,提供丰富的绘制功能和灵活的定制能力。通过 Canvas,可以创建矩形、圆形、路径、文本等基础图形,为鸿蒙应用增添个性化的视觉效果。本篇将介绍 Canvas 组件的基础操作,涵盖绘制矩形、圆形、路径和文本的实例。 关键词 Canvas 组件…

从零开始构建 ChatGPT

今天&#xff0c;我们要介绍的是一个名为 LLMs-from-scratch 的 GitHub 项目&#xff0c;它由开发者 rasbt 精心打造&#xff0c;旨在一步步教你如何使用 PyTorch 从零开始实现一个类似 ChatGPT 的大型语言模型&#xff08;LLM&#xff09;。 这是一个教育性质的开源项目&…

【Git】Git常用命令

目录 1 前言2 git命令2.1 branch2.2 checkout2.3 pull and push2.4 config2.4.1 Proxy 2.5 tag2.6 rebase2.7 patch2.8 remote2.9 submodule2.10 rm2.10 gitignore2.11 某个commit更改了哪些文件2.12 clean 3 结束语 1 前言 本章记录总结在使用git过程中常用的一些命令&#x…

redis分布式锁在项目中的应用总结

项目应用 应用1 redis分布式锁实现两个操作的原子性 需求&#xff1a;实现一人一单业务逻辑时&#xff08;如果能走到这个逻辑&#xff0c;代表库存是充足的&#xff09;&#xff0c;我们需要 先查询订单 如果订单不存在即没有买过则创建订单 这两个步骤我们要保证是原子…

前端 react 面试题(二)

文章目录 hooks的使用规则为什么hooks要确保在函数组件的最顶层,而不能放置在循环或者条件语句中。react的事件模型react的合成事件是如何实现的react事件传参,可以使用箭头函数或bind方法,这两种哪一种更好使用箭头函数:使用`bind`方法:react的事件模型和vue的区别React …

1分钟解决Excel打开CSV文件出现乱码问题

一、编码问题 1、不同编码格式 CSV 文件有多种编码格式&#xff0c;如 UTF - 8、UTF - 16、ANSI 等。如果 CSV 文件是 UTF - 8 编码&#xff0c;而 Excel 默认使用的是 ANSI 编码打开&#xff0c;就可能出现乱码。例如&#xff0c;许多从网络应用程序或非 Windows 系统生成的 …

【python】OpenCV—Tracking(10.4)—Centroid

文章目录 1、任务描述2、人脸检测模型3、完整代码4、结果展示5、涉及到的库函数6、参考 1、任务描述 基于质心实现多目标&#xff08;以人脸为例&#xff09;跟踪 人脸检测采用深度学习的方法 核心步骤&#xff1a; 步骤#1&#xff1a;接受边界框坐标并计算质心 步骤#2&…

GraphQL系列 - 第2讲 Spring集成GraphQL

目录 一、maven依赖二、Schema 定义三、代码集成3.1 创建模型类3.2 创建服务类3.3 创建控制器类 四、单元测试五、实际 HTTP 请求测试5.1 查询单个 Person5.2 查询所有 People5.3 添加 Person 六、其他6.1 开启graphiql6.2 开启schema查看端点 一、maven依赖 首先&#xff0c;…

Golang | Leetcode Golang题解之第526题优美的排列

题目&#xff1a; 题解&#xff1a; func countArrangement(n int) int {f : make([]int, 1<<n)f[0] 1for mask : 1; mask < 1<<n; mask {num : bits.OnesCount(uint(mask))for i : 0; i < n; i {if mask>>i&1 > 0 && (num%(i1) 0 |…

模拟栈的实现

栈的概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈 顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出 LIFO &#xff08; Last In First Out &#xff09;的原则。 压栈&…

Win10搭建SFTP服务器

1、下载安装 Release v9.5.0.0p1-Beta PowerShell/Win32-OpenSSH GitHub 下载OpenSSH-Win64.zip 解压之后放入到&#xff1a;C:\Program Files (x86)\OpenSSH-Win64以管理员身份打开CMD进入到 C:\Program Files (x86)\OpenSSH-Win64 文件夹执行命令 powershell.exe -Exec…

WordPress网站添加嵌入B站视频,自适应屏幕大小,取消自动播放

结合bv号 改成以下嵌入式代码&#xff08;自适应屏幕大小,取消自动播放&#xff09; <iframe style"width: 100%; aspect-ratio: 16/9;" src"//player.bilibili.com/player.html?isOutsidetrue&bvidBV13CSVYREpr&p1&autoplay0" scrolling…

C语言内幕--全局变量(结合内存分区、汇编视角看类型、连接器)

前言 学习资源&#xff1a;b站up主&#xff1a;底层技术栈学过C语言都知道&#xff0c;全局变量可以再全局中使用&#xff0c;其实全局变量内部还是涉及到不少知识&#xff0c;这里从内存分区、汇编视角看类型、连接器等角度看待全局变量&#xff1b;由于涉及到底层技术&#…

省级-建成区绿化覆盖率数据(2006-2022年)

建成区绿化覆盖率是指城市建成区的绿化覆盖面积占建成区的百分比。 城市绿化覆盖率的提升&#xff0c;不仅能够改善城市的空气质量&#xff0c;降低噪音污染&#xff0c;还能提高城市的生物多样性&#xff0c;为市民提供更多的休闲和娱乐空间。 2006年-2022年省级-建成区绿化…

基于CNN-BiLSTM的时间序列数据预测,15个输入1个输出,可以更改数据集,MATLAB代码

1. 数据收集与预处理 数据清洗&#xff1a;处理缺失值、异常值等。特征工程&#xff1a;提取有助于预测的特征。数据标准化&#xff1a;将时间序列数据标准化&#xff0c;使其具有零均值和单位方差&#xff0c;有助于模型训练。滑动窗口划分&#xff1a;将时间序列数据划分为多…

SSM学习 day02

一、vue项目开发流程 vue根组件 <template><div><h1>{{ message }}</h1><element-view></element-view></div> </template><script> import ElementView from ./views/Element/ElementView.vue export default {compon…

【NOIP普及组】 FBI树

【NOIP普及组】 FBI树 C语言版本C 版本Java版本Python版本 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 我们可以把由“0”和“1”组成的字符串分为三类&#xff1a;全“0”串称为B串&#xff0c;全“1”串称为I串&#xff0c;既含“0”又…

大数据新视界 -- 大数据大厂之数据质量管理全景洞察:从荆棘挑战到辉煌策略与前沿曙光

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

基于 webpack 项目接入 vite 你可能需要注意的点

前言 在之前的 如何优化你的 vue-cli 项目&#xff1f; 一文中介绍基于 webpack 进行的一些优化方法&#xff0c;本文的核心是基于一个 vue2 的项目&#xff08;也就是上篇文章中的项目&#xff09;来继续介绍一下如何接入 vite&#xff0c;以及这个过程中需要关注的点。 之前…