> 技术文档 > STM32使用Systick实现微秒(us)级延时_stm32 us延迟

STM32使用Systick实现微秒(us)级延时_stm32 us延迟


1、代码:(引用自立创开发板)

下列代码直接CV进自己的板子,.h文件改个#include \"stm32f4xx.h\"

然后把 SYSCLK 改为时钟树配的系统主频

SYS.c函数:

#include \"sys.h\"#define SYSCLK 168000000/** - @brief 用内核的 systick 实现的微妙延时 - @note None - @param _us:要延时的us数 - @retval None*/void delay_us(uint32_t _us){ uint32_t ticks; uint32_t told, tnow, tcnt = 0; // 计算需要的时钟数 = 延迟微秒数 * 每微秒的时钟数 ticks = _us * (SYSCLK / 1000000); // 获取当前的SysTick值 told = SysTick->VAL; while (1) { // 重复刷新获取当前的SysTick值 tnow = SysTick->VAL; if (tnow != told) { if (tnow LOAD - tnow + told; told = tnow; // 如果达到了需要的时钟数,就退出循环 if (tcnt >= ticks) break; } }} /** - @brief 调用用内核的 systick 实现的毫秒延时 - @note None - @param _ms:要延时的ms数 - @retval None*/void delay_ms(uint32_t _ms) { delay_us(_ms * 1000); } void delay_1ms(uint32_t ms) { delay_us(ms * 1000); } void delay_1us(uint32_t us) { delay_us(us); }

SYS.h函数

#ifndef __SYS_H__#define __SYS_H__ #include \"stm32f4xx.h\" //0,不支持ucos//1,支持ucos#define SYSTEM_SUPPORT_OS0//定义系统文件夹是否支持UCOS/////定义一些常用的数据类型短关键字 typedef int32_t s32;typedef int16_t s16;typedef int8_t s8; typedef const int32_t sc32; typedef const int16_t sc16; typedef const int8_t sc8; typedef __IO int32_t vs32;typedef __IO int16_t vs16;typedef __IO int8_t vs8; typedef __I int32_t vsc32; typedef __I int16_t vsc16; typedef __I int8_t vsc8; typedef uint32_t u32;typedef uint16_t u16;typedef uint8_t u8; typedef const uint32_t uc32; typedef const uint16_t uc16; typedef const uint8_t uc8; typedef __IO uint32_t vu32;typedef __IO uint16_t vu16;typedef __IO uint8_t vu8; typedef __I uint32_t vuc32; typedef __I uint16_t vuc16; typedef __I uint8_t vuc8; void delay_us(uint32_t _us);void delay_ms(uint32_t _ms);void delay_1ms(uint32_t ms);void delay_1us(uint32_t us); #endif

2.原理:系统滴答定时器(SYSTick)

ARM_M4手册对SYSTick有关的寄存器的描述:

SysTick是属于Cortex-M4内核中的一个外设,内嵌在NVIC中

系统定时器是一个24位的向下递减的计数器,计数器每计数一次的时间为1/SYSCLK。

系统时钟SYSCLK的值=HAL库时钟树配置的值

由于系统滴答定时器属于Cotex-M4内核的外设,相关寄存器介绍不在《参考手册》,而在《编程手册》

图例1 编程手册上对寄存器的定义

系统滴答定时器只有四个控制寄存器:STK_CTRL,STK_LOAD,STK_VAL和STK_CALIB。

图例2 四个控制寄存器

寄存器 中文名 描述 CTRL SysTick控制和状态寄存器 [31:17]保留位、16溢出标志位、[15:3]、2时钟源、1异常、0使能 LOAD SysTick重载寄存器 [31:24]保留位、[23:0]为重装位 VAL SysTick当前值寄存器 [31:24]保留位、[23:0]为当前值 CALIB SysTick校准值寄存器 没用到就先不管,我补充在后边,想看就记点

[31:24]保留位就是没用的位

整理一下流程:(当做定时器)

  1. 时钟源不分频
  2. 自动重装载值设置为 [SYSCLK(主频) / 1000 000] * n        这样出来的就是n us的值
  3. 在while(1)循环计算是否已经达到需要的时钟数、
  4. 到这里我们就有了us延时,封装一下就可以有毫秒和秒的延时。

       如下图

3.分析HAL库的HAL_Delay()函数

如果wait小于HAL_MAX_DELAY,则在wait上加上uwTickFreq的值,确保延时时间的准确性。

而HAL_MAX_DELAY = 0xFFFFFFFF

只要你的HAL_Delay延时时间不是超过2^32  = 4294967296ms,都会加上这个时间补偿,

既wait = wait + 1

AI对等待时间+1 的解释:

4.补充(寄存器)

4.1 STK_CTRL SysTick控制和状态寄存器

4.2 STK_LOAD SysTick重载寄存器

4.3 STK_VAL SysTick当前值寄存器

4.4 STK_CTRL SysTick校准值寄存器

5.参考资料:

【经验分享】STM32 基础重点—SysTick定时器 - STM32团队 ST意法半导体中文论坛

:16