对于stm32 systick timer周期为1ms的函数设置分析

之前一直对stm32的上电后的system tick timer时钟配置存疑,为什么定时时间不随频率改变总能保持1ms,cude生成的两个函数HAL_Init()、SystemClock_Config()具体做了什么。趁着空闲把困惑已久又不起眼的问题解答了。

首先分析main中第一个调用的函数HAL_Init():

HAL_StatusTypeDef HAL_Init(void)
{
  /* Configure Flash prefetch */
#if (PREFETCH_ENABLE != 0)
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
    defined(STM32F102x6) || defined(STM32F102xB) || \
    defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
    defined(STM32F105xC) || defined(STM32F107xC)

  /* Prefetch buffer is not available on value line devices */
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif
#endif /* PREFETCH_ENABLE */

  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  HAL_InitTick(TICK_INT_PRIORITY);

  /* Init the low level hardware */
  HAL_MspInit();

  /* Return function status */
  return HAL_OK;
}

在stm32f1xx_hal_conf.h中可以看到PREFETCH_ENABLE被宏定义为1,STM32F103xE已经在keil的设置中被预定义

//stm32f1xx_hal_conf.h
#define  PREFETCH_ENABLE			1U

在这里插入图片描述

所以函数__HAL_FLASH_PREFETCH_BUFFER_ENABLE()就能被调用,这个函数使能了flash的预取缓冲区

__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#define __HAL_FLASH_PREFETCH_BUFFER_ENABLE()    (FLASH->ACR |= FLASH_ACR_PRFTBE)

在cube中我对中断优先级设置了4bit主优先级,0bit的次优先级,所以 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)参数为NVIC_PRIORITYGROUP_4
在这里插入图片描述

然后就是函数HAL_InitTick(TICK_INT_PRIORITY)

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    return HAL_ERROR;
  }

  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}

SystemCoreClock 是个被初始化为16000000的变量,uwTickFreq被宏定义为1,所以调用参数为HAL_SYSTICK_Config(16000),经过重重查找找到

//stm32f1xx_hal_cortex.c
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
   return SysTick_Config(TicksNumb);
}

//core_cm3.h
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}

tick(16000) < SysTick_LOAD_RELOAD_Msk(0xFFFFFF), 这里SySTick的重装寄存器LOAD设为16000-1,计数寄存器设为0,SysTick_CTRL_CLKSOURCE_Msk设置systick时钟源为AHB而不是AHB/8, SysTick_CTRL_TICKINT_Msk 使能systick中断,SysTick_CTRL_ENABLE_Msk使能systick timer。那么关于systick timer周期设置流程由此得出:系统后面调用SystemClock_Config()初始化完成OSC CLK和AHB CLK与systick时钟源为AHB后,SYSTICK CLK频率就固定为72MHZ,变量SystemCoreClock被改变为72MHZ, 通过再次调用HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq),timer定时器周期=(72000000/1000)*72000000=1/1000(s)==1ms
完成收工!

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值