STM32学习笔记--Systick定时器+delay延时函数

基于正点原子mini开发板、STM32RCT6、库函数

一、Systick定时器介绍

  ARM Cortex-M3 内核的处理器内部包含了一个简单的SysTick 定时器,它是一个24 位的倒计数定时器。
  SysTick:系统定时器,24位到计数定时器,只能递减,存在于内核,嵌套在NVIC(中断向量控制器)中,所有的Cortex-M内核的单片机都具有这个定时器。
⚫ 当计到 0 时它就会从RELOAD 寄存器中自动重装载定时初值。只要不把CTRL 寄存器中的 ENABLE 为清 0,它就永不停息,即使在睡眠模式下也能工作。
⚫ SysTick定时器能产生中断
⚫ Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个复杂的定时器去实现简单的功能,比如在UCOS中,分时复用,需要一个最小的时间戳,一般在STM32+UCOS系统中,都采用Systick做UCOS的心跳时钟。

二、Systick相关寄存器

  4个Systick寄存器:

CTRL SysTick 控制和状态寄存器

LOAD SysTick 自动重装载除值寄存器

VAL SysTick 当前值寄存器

CALIB SysTick 校准值寄存器

1.SysTick 控制和状态寄存器- CTRL
在这里插入图片描述
  对于STM32,外部时钟源是HCLK(AHB总线时钟)的1/8;内核时钟是HCLK时钟。配置函数:

SysTick_CLKSourceConfig();

2.SysTick 重装载数值寄存器- LOAD
在这里插入图片描述
3.SysTick 当前值寄存器- VAL
在这里插入图片描述

三、Systick相关库函数

1.SysTick_Config(uint32_t ticks)

SysTick_Config(uint32_t ticks) //初始化systick,时钟为HCLK,并开启中断
                               //core_cm3.h文件中

 主要的作用:
1)、初始化systick
2)、打开systick
3)、打开systick的中断并设置优先级
4)、返回一个0代表成功或1代表失败

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
   
    
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS)
<think>嗯,用户想找关于STM32延时函数的资料和实现方法。好的,我需要先回忆一下STM32延时函数有哪些常见的方法。记得之前学过几种不同的实现方式,比如简单的循环延时、使用SysTick定时器,还有用其他定时器外设。首先,用户可能需要了解这些方法的基本原理和各自的优缺点。 首先,最简单的延时应该是循环延时,也就是通过执行空循环来消耗时间。这种方法不需要外设,但精度不高,而且受主频影响大。比如在51单片机里常用,STM32也可以用,但需要注意主频变化时的调整。可能需要示例代码,比如用for循环嵌套的那种。 然后是SysTick定时器,这是Cortex-M内核自带的,通常用来提供系统时钟节拍,比如给操作系统用。使用SysTick可以实现更精确的延时,比如HAL库中的HAL_Delay函数就是基于这个的。用户可能需要知道如何配置SysTick,以及如何自己编写延时函数,比如初始化SysTick,设置重装载值,然后等待计数器到零。 另外,还可以用其他定时器外设,比如TIM1、TIM2等,通过配置定时器的预分频和重装载值来生成精确的延时。这种方法灵活性高,适合需要高精度或复杂定时的场景。可能需要提到如何配置定时器,启动计数器,并等待更新事件或中断。 用户可能还关心如何选择适合自己项目的方法,比如如果只是简单应用,循环延时可能足够;如果需要高精度或者多任务,SysTick定时器更好。还要注意在中断中使用延时的问题,比如HAL_Delay在中断中使用可能导致问题,这时候可能需要其他方法。 还要考虑参考资料,比如ST的官方文档、HAL库的用户手册,以及相关的学习笔记或社区文章。比如引用中的内容提到SysTick_Config函数和示例代码,可能需要指出这些参考来源。 用户的问题可能还涉及具体的代码示例,比如如何用循环实现微秒级延时,如何用SysTick实现毫秒级延时,以及如何用TIM2实现更灵活的延时。需要确保代码示例正确,并符合STM32的编程规范,比如使用HAL库或者直接寄存器操作。 可能还需要提到注意事项,比如主频变化时的调整,中断对延时的影响,以及不同型号STM32的差异。比如如果使用HAL库,主频改变后HAL_Delay会自动调整,但自己写的延时函数可能需要手动更新参数。 最后,生成的相关问题应该覆盖用户可能进一步想了解的内容,比如如何提高延时精度、不同定时器的比较、在实时操作系统中的使用,以及如何验证延时是否正确。这些问题可以帮助用户深入理解并解决实际开发中的问题。</think>### STM32延时函数实现方法详解 #### 一、循环延时(基础方法) 通过空循环消耗时间实现,适用于简单场景。 **示例代码(微秒级延时)**: ```c #define DELAY_LOOP_CYCLES 6 // 根据主频调整的循环周期数 void delay_us(uint32_t us) { for(uint32_t i=0; i<us; i++){ volatile uint32_t count = DELAY_LOOP_CYCLES; while(count--); } } ``` *特点*:无需外设,精度受主频影响较大,需通过示波器校准[^3]。 #### 二、SysTick定时器(推荐方法) 利用Cortex-M内核自带的24位系统定时器,精度更高。 **配置步骤**: 1. 初始化SysTick时钟源(通常选择HCLK) 2. 设置重装载值`ticks = (SystemCoreClock / 1000000) * us` 3. 启动定时器并等待计数完成 **示例代码(毫秒级延时)**: ```c void SysTick_Init(void) { SysTick->CTRL = 0; // 禁用SysTick SysTick->LOAD = (SystemCoreClock/1000) - 1; // 1ms中断 SysTick->VAL = 0; SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; } void delay_ms(uint32_t ms) { while(ms--) { SysTick->VAL = 0; while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); } } ``` *注意*:HAL库中`HAL_Delay()`即基于此实现[^2]。 #### 三、硬件定时器(高精度需求) 使用TIM2/TIM3等通用定时器,支持微秒级高精度延时。 **配置流程**: ```c // TIM2初始化(示例) void TIM2_Init(void) { RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; TIM2->PSC = SystemCoreClock/1000000 - 1; // 1MHz计数 TIM2->ARR = 0xFFFF; TIM2->CR1 |= TIM_CR1_CEN; } void delay_us(uint16_t us) { TIM2->CNT = 0; while(TIM2->CNT < us); } ``` *优势*:可达±0.5us精度,支持中断模式[^4]。 #### 四、参考文档建议 1. 《Cortex-M3权威指南》:SysTick工作原理详解 2. ST官方文档《RM0008 Reference Manual》:定时器配置章节 3. HAL库用户手册:`HAL_Delay()`源码分析[^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值