本帖最后由 南来之风 于 2023-7-31 22:24 编辑
ST的官方库有非常丰富的外设使用例程,本文体验的就是:STM32Cube_FW_WBA_V1.1.0\Projects\NUCLEO-WBA52CG\Examples\TIM\TIM_TimeBase
该例程配置使用TIM模块产生一个1s的中断,然后再中断服务函数中翻转LED。
初始化外设,Flash和Systick:
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) - 1SystemCoreClock 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频率闪烁。
|