stm32学习之路——系统滴答时钟

1. 系统滴答时钟

stm32配置完外部晶振时钟源后会有一个默认的时钟中断用于记录tick,这个时钟是固定的1ms(暂时没找到不修改代码调整的方式)。HAL库中systick的配置

// Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
/**
  * @brief This function configures the source of the time base.
  *        The time source is configured  to have 1ms time base with a dedicated
  *        Tick interrupt priority.
  * @note This function is called  automatically at the beginning of program after
  *       reset by HAL_Init() or at any time when clock is reconfigured  by HAL_RCC_ClockConfig().
  * @note In the default implementation, SysTick timer is the source of time base.
  *       It is used to generate interrupts at regular time intervals.
  *       Care must be taken if HAL_Delay() is called from a peripheral ISR process,
  *       The SysTick interrupt must have higher priority (numerically lower)
  *       than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
  *       The function is declared as __weak  to be overwritten  in case of other
  *       implementation  in user file.
  * @param TickPriority Tick interrupt priority.
  * @retval HAL status
  */
__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;
}

可以看到时钟被调整为1ms,传入HAL_SYSTICK_Config的是计数器的值,计数到达这个值触发中断。算一下

  • SystemCoreClock是核心时钟的频率,也就是计数器计数频率,如果什么都不除,这里就会造成1s的中断计数(8MHz计数8M,就是1s一次)
  • 除以1000就是代表搞1ms中断
  • uwTickFreq定义如下,代表真实想要的中断频率,默认就是1KHZ也就是除以1,还是1000,对应的正好是1ms中断
// Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal.h
/** @defgroup HAL_TICK_FREQ Tick Frequency
  * @{
  */
typedef enum
{
  HAL_TICK_FREQ_10HZ         = 100U,
  HAL_TICK_FREQ_100HZ        = 10U,
  HAL_TICK_FREQ_1KHZ         = 1U,
  HAL_TICK_FREQ_DEFAULT      = HAL_TICK_FREQ_1KHZ
} HAL_TickFreqTypeDef;

// Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT;  /* 1KHz */
  • 系统时钟中断触发函数定义为SysTick_Handler
// Core/Src/stm32f1xx_it.c
/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

// Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c
/**
  * @brief This function is called to increment  a global variable "uwTick"
  *        used as application time base.
  * @note In the default implementation, this variable is incremented each 1ms
  *       in SysTick ISR.
  * @note This function is declared as __weak to be overwritten in case of other
  *      implementations in user file.
  * @retval None
  */
__weak void HAL_IncTick(void)
{
  uwTick += uwTickFreq;
}

这个HAL_IncTick是个__weak定义的,说明可以用户自定义,从里面的定义可以看出,这个uwTick保持ms级别计数。

  • uwTickFreq = 1,1ms,uwTick+1
  • uwTickFreq = 10,10ms,uwTick+10

uwTick和uwTickFreq对外暴露了,定义在这里

// Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal.h
/* Exported types ------------------------------------------------------------*/
extern __IO uint32_t uwTick;
extern uint32_t uwTickPrio;
extern HAL_TickFreqTypeDef uwTickFreq;

我们可以重写这个HAL_IncTick作为我们自己的定时器处理函数,可以从一个1ms定时器搞出很多个定时器。

volatile unsigned long jiffies = 0;

static void timer_handler(void) {
    ++jiffies;
}

/**
 * @brief  Period elapsed callback in non-blocking mode
 * @param  htim TIM handle
 * @retval None
 */
void HAL_IncTick() {
    // 还原原始调用
    uwTick += uwTickFreq;
    // 调用定时器处理函数
    timer_handler();
}

虽然uwTick作为ms计数很不错,这里搞个好玩的,把linux的jiffies搞进来使用,单独记录一个。主要是想要应用层代码和HAL完全隔离,不想要太多依赖HAL库,这样好移植

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员kid1412

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值