使用cubeMx 生成systick及周期调整

使用cubeMx 生成systick及周期调整

cubeMX配置
在cubeMx中生成的代码工程是自动配置systick时钟的,因为HAL库中的一些函数需要systick时钟来判断操作是否超时,下面要进入重点:如何配置systick,从cubeMX中生成的systick的周期时1ms一次的。
在main函数中找到其初始化代码:

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

从SystemClock_Config();进入找到

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage 
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

HAL_RCC_OscConfig(&RCC_OscInitStruct) 这个函数里面包含了配置systick的代码,进来后找到HAL_InitTick(uwTickPrio) ,HAL_InitTick(uwTickPrio) 就是配置systick的函数。

   /* Adapt Systick interrupt period */
        if (HAL_InitTick(uwTickPrio) != HAL_OK)
        {
          return HAL_ERROR;
        }

下面就是定义systick的函数,其中uwTickFreq定义为1,可以去看其定义的地方。

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  HAL_StatusTypeDef  status = HAL_OK;

  if (uwTickFreq != 0U)
  {
    /*Configure the SysTick to have interrupt in 1ms time basis*/
    if (HAL_SYSTICK_Config(SystemCoreClock / (1000U /uwTickFreq)) == 0U)
    {
      /* Configure the SysTick IRQ priority */
      if (TickPriority < (1UL << __NVIC_PRIO_BITS))
      {
        HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
        uwTickPrio = TickPriority;
      }
      else
      {
        status = HAL_ERROR;
      }
    }
    else
    {
      status = HAL_ERROR;
    }
  }
  else
  {
    status = HAL_ERROR;
  }

  /* Return function status */
  return status;
}

那么这个周期时如何计算的呢?关键在于SystemCoreClock / (1000U /uwTickFreq),这里是得到的数值是传入到设置systick定时器的。因为uwTickFreq为1,所以周期的数值就是SystemCoreClock/1000,这里我们先假设SystemCoreClock是72MHz,那么systick的周期值就是72000,systick进入中断的频率就是72000000/72000=1000Hz,也就是1s进入systick中断1000次,所以每次中断就是1ms。如果要调整周期,只需要调整 (1000U /uwTickFreq)这个数值即可, (1000U /uwTickFreq)计算的结果就是systick的频率值,由于uwTickFreq为1,所以systick的频率就是1000U,如果想改变systick的周期,只要1000U改为想要的频率值即可(周期=1/频率)。
改变了周期之后会对HAL库的一些函数有影响,因为有些函数是要判断操作是否超时的,所以会以systick为计时器,通过回调__weak uint32_t HAL_GetTick(void)这个函数来判断操作是否超时,具体操作可以去看相应的函数。既然有影响我们就要消除影响,因为HAL_GetTick()这个函数主要是return uwTick;而影响uwTick的函数是__weak void HAL_IncTick(void)

__weak void HAL_IncTick(void)
{
  uwTick += uwTickFreq;
}

uwTickFreq为1,这个函数有__weak 关键字标识,是可以重写的,我们只要在我们自己的.c文件中重写void HAL_IncTick(void)函数即可,我们这里仍然希望是1ms( uwTick +1),那么就根据自己设置的systick的频率来计算systick的周期值,每个周期systick会回调一次HAL_IncTick()函数,只要在HAL_IncTick()函数中计算好回调多少次该函数uwTick再+1即可。

猜你喜欢

转载自blog.csdn.net/qq_35002379/article/details/103402114