打印
[STM32WBA]

【STM32WBA52CG测评】-4- 定时器模块TIM例程分析

[复制链接]
882|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 南来之风 于 2023-7-31 22:24 编辑

ST的官方库有非常丰富的外设使用例程,本文体验的就是:STM32Cube_FW_WBA_V1.1.0\Projects\NUCLEO-WBA52CG\Examples\TIM\TIM_TimeBase
该例程配置使用TIM模块产生一个1s的中断,然后再中断服务函数中翻转LED。

初始化外设,Flash和Systick:
HAL_Init();


SystemClock_Config() 函数用于配置STM32WBA52CGUx 设备系统时钟为100 MHz
  /* Configure the system clock */
  SystemClock_Config();

根据官方ReadMe,TIM模块的时钟频率,TIM2模块的计数器时钟频率,以及周期都有相应的公式:


In this example TIM2 input clock (TIM2CLK)  is set to APB1 clock (PCLK1),since APB1 prescaler is equal to 1.  TIM2CLK = PCLK1  PCLK1 = HCLK  => TIM2CLK = HCLK = SystemCoreClockTo get TIM2 counter clock at 10 KHz, the Prescaler is computed as following:Prescaler = (TIM2CLK / TIM2 counter clock) - 1Prescaler = (SystemCoreClock /10 KHz) - 1
SystemCoreClock is set to 100 MHz for STM32WBAxx Devices.
The TIM2 ARR register value is equal to 10000 - 1
Update rate = TIM2 counter clock / (Period + 1) = 1 Hz
So the TIM2 generates an interrupt each 1 s
When the counter value reaches the auto-reload register value, the TIM update interrupt is generated and, in the handler routine, pin PB.4 (connected to LD1 on board NUCLEO-WBA52CG) is toggled. So led blinks at the following frequency: 0.5Hz.
In case of error, LD3 is turned ON.

在main.h中,有相应的参数定义:
/* Compute the prescaler value to have TIMx counter clock equal to 10000 Hz */

#define PRESCALER_VALUE (uint32_t)(((SystemCoreClock) / (10000)) - 1)

  /* Initialize TIMx peripheral as follows:
       + Period = 10000 - 1
       + Prescaler = (SystemCoreClock/10000) - 1
       + ClockDivision = 0
       + Counter direction = Up
  */

#define PERIOD_VALUE (10000 - 1);


在main.c中,调用如下函数进行TIM模块初始化:
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url] TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = PRESCALER_VALUE;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = PERIOD_VALUE;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

如下定义了TIM2模块的中断服务子程序:
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url] This function handles TIM2 global interrupt.
  */
void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */

  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */

  /* USER CODE END TIM2_IRQn 1 */
}

