[其他ST产品] STM32CUBE——使用DWT提供毫秒延迟

[复制链接]
2204|52
 楼主| 王派oo 发表于 2022-8-31 17:23 | 显示全部楼层 |阅读模式
起因
由于使用了CUBE,原子哥的延时就用不了,所以尝试其他延时函数:CUBE的HAL_Delay()和使用STM32的DWT(Data watchpoint trigger)

前言
为什么要学习这种延时的方法?

HAL_Delay实用程序函数:它建立在SysTick计时器上,当我们跑操作系统,就一般会占用一个硬件定时器——SysTick(也可以把其他定时器当成时钟),这样一来又难免产生冲突。
以便为在阻塞和非阻塞模式下工作的驱动程序提供两个版本。阻塞函数将使用我们今天将要开发的延迟实用程序(DWT)。非阻塞功能将由 SysTick 计时器处理

评论

———————————————— 版权声明:本文为CSDN博主「煤炭的奇妙漂流」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/m0_46152804/article/details/123598771  发表于 2022-8-31 17:25
 楼主| 王派oo 发表于 2022-8-31 17:30 | 显示全部楼层
系统图
41860630f2a3369903.png
 楼主| 王派oo 发表于 2022-8-31 17:31 | 显示全部楼层
DWT_Initialization() 函数
要实现延时的功能,总共涉及到三个寄存器:DEMCR 、DWT_CTRL、DWT_CYCCNT,分别用于开启DWT功能、开启CYCCNT及获得系统时钟计数值。
17888630f2a47a838c.png
 楼主| 王派oo 发表于 2022-8-31 17:32 | 显示全部楼层
  1. uint32_t DWT_Delay_Init(void)
  2. {
  3.     /* 禁用 TRC */
  4.     CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; // ~0x01000000;
  5.     /* 启动 TRC */
  6.     CoreDebug->DEMCR |=  CoreDebug_DEMCR_TRCENA_Msk; // 0x01000000;

  7.     /* Disable clock cycle counter */
  8.     DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001;
  9.     /* 启动  时钟周期计数器 */
  10.     DWT->CTRL |=  DWT_CTRL_CYCCNTENA_Msk; //0x00000001;

  11.     /* 重置时钟周期计数器值 */
  12.     DWT->CYCCNT = 0;

  13.     /* 3 NO OPERATION instructions 3空 */
  14.    
  15.     __ASM volatile ("NOP");
  16.     __ASM volatile ("NOP");
  17.     __ASM volatile ("NOP");

  18.     /* 检查时钟周期计数器是否已启动*/
  19.     if(DWT->CYCCNT)
  20.     {
  21.        return 0; /*clock cycle counter started*/
  22.     }
  23.     else
  24.     {
  25.       return 1; /*clock cycle counter not started*/
  26.     }
  27. }
 楼主| 王派oo 发表于 2022-8-31 17:36 | 显示全部楼层
DEMCR寄存器
DEMCR寄存器为使能寄存器
    /* Disable TRC */
    CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; // ~0x01000000;
    /* Enable TRC */
    CoreDebug->DEMCR |=  CoreDebug_DEMCR_TRCENA_Msk; // 0x01000000;
 楼主| 王派oo 发表于 2022-8-31 17:38 | 显示全部楼层
24位置1对应0x01000000;
99998630f2c0b28398.png
 楼主| 王派oo 发表于 2022-8-31 17:39 | 显示全部楼层
DWT_CTRL寄存器
DWT_CTRL寄存器是时钟周期计数器
  1. /* Disable clock cycle counter */
  2.     DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001;
  3.     /* 启动  时钟周期计数器 */
  4.     DWT->CTRL |=  DWT_CTRL_CYCCNTENA_Msk; //0x00000001;
  5.    
 楼主| 王派oo 发表于 2022-8-31 17:42 | 显示全部楼层
第一位置"1"对应0x00000001
32766630f2cf4ba7f1.png
 楼主| 王派oo 发表于 2022-8-31 17:43 | 显示全部楼层
DWT_CYCCNT寄存器
  1.     /* 重置时钟周期计数器值 */
  2.     DWT->CYCCNT = 0;
 楼主| 王派oo 发表于 2022-8-31 17:45 | 显示全部楼层
它是一个向上的计数器,记录的是内核时钟运行的个数,内核时钟跳动一次,该计数器就加1,精度非常高,决定内核的频率是多少,如果是F103系列,内核时钟是72M,那精度就是1/72M = 14ns
 楼主| 王派oo 发表于 2022-8-31 17:46 | 显示全部楼层
DWT_Delay_us() 函数
此函数使用DWT提供以微秒计的延迟

  1. // 该函数使用DWT提供毫秒延迟
  2. __STATIC_INLINE void DWT_Delay_ms(volatile uint32_t au32_milliseconds)
  3. {
  4.   uint32_t au32_initial_ticks = DWT->CYCCNT;
  5.   uint32_t au32_ticks = (HAL_RCC_GetHCLKFreq() / 1000);
  6.   au32_milliseconds *= au32_ticks;
  7.   while ((DWT->CYCCNT - au32_initial_ticks) < au32_milliseconds);
  8. }
 楼主| 王派oo 发表于 2022-8-31 17:47 | 显示全部楼层
演示
以下是本实验的应用程序代码
  1. #include "main.h"
  2. #include "../util/Timer_Delay.h"
  3. #include "../util/DWT_Delay.h"

  4. void SystemClock_Config(void);
  5. static void MX_GPIO_Init(void);

  6. int main(void)
  7. {
  8.     HAL_Init();
  9.     SystemClock_Config();
  10.     MX_GPIO_Init();
  11.     /* Initialize The TimerDelay*/
  12.     TimerDelay_Init();

  13.     while (1)
  14.     {
  15.         HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
  16.         delay_ms(100);
  17.     }
  18. }
 楼主| 王派oo 发表于 2022-8-31 17:49 | 显示全部楼层
演示
以下是本实验的应用程序代码
  1. #include "main.h"
  2. #include "../util/Timer_Delay.h"
  3. #include "../util/DWT_Delay.h"

  4. void SystemClock_Config(void);
  5. static void MX_GPIO_Init(void);

  6. int main(void)
  7. {
  8.     HAL_Init();
  9.     SystemClock_Config();
  10.     MX_GPIO_Init();
  11.     /* Initialize The TimerDelay*/
  12.     TimerDelay_Init();

  13.     while (1)
  14.     {
  15.         HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
  16.         delay_ms(100);
  17.     }
  18. }
 楼主| 王派oo 发表于 2022-8-31 17:51 | 显示全部楼层
 楼主| 王派oo 发表于 2022-8-31 17:52 | 显示全部楼层
总结一下:

a.先使能DWT外设,由内核调试寄存器DEM_CR的位24控制,写1使能。

b.使能CYCCNT寄存器,由DWT_CTRL的位0控制,写1使能。

c.使能CYCCNT寄存器之前,先清0。
chenci2013 发表于 2022-9-5 12:34 | 显示全部楼层
systick就行的
minzisc 发表于 2022-9-5 17:05 | 显示全部楼层
能够做us的延时吗
koala889 发表于 2022-9-5 20:14 | 显示全部楼层
要求精确么
updownq 发表于 2022-9-7 16:47 | 显示全部楼层
STM32CUBE开发程序简单多了
maqianqu 发表于 2022-9-7 19:25 | 显示全部楼层
定时器直接实现延时不好吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

308

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部