HAL库 TIM计数器及中断开启过程

一、初始化TIM基本计数器参数函数

void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 36000-1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 2000-1; 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(); } }

二、HAL_TIM_Base_Init(&htim2)应用参数基本参数配置spa

HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) { /* Check the TIM handle allocation */
  if (htim == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_TIM_INSTANCE(htim->Instance)); assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); if (htim->State == HAL_TIM_STATE_RESET) { /* Allocate lock resource and initialize it */ htim->Lock = HAL_UNLOCKED; #if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
    /* Reset interrupt callbacks to legacy weak callbacks */ TIM_ResetCallback(htim); if (htim->Base_MspInitCallback == NULL) { htim->Base_MspInitCallback = HAL_TIM_Base_MspInit; } /* Init the low level hardware : GPIO, CLOCK, NVIC */ htim->Base_MspInitCallback(htim); #else
    /* Init the low level hardware : GPIO, CLOCK, NVIC */ HAL_TIM_Base_MspInit(htim); #endif /* USE_HAL_TIM_REGISTER_CALLBACKS */ } /* Set the TIM state */ htim->State = HAL_TIM_STATE_BUSY; /* Set the Time Base configuration */ TIM_Base_SetConfig(htim->Instance, &htim->Init); /* Initialize the TIM state*/ htim->State = HAL_TIM_STATE_READY; return HAL_OK; }

三、HAL_TIM_Base_MspInit(htim) 初始化中断信息(该函数须要重写,CubeMX在配置生成代码时会自动重写该函数)调试

/** * @brief Initializes the TIM Base MSP. * @param htim TIM Base handle * @retval None */ __weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) { /* Prevent unused argument(s) compilation warning */ UNUSED(htim); /* NOTE : This function should not be modified, when the callback is needed, the HAL_TIM_Base_MspInit could be implemented in the user file */ }

重写实现code

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM2) { /* USER CODE BEGIN TIM2_MspInit 0 */

  /* USER CODE END TIM2_MspInit 0 */
    /* TIM2 clock enable */ __HAL_RCC_TIM2_CLK_ENABLE(); /* TIM2 interrupt Init */ HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM2_IRQn); /* USER CODE BEGIN TIM2_MspInit 1 */

  /* USER CODE END TIM2_MspInit 1 */ } }

四、使能TIM中断blog

虽然通过以上配置,TIM的参数信息都已完整应用,可是TIM的中断并没用真正使能.这个地方困扰了我很久(运行没错误,可是计数中断就不触发, 不计数),必需调用如下函数使能中断,串口中断使能也是相似的.回调函数

HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *TIM);//开启定时器中断requests

该函数的调用地点只要是在 HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) 函数以后就行,能够在main.c中也能够在上面的代码以后.it

下面的代码存在一个BUG,若是 HAL_TIM_Base_Start_IT 函数调用写在下面的位置,虽然可使能中断,但会形成MCU上电即触发中断的状况.io

HAL_TIM_Base_MspInit调用以后会从新设置寄存器的值,__HAL_TIM_CLEAR_FLAG(tim_baseHandle, TIM_SR_UIF)清理的寄存器被改写.event

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM2) { /* USER CODE BEGIN TIM2_MspInit 0 */

  /* USER CODE END TIM2_MspInit 0 */
    /* TIM2 clock enable */ __HAL_RCC_TIM2_CLK_ENABLE(); /* TIM2 interrupt Init */ HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM2_IRQn); /* USER CODE BEGIN TIM2_MspInit 1 */
    //清理TIM开启时的中断标识
    __HAL_TIM_CLEAR_FLAG(tim_baseHandle, TIM_SR_UIF);//添加这条语句解决问题 //htim2.Instance->SR = 0; //这是另外一种解决办法 //使能TIM中断
    HAL_TIM_Base_Start_IT(tim_baseHandle);
  /* USER CODE END TIM2_MspInit 1 */ } }

正确的作法是在 HAL_TIM_Base_Init(&htim2) 以后使能TIM中断,并清理TIM的更新中断寄存器

void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 36000-1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 10000-1; 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(); } //清理TIM开启时的中断标识
    __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE); //使能TIM中断
    HAL_TIM_Base_Start_IT(&htim2); }

 

五、计数中断处理

/** * @brief 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_TIM_IRQHandler(&htim2)中断函数处理
/** * @brief This function handles TIM interrupts requests. * @param htim TIM handle * @retval None */
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) { /* Capture compare 1 event */
  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET) { if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET) { { __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; } } } ........................ ........................ /* TIM Update event */
  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET) { if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET) { __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 */ } } ........................ ........................ }
HAL_TIM_PeriodElapsedCallback(htim);当计数溢出时调用的回调函数,须要用户根据实际需求具体实现
/** * @brief Period elapsed callback in non-blocking mode * @param htim TIM handle * @retval None */ __weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { /* Prevent unused argument(s) compilation warning */ UNUSED(htim); /* NOTE : This function should not be modified, when the callback is needed, the HAL_TIM_PeriodElapsedCallback could be implemented in the user file */ }

 

六、实现计数完成回调函数,调试代码,查看计数器中断效果.

相关文章
相关标签/搜索