当前位置: 首页 > news >正文

STM32_HAL库提高中断执行效率

目录

  • 中断流程分析
  • 我的解决办法
  • 优缺点

大家都在说STM32 HAL 库中断效率低下。具体哪里不行?如何优化?
我手里的项目要用到多个定时器TIM6、TIM7、TIM9、TIM10、TIM11、TIM12、TIM13,在处理这些定时器中断的时候,也发现了这个问题。
下面给出我的分析和解决办法。

中断流程分析

以TIM7 中断流程分析,中断条件满足之后,单片机从中断向量表中找中断服务函数TIM7_IRQHandler,然后跳转进去

; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size

__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
......                               
                DCD     TIM6_DAC_IRQHandler               ; TIM6 and DAC1&2 underrun errors                   
                DCD     TIM7_IRQHandler                   ; TIM7

TIM7_IRQHandler内容如下,从这里HAL库开始接管

void TIM7_IRQHandler(void)
{
  /* USER CODE BEGIN TIM7_IRQn 0 */

  /* USER CODE END TIM7_IRQn 0 */
  HAL_TIM_IRQHandler(&htim7);
  /* USER CODE BEGIN TIM7_IRQn 1 */

  /* USER CODE END TIM7_IRQn 1 */
}

HAL_TIM_IRQHandler内容如下,为了方便阅读做了删减

	if ((itflag & (TIM_FLAG_CC1)) == (TIM_FLAG_CC1)){/* Capture compare 1 event Process */}
	if ((itflag & (TIM_FLAG_CC2)) == (TIM_FLAG_CC2)){/* Capture compare 2 event Process */}
	if ((itflag & (TIM_FLAG_CC3)) == (TIM_FLAG_CC3)){/* Capture compare 3 event Process */}
	if ((itflag & (TIM_FLAG_CC4)) == (TIM_FLAG_CC4)){/* Capture compare 4 event Process */}
	if ((itflag & (TIM_FLAG_UPDATE)) == (TIM_FLAG_UPDATE)){
			/* TIM Update event Process */
			//我的定时器只用来做定时中断,所以关注TIM_IT_UPDATE中断
		    if ((itsource & (TIM_IT_UPDATE)) == (TIM_IT_UPDATE))
		   	{
		   		//清除标志位
			    __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_UPDATE);	
				#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
				//如果启用了回调函数注册执行这里,实际上我们重写下面一条语句的函数效果类似。
				      htim->PeriodElapsedCallback(htim);
				#else
				//没有启用回调函数,执行这里。HAL_TIM_PeriodElapsedCallback是虚函数,用户自行重写
				      HAL_TIM_PeriodElapsedCallback(htim);
				#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
		    }
	}
	if ((itflag & (TIM_FLAG_BREAK)) == (TIM_FLAG_BREAK)){/* TIM Break input event Process */}
	if ((itflag & (TIM_FLAG_TRIGGER)) == (TIM_FLAG_TRIGGER)){/* TIM Trigger detection event Process */}
	if ((itflag & (TIM_FLAG_COM)) == (TIM_FLAG_COM)){/* TIM commutation event Process */}
	

HAL_TIM_PeriodElapsedCallback的定义如下

/**
  * @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
   */
}

可以看出来,不同中断公用一个最终的处理函数HAL_TIM_PeriodElapsedCallback,在该函数里用户自己靠传入的形参htim去区分是哪一个中断触发的。那么实际重写HAL_TIM_PeriodElapsedCallback的时候,应该是如下结构

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim == htim6)
	{
	} else if(htim == htim7)
	{
	}else if(htim == htim9)
	{
	}else if(htim == htim10)
	{
	}
	......
}

这样的处理方便倒是挺方便的,但是明显的效率低下。主要体现如下两部分:

  • 我不需要判断那么多中断事件,我对自己项目中定时器的作用非常清晰,不会用于做捕获、从机等,也就不用判断这些中断事件。
  • 不同定时器公用一个回调函数,在回调函数内再区分,效率低下。原本不同的定时器就有不同的中断服务函数的。
    在这里插入图片描述

我的解决办法

在TIM7_IRQHandler里写应用,然后直接返回

void TIM7_IRQHandler(void)
{
  /* USER CODE BEGIN TIM7_IRQn 0 */
  if(TIMER_Group.callback[1])				
    TIMER_Group.callback[1]();
  return;
  /* USER CODE END TIM7_IRQn 0 */
  HAL_TIM_IRQHandler(&htim7);
  /* USER CODE BEGIN TIM7_IRQn 1 */

  /* USER CODE END TIM7_IRQn 1 */
}

callback指向的函数内容如下

static void hwtimer2_callback(void)
{
	/* some app*/
	__HAL_TIM_CLEAR_FLAG(htim7, TIM_IT_UPDATE);//手动清除标志位
}

优缺点

优点:解决了中断效率低下的问题
缺点1:return后面HAL_TIM_IRQHandler(&htim7);任然参与编译,可能占用更多的Flash空间
缺点2:因为HAL_TIM_IRQHandler(&htim7);代码不可到达,会报

相关文章:

  • 采矿业中的无人机-通过无人机勘测完实现 99% 的精确测量和 30 倍以上的加速数据采集
  • [随笔] nn.Embedding的前向传播与反向传播
  • Spring Boot项目中结合MyBatis实现MySQL的自动主从切换
  • 快排算法 (分治实现)
  • 11. Langchain输出解析(Output Parsers):从自由文本到结构化数据
  • 【后端开发】Spring MVC-常见使用、Cookie、Session
  • 分析下HashMap容量和负载系数,它是怎么扩容的?
  • 底盘---全向轮(Omni Wheel)
  • 重温Java - Java基础二
  • 无人设备遥控器之通信链路管理篇
  • C++ 创建静态数组出现栈满程序崩溃的问题
  • 【虚拟机栈中的栈帧是什么?有什么作用?局部变量表、操作数栈、动态链接和方法返回地址是什么?有什么作用?为什么要放在栈帧里?】
  • Ubuntu24.04 编译 Qt 源码
  • 一个可以在Android手机上运行的Linux高仿window10的应用
  • Python中的AdaBoost分类器:集成方法与模型构建
  • VT01N/VT02N进行交货的时候,对装运点加权限控制的增强
  • 原生SSE实现AI智能问答+Vue3前端打字机流效果
  • 【语法】C++的list
  • 模糊测试究竟在干什么
  • 41、web前端开发之Vue3保姆教程(五 实战案例)
  • 不想让网站保存密码怎么做/360推广客服电话是多少
  • 如何做网站宣传自己/网页设计模板素材图片
  • 驻马店网站建设zmdsem/广东seo排名
  • 怎么用网站做文案/自己搭建网站需要什么
  • 重庆公司网站seo/全网整合营销
  • 保险公司网站开发/广州网站优化排名系统