STM32_HAL库提高中断执行效率

目录

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

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

中断流程分析

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

; Vector Table Mapped to Address 0 at ResetAREA    RESET, DATA, READONLYEXPORT  __VectorsEXPORT  __Vectors_EndEXPORT  __Vectors_Size__Vectors       DCD     __initial_sp               ; Top of StackDCD     Reset_Handler              ; Reset HandlerDCD     NMI_Handler                ; NMI HandlerDCD     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);代码不可到达,会报

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/76568.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ惰性队列的工作原理、消息持久化机制、同步刷盘的概念、延迟插件的使用方法

惰性队列工作原理 惰性队列通过尽可能多地将消息存储到磁盘上来减少内存的使用。与传统队列相比,惰性队列不会主动将消息加载到内存中,而是尽量让消息停留在磁盘上,从而降低内存占用。尽管如此,它并不保证所有操作都是同步写入磁…

Spark Core(二)

Spark-Core编程(二) RDD转换算子 RDD 根据数据处理方式的不同将算子整体上分为 Value 类型、双 Value 类型和 Key-Value 类型 Value类型 1)map 将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以是…

C#打开文件及目录脚本

如果每天开始工作前都要做一些准备工作,比如打开文件或文件夹,我们可以使用代码一键完成。 using System.Diagnostics; using System.IO;namespace OpenFile {internal class Program{static void Main(string[] args){Console.WriteLine("Hello, …

Python生成exe

其中的 -w 参数是 PyInstaller 用于窗口模式(Windowed mode),它会关闭命令行窗口的输出,这通常用于 图形界面程序(GUI),比如使用 PyQt6, Tkinter, PySide6 等。 所以: 如果你在没有…

【大模型微调】如何解决llamaFactory微调效果与vllm部署效果不一致如何解决

以下个人没整理太全 一、生成式语言模型的对话模板介绍 使用Qwen/Qwen1.5-0.5B-Chat训练 对话模板不一样。回答的内容就会不一样。 我们可以看到例如qwen模型的tokenizer_config.json文件,就可以看到对话模板,一般同系列的模型,模板基本都…

Linux网络编程——详解网络层IP协议、网段划分、路由

目录 一、前言 二、IP协议的认识 1、什么是IP协议? 2、IP协议报头 三、网段划分 1、初步认识IP与路由 2、IP地址 I、DHCP动态主机配置协议 3、IP地址的划分 I、CIDR设计 II、子网数目的计算 III、子网掩码的确定 四、特殊的IP地址 五、IP地址的数量限…

ansible+docker+docker-compose快速部署4节点高可用minio集群

目录 github项目地址 示例服务器列表 安装前 修改变量文件group_vars/all.yml 修改ansible主机清单 修改setup.sh安装脚本 用法演示 安装后验证 github项目地址 https://github.com/sulibao/ansible_minio_cluster.git 示例服务器列表 安装前 修改变量文件group_var…

MySql主从相关概念

想象一下,你的业务飞速增长,用户请求如潮水般涌来,突然数据库主库宕机,数据丢失,服务瘫痪——这简直是开发者的噩梦!MySQL主从复制就像一张安全网,通过主库写、从库读的协作模式,不仅…

机械臂只有位置信息是否可以进行手眼标定?

平常我在做手眼标定时,一般都是通过OpenCV的cv::calibrateHandEye函数进行求解,需要输入多组不同的机械臂位姿。今天遇到了一款舵机机器人,只能获取位置,得不到姿态信息,想着那就把姿态都设为0,结果求不出来…

华为数字芯片机考2025合集2已校正

单选 1. 题目内容 关于亚稳态的描述错误的是( )。 1. 解题步骤 1.1 理解亚稳态(Metastability)的核心特性 亚稳态是指触发器无法在指定时间内稳定输出有效逻辑电平(0或1)的状态,其关键特点…

T-Box车载系统介绍及其应用

定义 T-Box汽车系统,全称为Telematics - BOX,也常简称为车载T - BOX,是汽车智能系统及车联网系统中的核心组成部分,是安装在车辆上的一种高科技远程信息处理器。 工作原理 T-Box的核心功能主要通过MPU和MCU实现。MPU负责应用程序功…

[redis进阶一]redis的持久化(1)RDB篇章

目录 一 认识持久化 (1)先看总结图 (2)什么是持久化? (3)redis是怎么进行持久化的呢 (4)简单分析一下RDB持久化和AOF持久化的不同 二 RDB持久化 (1)RDB的触发机制 (2)RDB的bgsave执行流程 (3)RDB文件的处理 (4)RDB的优缺点 (5)RDB效果演示板书 三 温习Linux文件…

uniapp日常总结--uniapp页面跳转方式

uniapp日常总结--uniapp页面跳转方式_uniapp 跳转-CSDN博客

《汽车电器与电子技术》实验报告

SRS系统结构原理与故障检测诊断 车辆上为什么要配安全气囊?——解析汽车被动安全的关键防线 一、安全气囊的核心作用:应对高速碰撞的“救命缓冲垫” 车辆在高速碰撞时(如正面碰撞、侧面碰撞),人体会因惯性以极高速度…

ffmpeg编解码器相关函数

文章目录 🎯 你需要理解的核心结构体:📦 常用函数及使用顺序(以解码为例)1️⃣ avcodec_find_decoder() / avcodec_find_encoder()2️⃣ avcodec_alloc_context3()3️⃣ avcodec_parameters_to_context()4️⃣ avcodec…

尚硅谷2019版Java网络编程笔记

第14章 网络编程 网络编程概述 什么是网络编程? 网络编程是通过网络协议实现计算机之间的数据交换。Java提供了强大的网络编程支持,隐藏了底层细节,开发者可以轻松实现网络通信。 网络编程的核心问题 如何定位网络上的主机:通…

解决【远程主机可能不符合 glibc 和 libstdc++ Vs code 服务器的先决条件】

可能是因为vscode不支持远程操作系统的版本,要么升级操作系统要么回退vscode版本 vscode回退1.97版本下载地址: 1.97版本VSCODE

forms+windows添加激活水印

formswindows添加激活水印 多语言水印文本,根据系统语言自动切换。水印显示在每个屏幕的右下角,位置动态调整。半透明灰色文字,微软雅黑字体。窗口无边框、置顶、透明背景,不干扰用户操作。支持多显示器。高DPI适配。 效果图&am…

LeetCode --- 444 周赛

题目列表 3507. 移除最小数对使数组有序 I 3508. 设计路由器 3509. 最大化交错和为 K 的子序列乘积 3510. 移除最小数对使数组有序 II 一、移除最小数对使数组有序 I & II 由于数组是给定的,所以本题的操作步骤是固定的,我们只要能快速模拟操作的过…

限流、降级、熔断、隔离?

在微服务架构中,服务限流、降级、熔断和隔离是保障系统高可用性的核心手段,但它们解决的问题和应用场景不同。以下是它们的区别、解决方案和实际案例的详细说明: 一、服务限流(Rate Limiting) 定义:通过限…