STM32F407HAL库-10.滴答定时器

SysTick定时器也叫滴答定时器,是属于CM4内核中的一个外设,内嵌在NVIC中。滴答定时器是一个24bit的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK等于 180M。当重装载数值寄存器的值递减到 0的时候,系统定时器就产生一次中断,以此循环往复。

SysTick定时器有4个寄存器,在使用SysTick产生定时的时候,只需要配置CTRL、LOAD、VAL三个寄存器,CALIB校准寄存器不需要配置(出厂时已校准好),寄存器介绍如下:

寄存器名称

寄存器描述

SYST_CSR

SysTick控制及状态寄存器

SYST_RVR

SysTick重装载值寄存器

SYST_CVR

SysTick当前数值寄存器

SYST_CALIB

SysTick校准数值寄存器

1、SYST_CSR控制及状态寄存器

STM32F407HAL库-10.滴答定时器_第1张图片

位段

名称

复位值

描述

16

COUNTFLAG

0

如果计时器从上次读取后计数到0,则该位返回1

2

CLKSOURCE

0

时钟源选择位:

0 = AHB/8

1 = 处理器时钟AHB

1

TICKINT

0

启用SysTick异常请求:

0 = 计时器数到0时没有异常请求。

1 = 计时器数到0时产生SysTick异常请求

通过读取 COUNTFLAG 位可以确定计数器是否递减到 0

0

ENABLE

0

SysTick定时器的使能位

2、SYST_RVR重装载值寄存器

位段

名称

复位值

描述

23::0

RELOAD

0

当倒数计数到0时,加载到SYST_CVR寄存器的值

RELOAD值可以是0x00000001 - 0x00FFFFFF范围内的任何值。起始值可以为0,但是没有效果,因为SysTick异常请求和COUNTFLAG在从1到0计数时才被激活。

重新装载值是根据其使用情况计算的。例如,要生成周期为N个处理器时钟周期的多次触发定时器,可以配置RELOAD值为N-1。如果每100个时钟脉冲需要SysTick中断,则将RELOAD设置为99。

3、SYST_CVR当前数值寄存器

位段

名称

复位值

描述

23::0

CURRENT

0

读取返回SysTick计数器的当前值。向寄存器写入任何值时都会将该字段清除为0,并将SYST_CSR的COUNTFLAG位清除为0。

系统定时器的校准数值寄存器在定时实验中不需要用到。寄存器详细介绍请参考Cortex-M4用户指南《Cortex-M4 Generic User Guide》。

4、HAL库提供了滴答定时器初始化函数,位于“core_cm4.h”文件的2014行,函数主要实现了初始化系统计时器的各个寄存器及其中断,并启动系统计时,函数内容如下:

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                  
  }
  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                        
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         
  return (0UL);                                                    
}

5、在“stm32f4xx_hal.c”文件的269行提供了一个滴答定时器配置函数HAL_InitTick(),该函数根据系统时钟频率SystemCoreClock来重新配置滴答定时器的重装载值,以决定产生每个中断的时间(函数中配置为1ms产生一次中断),函数同时设置了定时器的中断优先级,函数内容如下:

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }
  return HAL_OK;
} 

6、在“stm32f4xx_hal.c”文件中,HAL库还定义了ms延时函数HAL_Delay(),函数中首先定义了32位全局变量uwTick,在Systick中断服务函数SysTick_Handler(位于“bsp_clock.c”文件)中通过调用HAL_IncTick实现uwTick值不断增加,也就是每隔1ms增加1。而HAL_Delay函数在进入函数之后先记录当前uwTick的值,然后不断在循环中读取uwTick当前值,进行减运算,得出的就是延时的毫秒数。

//下面代码均在文件 stm32f4xx_hal.c 中
static __IO uint32_t uwTick; //定义计数全局变量
__weak void HAL_IncTick(void) //全局变量 uwTick 递增
{
    uwTick++;
}
__weak uint32_t HAL_GetTick(void) //获取全局变量 uwTick 的值
{
    return uwTick;
}
//开放的 HAL 延时函数,延时 Delay 毫秒
__weak void HAL_Delay(__IO uint32_t Delay)
{
    uint32_t tickstart = 0;
    tickstart = HAL_GetTick();
    while((HAL_GetTick() - tickstart) < Delay)
    {
    }
}

 

你可能感兴趣的:(STM32F4外设开发)