使用STM32_HAL库实现SysTick系统定时器计时

1介绍

系统定时器(SysTick)是ARM Cortex-M处理器系列中的一个特殊定时器,它不属于STM32F1系列微控制器的外设,而是处理器内部的一个组件。SysTick定时器的作用是为操作系统或其他需要精确时钟计数和中断服务的应用提供基础的时间参考。

关键特点:

  1. 24位计数器:SysTick计数器是一个24位的寄存器,可以计数的范围是从0到16777215(即2^24 – 1)。

  2. 可配置的时钟源:SysTick可以使用不同的时钟源,包括处理器的主时钟(Cortex-M3/M4/M7等处理器的主时钟)。时钟源的选择会影响SysTick的计数频率。

  3. 中断功能:SysTick可以产生中断请求,当计数器的值达到预设的值时。这个中断可以用来实现操作系统的时间间隔计时器或用于其他需要精确时间计数的应用。

  4. 触发DMA请求:SysTick还可以配置为在计数器达到预设值时触发DMA请求,这可以用于与DMA控制器协同工作,实现数据传输的定时控制。

  5. 初始化与配置:SysTick的配置和初始化通常在系统初始化时完成,通过设置SysTick控制和状态寄存器(SysTick_CSR)的值来配置时钟源、预分频器、中断使能等参数。

 用途

  • 操作系统时间基准:在嵌入式系统中,SysTick定时器可以作为操作系统的时钟基准,用于时间管理和任务调度。
  • 定时中断服务:在不需要精确时间控制的应用中,SysTick可以用于生成固定时间间隔的中断,用于定时服务或执行某些周期性任务。
  • DMA请求触发:在一些应用中,SysTick可以作为DMA控制器的外部触发源,用于控制数据传输的定时。
  •  配置SysTick定时器的步骤

    1. 使能SysTick时钟: 在系统时钟配置(SystemClock_Config)函数中,你需要使能SysTick时钟。这通常通过设置RCC时钟控制寄存器(RCC_APB2ENR)的SYSCKEN位来实现。

    2. 配置SysTick时钟源: SysTick可以使用多种时钟源,包括处理器的主时钟(HCLK)、系统时钟(SystemCoreClock)或者一个较低的时钟源。你需要在SysTick控制和状态寄存器(SysTick_CSR)中设置时钟源选择位(CLKSOURCE)。

    3. 设置SysTick分频器: 你可以通过设置SysTick分频器寄存器(SysTick_CLKSource)来配置SysTick时钟源的分频值。这会影响SysTick的计数频率。

    4. 配置SysTick计数器: 在SysTick计数器寄存器(SysTick_VAL)中,你需要设置计数器的初始值。这决定了SysTick定时器的周期。

    5. 配置中断和DMA请求(需要时在配置): 你可以通过设置SysTick控制和状态寄存器(SysTick_CSR)的位来使能中断请求(TICKINT)和DMA请求(DMAINT)。

    6. 初始化SysTick: 在系统初始化代码中,你需要调用SysTick_Config函数,并传递一个周期值,这个值决定了SysTick定时器的周期。

    7. 使用SysTick定时器: 一旦SysTick定时器配置完成,它将按照配置的周期产生中断请求。你可以在中断服务例程中处理SysTick定时器的中断请求。

    用于配置、初始化和操作SysTick定时器:

    1. HAL_SYSTICK_Config: 这个函数用于配置SysTick定时器的时钟源、分频器和重载值。它返回一个布尔值,指示配置是否成功。

    2. HAL_SYSTICK_CLKSourceConfig: 这个函数用于配置SysTick定时器的时钟源。它可以设置为HCLK(主时钟)或者HCLK的8分频。

    3. HAL_SYSTICK_CLKSourceSwitchCmd: 这个函数用于在不同的时钟源之间切换SysTick定时器的时钟源。

    4. HAL_SYSTICK_IRQHandler: 这个函数是SysTick定时器的中断服务例程。当SysTick定时器溢出时,它会自动调用这个函数。

    5. HAL_IncTick: 这个函数用于递增SysTick定时器的计数器。它通常在SysTick定时器的中断服务例程中调用,以提供精确的系统时钟。

    6. HAL_GetTick: 这个函数用于获取当前的SysTick定时器计数值。它返回的是自系统启动以来经过的SysTick定时器计数器的值。

    7. HAL_SYSTICK_GetCurrentState: 这个函数用于获取SysTick定时器当前的状态。

    8. HAL_SYSTICK_GetCounter: 这个函数用于获取SysTick定时器的当前计数值。

    9. HAL_SYSTICK_GetReloadValue: 这个函数用于获取SysTick定时器的自动重装载值。

    10. HAL_SYSTICK_SetReload 这个函数用于设置SysTick定时器的自动重装载值。

    11. HAL_SYSTICK_Cmd: 这个函数用于启用或禁用SysTick定时器。

    注意 

    重写SysTick配置会影响HAL_Delay()函数。HAL_Delay()函数依赖于SysTick定时器的配置来提供延迟功能。如果你重写了SysTick的配置,你将改变SysTick定时器的操作方式,这可能会导致HAL_Delay()函数的行为与预期不符。

    在STM32HAL库中,HAL_Delay()函数内部使用了SysTick定时器来计算延迟时间。当HAL_Delay()函数被调用时,它会设置SysTick定时器的自动重装载值,以实现指定的延迟时间。SysTick定时器的配置决定了延迟的精度和分辨率。

    如果你重写了SysTick的配置,你可能会改变SysTick定时器的时钟源、分频器、自动重装载值等参数。这可能会导致HAL_Delay()函数无法正确计算延迟时间,或者在延迟时间到达时无法正确清除中断标志。

    因此,如果你重写了SysTick的配置,你应该确保你的配置与HAL_Delay()函数的期望行为兼容。如果可能的话,最好不要重写SysTick的配置,除非你有充分的理由和充分的测试来确保你的配置不会破坏HAL_Delay()函数的性能和准确性。

     Systick的频率与时间之间的转换公式

     SysTick定时器的时钟源分频器通常在初始化时被设置为固定值,因此在实际应用中,你通常不需要手动计算这些值。HAL库已经封装了这些底层硬件的复杂性,并提供了一个简单的API来使用

    如果STM32F1系列微控制器的HCLK(主时钟)频率是72 MHz,并且SysTick定时器的分频器值设置为8(这是默认值),那么SysTick定时器的时钟频率将是:

                         

    时钟频率=72 MHz/8=9 MHz

    这意味着SysTick定时器的时钟频率是9 MHz。SysTick定时器的自动重装载值(reload value)决定了计数器的计数周期。SysTick定时器的计数周期可以通过以下公式计算:

                   

    周期= 1/时钟频率
    
    ​
    

    因此,如果SysTick定时器的自动重装载值为1000,那么计数器将在9微秒后重新开始计数。

    如果你想知道SysTick定时器的计数器增加多少次才能达到1毫秒,你可以使用以下公式:

    计数次数= 1毫秒/周期
    
    ​
    
    ​
    

    将周期值代入公式:

    计数次数= 9 微秒/1 毫秒= 9 微秒/1000 微秒≈111.11 次

    这意味着SysTick定时器的计数器需要增加大约111次才能达到1毫秒。由于计数器是16位的,它可以从0增加到65535(即2^16 – 1),所以你可以使用以下公式来计算SysTick定时器能够提供多少毫秒的延迟:

    最大延迟时间= 65535/9 微秒
    ​
    

    将周期值代入公式:

    最大延迟时间= 65535/9 微秒≈727.07 毫秒
    ​
    

    因此,使用SysTick定时器,你可以实现大约727毫秒的延迟。如果需要更长的延迟时间,你可能需要使用其他定时器或外部时钟源。

    实例思路

    1设置时钟源(画圈的选/8)

     2代码设置(寄存器设计思路)

    实现系统的us延时(参数)
    {
       1.选择时钟 建议选择经过8分频后的外部时钟。
       2.写入重装载值,设为预期值-1。
       3.禁止中断。
       4.清空计数器。
       5.使能计数器。
       6.等待时间到达,等待标志位置1。
       7.关闭计数器。
       8.清空计数器。
    }
    

    2代码设置(修改HAL库的滴答计时器影响HAL_Delay()调节延时时间(会影响中断频率))

    1.1找到计时器的配置文件(函数)

     1.2修改此函数

    HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq))
    解释

    具体来说:

    1. SystemCoreClock:这是系统的核心时钟频率,即CPU的主频。

    2. 1000U:这里的U表示这个数字是一个无符号整数(unsigned int),1000U就是1000。

    3. uwTickFreq:这是一个变量,表示每秒钟SysTick定时器中断的次数。如果uwTickFreq是1,那么每个SysTick中断周期是1秒;如果uwTickFreq是1000,那么每个SysTick中断周期是1毫秒(ms),以此类推。

    4. 1000U / uwTickFreq:这个表达式计算每秒钟SysTick定时器应该中断多少次。这个值是用来将核心时钟频率(Hz)转换为每次SysTick中断所需的时钟周期数。

    5. SystemCoreClock / (1000U / uwTickFreq):这个表达式计算SysTick定时器的重装载数值,即每次SysTick中断所需的时钟周期数。这样配置后,SysTick定时器就会以uwTickFreq指定的频率产生中断。

    6. HAL_SYSTICK_Config():这个函数用于配置SysTick定时器的重装载数值寄存器。

    通过这种方式,我们可以灵活地配置SysTick定时器以不同的频率产生中断,而不必硬编码特定的频率值。这在需要根据不同应用场景调整定时器中断频率时非常有用。

    1.3修改此值uwTickFreq

    将 uwTickFreq 设置为 1 意味着 uwTick 变量将以秒为单位增加

    uwTickFreq 设置为1000  HAL_Delay(1)=1ms(默认)

    uwTickFreq 设置为 1000000(1百万)意味着 uwTick 变量将以微秒(μs)为单位增加

    作者:快秃头的码农

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32_HAL库实现SysTick系统定时器计时

    发表回复