接着调用HAL库中的中断服务子程序:
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
  uint32_t itsource = htim->Instance->DIER;
  uint32_t itflag   = htim->Instance->SR;

  /* Capture compare 1 event */
  if ((itflag & (TIM_FLAG_CC1)) == (TIM_FLAG_CC1))
  {
    if ((itsource & (TIM_IT_CC1)) == (TIM_IT_CC1))
    {
      {
        __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;

        /* Input capture event */
        if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
        {
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
          htim->IC_CaptureCallback(htim);
#else
          HAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
        }
        /* Output compare event */
        else
        {
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
          htim->OC_DelayElapsedCallback(htim);
          htim->PWM_PulseFinishedCallback(htim);
#else
          HAL_TIM_OC_DelayElapsedCallback(htim);
          HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
        }
        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
      }
    }
  }
  /* Capture compare 2 event */
  if ((itflag & (TIM_FLAG_CC2)) == (TIM_FLAG_CC2))
  {
    if ((itsource & (TIM_IT_CC2)) == (TIM_IT_CC2))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC2);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
      /* Input capture event */
      if ((htim->Instance->CCMR1 & TIM_CCMR1_CC2S) != 0x00U)
      {
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
        htim->IC_CaptureCallback(htim);
#else
        HAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
      }
      /* Output compare event */
      else
      {
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
        htim->OC_DelayElapsedCallback(htim);
        htim->PWM_PulseFinishedCallback(htim);
#else
        HAL_TIM_OC_DelayElapsedCallback(htim);
        HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
  }
  /* Capture compare 3 event */
  if ((itflag & (TIM_FLAG_CC3)) == (TIM_FLAG_CC3))
  {
    if ((itsource & (TIM_IT_CC3)) == (TIM_IT_CC3))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC3);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
      /* Input capture event */
      if ((htim->Instance->CCMR2 & TIM_CCMR2_CC3S) != 0x00U)
      {
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
        htim->IC_CaptureCallback(htim);
#else
        HAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
      }
      /* Output compare event */
      else
      {
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
        htim->OC_DelayElapsedCallback(htim);
        htim->PWM_PulseFinishedCallback(htim);
#else
        HAL_TIM_OC_DelayElapsedCallback(htim);
        HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
  }
  /* Capture compare 4 event */
  if ((itflag & (TIM_FLAG_CC4)) == (TIM_FLAG_CC4))
  {
    if ((itsource & (TIM_IT_CC4)) == (TIM_IT_CC4))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC4);
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
      /* Input capture event */
      if ((htim->Instance->CCMR2 & TIM_CCMR2_CC4S) != 0x00U)
      {
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
        htim->IC_CaptureCallback(htim);
#else
        HAL_TIM_IC_CaptureCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
      }
      /* Output compare event */
      else
      {
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
        htim->OC_DelayElapsedCallback(htim);
        htim->PWM_PulseFinishedCallback(htim);
#else
        HAL_TIM_OC_DelayElapsedCallback(htim);
        HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
      }
      htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
    }
  }
  /* TIM Update event */
  if ((itflag & (TIM_FLAG_UPDATE)) == (TIM_FLAG_UPDATE))
  {
    if ((itsource & (TIM_IT_UPDATE)) == (TIM_IT_UPDATE))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->PeriodElapsedCallback(htim);
#else
      HAL_TIM_PeriodElapsedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
  /* TIM Break input event */
  if ((itflag & (TIM_FLAG_BREAK)) == (TIM_FLAG_BREAK))
  {
    if ((itsource & (TIM_IT_BREAK)) == (TIM_IT_BREAK))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_BREAK);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->BreakCallback(htim);
#else
      HAL_TIMEx_BreakCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
  /* TIM Break2 input event */
  if ((itflag & (TIM_FLAG_BREAK2)) == (TIM_FLAG_BREAK2))
  {
    if ((itsource & (TIM_IT_BREAK)) == (TIM_IT_BREAK))
    {
      __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_BREAK2);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->Break2Callback(htim);
#else
      HAL_TIMEx_Break2Callback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
  /* TIM Trigger detection event */
  if ((itflag & (TIM_FLAG_TRIGGER)) == (TIM_FLAG_TRIGGER))
  {
    if ((itsource & (TIM_IT_TRIGGER)) == (TIM_IT_TRIGGER))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_IT_TRIGGER);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->TriggerCallback(htim);
#else
      HAL_TIM_TriggerCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
  /* TIM commutation event */
  if ((itflag & (TIM_FLAG_COM)) == (TIM_FLAG_COM))
  {
    if ((itsource & (TIM_IT_COM)) == (TIM_IT_COM))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_COM);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->CommutationCallback(htim);
#else
      HAL_TIMEx_CommutCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
  /* TIM Encoder index event */
  if ((itflag & (TIM_FLAG_IDX)) == (TIM_FLAG_IDX))
  {
    if ((itsource & (TIM_IT_IDX)) == (TIM_IT_IDX))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_IDX);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->EncoderIndexCallback(htim);
#else
      HAL_TIMEx_EncoderIndexCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
  /* TIM Direction change event */
  if ((itflag & (TIM_FLAG_DIR)) == (TIM_FLAG_DIR))
  {
    if ((itsource & (TIM_IT_DIR)) == (TIM_IT_DIR))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_DIR);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->DirectionChangeCallback(htim);
#else
      HAL_TIMEx_DirectionChangeCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
  /* TIM Index error event */
  if ((itflag & (TIM_FLAG_IERR)) == (TIM_FLAG_IERR))
  {
    if ((itsource & (TIM_IT_IERR)) == (TIM_IT_IERR))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_IERR);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->IndexErrorCallback(htim);
#else
      HAL_TIMEx_IndexErrorCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
  /* TIM Transition error event */
  if ((itflag & (TIM_FLAG_TERR)) == (TIM_FLAG_TERR))
  {
    if ((itsource & (TIM_IT_TERR)) == (TIM_IT_TERR))
    {
      __HAL_TIM_CLEAR_IT(htim, TIM_FLAG_TERR);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
      htim->TransitionErrorCallback(htim);
#else
      HAL_TIMEx_TransitionErrorCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
    }
  }
}

注意其中有个函数调用:

HAL_TIM_PeriodElapsedCallback(htim);

这个回调函数的定义如下:

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  Period elapsed callback in non blocking mode
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
        BSP_LED_Toggle(LD1);
}


烧录后,可以看到LD1以1s频率闪烁。






使用特权

评论回复
沙发
gejigeji521| | 2024-1-12 17:03 | 只看该作者
分析的少了,全是源码了,没看太懂,应该先将一下整个原理。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

48

主题

250

帖子

2

粉丝