LED定时闪烁实验
先简单说明一下用法。
stm32cube配置TIM3,时钟源选择内部时钟。在下方参数配置中输入预分频值和计数值,使能自动装载。
在主函数中添加代码
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* 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();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
MX_TIM3_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim3); //这是添加的代码
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if(LED_FLAG)
LED_On();
else
LED_Off();
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
在stm32f1xx_hal_tim.c文件中找到如下定义:
__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
*/
}
去掉__weak后把它复制到自己的代码中,如下。(自动生成的代码中,中断回调函数都有一个__weak 关键字表示弱定义,加上了__weak 修饰符的函数,去掉__weak,我们在自己的文件中定义一个相同的函数,编译时会忽略弱定义的函数,会编译我们定义的函数。如果我们没有重新定义则会编译弱定义的代码)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
if (htim == (&htim3))
LED_FLAG = !LED_FLAG;
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
*/
}
至此定时器就可以正常使用了。
下面分析一下定时器相关带代码工作流程。
main中添加的HAL_TIM_Base_Start_IT(&htim3);函数是启动基本定时器的中断。如果配制了其他的定时器相关的功能则有其他的对应的启动函数例如HAL_TIM_PWM_Start_IT() ;HAL_TIM_OnePulse_Start_IT() ;等
首先看一下汇编引导文件
中断向量表中定义是 EXPORT TIM3_IRQHandler [WEAK],所以中断发生时最先执行的是下面这个函数,他引用了HAL_TIM_IRQHandler(&htim3);
void TIM3_IRQHandler(void) //删除了注释太占地方
{
HAL_TIM_IRQHandler(&htim3);
}
我们再开启TIM4作为对比,结构相同
void TIM4_IRQHandler(void) //删除了注释太占地方
{
HAL_TIM_IRQHandler(&htim4);
}
在HAL_TIM_IRQHandler(&htim3);中找到如下代码。执行了我们的中断回调函数
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) //此定义值为0,执行else分支
htim->PeriodElapsedCallback(htim);
#else
HAL_TIM_PeriodElapsedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
}