1、初始化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();
}
}
2、HAL_TIM_Base_Init(&htim2)应用参数基本参数配置
HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim)
{/*Check the TIM handle allocation*/
if (htim ==NULL)
{returnHAL_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;returnHAL_OK;
}
3、HAL_TIM_Base_MspInit(htim)初始化中断信息(该函数需要重写,CubeMX在配置生成代码时会自动重写该函数)
/**
* @brief Initializes the TIM Base MSP.
* @param htim TIM Base handle
* @retval None*/__weakvoid 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*/}
重写实现
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*/}
}
4、使能TIM中断
虽然经过以上配置,TIM的参数信息都已完整应用,但是TIM的中断并没用真正使能.这个地方困扰了我好久(运行没错误,但是计数中断就不触发, 不计数),必需调用以下函数使能中断,串口中断使能也是类似的.
HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *TIM);//开启定时器中断
该函数的调用地点只要是在 HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) 函数之后就行,可以在main.c中也可以在上面的代码之后.
下面的代码存在一个BUG,如果 HAL_TIM_Base_Start_IT 函数调用写在下面的位置,虽然可以使能中断,但会造成MCU上电即触发中断的情况.
HAL_TIM_Base_MspInit调用之后会重新设置寄存器的值,__HAL_TIM_CLEAR_FLAG(tim_baseHandle, TIM_SR_UIF)清理的寄存器被改写.
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);
}
5、计数中断处理
/**
* @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);#elseHAL_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);#elseHAL_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);#elseHAL_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*/__weakvoid 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*/}
6、实现计数完成回调函数,调试代码,查看计数器中断效果.
原文:https://www.cnblogs.com/dw039/p/11629744.html