STM32 HAL库FreeRTOS 中断管理

news2025/4/22 9:17:04

一、引言

在嵌入式系统开发中,STM32 微控制器凭借其高性能、低功耗和丰富的外设资源,被广泛应用于各种领域。FreeRTOS 作为一款轻量级、开源且功能强大的实时操作系统,为多任务处理提供了良好的支持。中断是嵌入式系统中实现实时响应外部事件的重要机制,合理管理中断对于系统的稳定性和实时性至关重要。本文将深入探讨基于 STM32 HAL 库与 FreeRTOS 的中断管理,详细介绍中断的基本概念、STM32 的中断机制、FreeRTOS 对中断的处理方式以及如何在两者结合的环境下进行有效的中断管理。

二、中断基本概念

2.1 中断的定义

中断是指 CPU 在执行程序的过程中,遇到外部或内部的紧急事件需要处理时,暂时停止当前程序的执行,转去执行相应的中断服务程序,处理完中断事件后,再返回原来被中断的程序继续执行。中断机制使得系统能够及时响应外部事件,提高了系统的实时性和处理能力。

2.2 中断的分类

  • 硬件中断:由外部硬件设备产生的中断请求,如按键按下、定时器溢出、串口接收到数据等。硬件中断又可分为可屏蔽中断和不可屏蔽中断。可屏蔽中断可以通过软件设置来允许或禁止,而不可屏蔽中断通常用于处理紧急事件,不能被软件屏蔽。
  • 软件中断:由软件指令触发的中断,通常用于系统调用、异常处理等。软件中断是程序主动发起的,用于实现特定的功能。

2.3 中断处理流程

中断处理的基本流程包括以下几个步骤:

  1. 中断请求:外部或内部设备向 CPU 发送中断请求信号。
  2. 中断响应:CPU 检测到中断请求后,暂停当前程序的执行,保存现场信息(如寄存器值),然后跳转到相应的中断服务程序入口地址。
  3. 中断服务程序执行:CPU 执行中断服务程序,处理中断事件。
  4. 恢复现场:中断服务程序执行完毕后,恢复之前保存的现场信息,使 CPU 能够继续执行被中断的程序。
  5. 返回主程序:CPU 返回到原来被中断的程序继续执行。

三、STM32 的中断机制

3.1 STM32 中断控制器

STM32 系列微控制器采用了嵌套向量中断控制器(NVIC)来管理中断。NVIC 具有以下特点:

  • 支持多个中断源:STM32 不同型号的芯片支持的中断源数量不同,一般在几十个到上百个之间。
  • 中断优先级管理:NVIC 支持中断优先级分组,每个中断源可以设置不同的抢占优先级和子优先级。抢占优先级高的中断可以打断抢占优先级低的中断服务程序,而子优先级用于在抢占优先级相同的情况下确定中断的执行顺序。
  • 中断嵌套:支持中断嵌套功能,即高优先级的中断可以打断低优先级的中断服务程序,提高了系统的实时响应能力。

3.2 STM32 中断优先级分组

STM32 的 NVIC 支持多种中断优先级分组方式,通过设置 AIRCR 寄存器的 PRIGROUP 位来选择不同的分组方式。不同的分组方式将抢占优先级和子优先级的位数进行了不同的分配,例如:

  • 分组 0:0 位抢占优先级,4 位子优先级。
  • 分组 1:1 位抢占优先级,3 位子优先级。
  • 分组 2:2 位抢占优先级,2 位子优先级。
  • 分组 3:3 位抢占优先级,1 位子优先级。
  • 分组 4:4 位抢占优先级,0 位子优先级。

3.3 STM32 中断处理流程

在 STM32 中,中断处理的基本流程如下:

  1. 中断请求:外部或内部设备产生中断请求信号,通过 GPIO 引脚或内部总线发送到 NVIC。
  2. NVIC 处理:NVIC 检测到中断请求后,根据中断优先级分组和中断源的优先级设置,判断是否响应该中断请求。如果响应,则将中断请求挂起,并通知 CPU。
  3. CPU 响应:CPU 检测到 NVIC 的中断通知后,暂停当前程序的执行,保存现场信息(如寄存器值),然后跳转到相应的中断向量表中查找中断服务程序的入口地址。
  4. 中断服务程序执行:CPU 执行中断服务程序,处理中断事件。
  5. 恢复现场:中断服务程序执行完毕后,恢复之前保存的现场信息,使 CPU 能够继续执行被中断的程序。
  6. 返回主程序:CPU 返回到原来被中断的程序继续执行。

四、FreeRTOS 对中断的处理方式

4.1 FreeRTOS 中断管理的基本原则

FreeRTOS 是一个实时操作系统,需要保证系统的实时性和任务调度的正确性。在处理中断时,FreeRTOS 遵循以下基本原则:

  • 中断服务程序应尽量短小:中断服务程序的执行时间应尽量短,避免长时间占用 CPU 资源,影响其他任务的执行。
  • 中断服务程序中避免调用阻塞函数:在中断服务程序中应避免调用 FreeRTOS 提供的阻塞函数,如 vTaskDelay()xQueueReceive() 等,因为这些函数可能会导致任务调度,而中断服务程序中不允许进行任务调度。
  • 使用中断安全的 API 函数:在中断服务程序中应使用 FreeRTOS 提供的中断安全的 API 函数,如 xSemaphoreGiveFromISR()xQueueSendFromISR() 等,这些函数可以在中断服务程序中安全地调用。

4.2 FreeRTOS 中断优先级配置

FreeRTOS 对中断优先级有一定的要求,需要将中断优先级分为两类:

  • 可管理的中断优先级:这些中断优先级低于 configMAX_SYSCALL_INTERRUPT_PRIORITY,FreeRTOS 可以对这些中断进行管理,在中断服务程序中可以安全地调用 FreeRTOS 提供的中断安全的 API 函数。
  • 不可管理的中断优先级:这些中断优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY,FreeRTOS 无法对这些中断进行管理,在中断服务程序中不允许调用 FreeRTOS 提供的 API 函数。

4.3 FreeRTOS 中断服务程序的编写

在 FreeRTOS 中,编写中断服务程序时需要注意以下几点:

  1. 保存现场信息:在中断服务程序开始时,需要保存现场信息,如寄存器值,以便在中断服务程序执行完毕后恢复现场。
  2. 处理中断事件:根据中断源的类型,处理相应的中断事件,如读取按键状态、处理定时器溢出等。
  3. 使用中断安全的 API 函数:如果需要在中断服务程序中与 FreeRTOS 任务进行通信,可以使用 FreeRTOS 提供的中断安全的 API 函数,如 xSemaphoreGiveFromISR()xQueueSendFromISR() 等。
  4. 恢复现场信息:在中断服务程序执行完毕后,恢复之前保存的现场信息,使 CPU 能够继续执行被中断的程序。

五、基于 STM32 HAL 库与 FreeRTOS 的中断管理实现

5.1 工程搭建

首先,需要使用 STM32CubeMX 工具创建一个基于 STM32 HAL 库和 FreeRTOS 的工程。具体步骤如下:

  1. 打开 STM32CubeMX,选择对应的 STM32 芯片型号。
  2. 配置系统时钟、GPIO 引脚、定时器等外设。
  3. 在 “Middleware” 选项卡中选择 FreeRTOS,配置 FreeRTOS 的相关参数,如任务栈大小、任务优先级等。
  4. 配置中断优先级分组,确保将中断优先级分为可管理的中断优先级和不可管理的中断优先级。
  5. 生成代码,并选择合适的 IDE 进行开发。

5.2 中断初始化

在生成的代码中,需要对中断进行初始化。以下是一个简单的示例,初始化一个外部中断:

#include "stm32xxxx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

// 定义一个信号量句柄
SemaphoreHandle_t xSemaphore;

// 外部中断服务函数
void EXTIx_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    // 清除中断标志位
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_x);

    // 释放信号量
    xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);

    // 如果有更高优先级的任务被唤醒,则进行任务切换
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

// 初始化外部中断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_x)
    {
        // 处理外部中断事件
    }
}

// 任务函数
void vTaskFunction(void *pvParameters)
{
    for (;;)
    {
        // 等待信号量
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdPASS)
        {
            // 处理信号量事件
        }
    }
}

// 主函数
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();

    // 创建信号量
    xSemaphore = xSemaphoreCreateBinary();
    if (xSemaphore != NULL)
    {
        // 初始化信号量为不可用状态
        xSemaphoreTake(xSemaphore, 0);
    }

    // 创建任务
    xTaskCreate(vTaskFunction, "Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

    // 启动调度器
    vTaskStartScheduler();

    while (1)
    {
        // 不会执行到这里
    }
}

5.3 中断服务程序与任务通信

在中断服务程序中,可以使用 FreeRTOS 提供的中断安全的 API 函数与任务进行通信。例如,使用信号量来通知任务有中断事件发生:

// 中断服务程序
void EXTIx_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    // 清除中断标志位
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_x);

    // 释放信号量
    xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);

    // 如果有更高优先级的任务被唤醒,则进行任务切换
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

// 任务函数
void vTaskFunction(void *pvParameters)
{
    for (;;)
    {
        // 等待信号量
        if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdPASS)
        {
            // 处理信号量事件
        }
    }
}

5.4 中断优先级管理

在使用 STM32 HAL 库和 FreeRTOS 时,需要合理配置中断优先级。将中断优先级分为可管理的中断优先级和不可管理的中断优先级,确保在可管理的中断服务程序中可以安全地调用 FreeRTOS 提供的中断安全的 API 函数。以下是一个配置中断优先级的示例:

// 配置中断优先级分组
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

// 配置外部中断优先级
HAL_NVIC_SetPriority(EXTIx_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY - 1, 0);
HAL_NVIC_EnableIRQ(EXTIx_IRQn);

六、中断管理的常见问题及解决方法

6.1 中断服务程序执行时间过长

如果中断服务程序执行时间过长,会影响系统的实时性和任务调度的正确性。解决方法是尽量缩短中断服务程序的执行时间,将一些复杂的处理任务放到任务中去执行。例如,可以在中断服务程序中设置一个标志位,然后在任务中检查该标志位并进行相应的处理。

6.2 中断服务程序中调用阻塞函数

在中断服务程序中调用阻塞函数会导致任务调度,而中断服务程序中不允许进行任务调度。解决方法是使用 FreeRTOS 提供的中断安全的 API 函数,如 xSemaphoreGiveFromISR()xQueueSendFromISR() 等,这些函数可以在中断服务程序中安全地调用。

6.3 中断优先级配置错误

如果中断优先级配置错误,可能会导致中断嵌套异常或无法正确处理中断事件。解决方法是仔细配置中断优先级分组和每个中断源的优先级,确保将中断优先级分为可管理的中断优先级和不可管理的中断优先级,并根据实际需求设置合适的优先级。

七、总结

本文详细介绍了基于 STM32 HAL 库与 FreeRTOS 的中断管理。首先介绍了中断的基本概念、STM32 的中断机制和 FreeRTOS 对中断的处理方式。然后,通过实际的代码示例,展示了如何在 STM32 HAL 库和 FreeRTOS 环境下进行中断初始化、中断服务程序与任务通信以及中断优先级管理。最后,讨论了中断管理中常见的问题及解决方法。通过合理的中断管理,可以提高系统的实时性和稳定性,确保系统能够及时响应外部事件。在实际开发中,需要根据具体的应用场景和需求,合理配置中断优先级,编写高效的中断服务程序,以充分发挥 STM32 和 FreeRTOS 的优势。

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

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

相关文章

STM32——新建工程并使用寄存器以及库函数进行点灯

本文是根据江协科技提供的教学视频所写,旨在便于日后复习,同时供学习嵌入式的朋友们参考,文中涉及到的所有资料也均来源于江协科技(资料下载)。 新建工程并使用寄存器以及库函数进行点灯操作 新建工程步骤1.建立工程2.…

java集合框架day1————集合体系介绍

在进入正文之前&#xff0c;我们先来思考一下之前学过的数组有什么缺点&#xff1f; <1>长度开始时必须指定&#xff0c;而且一旦指定&#xff0c;不能更改 <2>保存的必须为同一类型的元素 <3>使用数组进行增加/删除元素的代码比较麻烦 为了方便读者理解&…

百度热力图数据获取,原理,处理及论文应用18

目录 0、数据简介0、示例数据1、百度热力图数据日期如何选择1.1、其他实验数据的时间1.2、看日历天气 2、百度热力图几天够研究&#xff1f;部分文章统计3、数据原理3.1 Bd09mc即百度墨卡托投影坐标系200单位的距离是可以自己设置的吗&#xff1f;3.2 csv文件字段说明3.3 ** 这…

【身份证扫描件识别表格】如何识别大量身份证扫描件将内容导出保存到Excel表格,一次性处理多张身份证图片导出Excel表格,基于WPF和腾讯云的实现方案

基于WPF和腾讯云的身份证扫描件批量处理方案 适用场景 本方案适用于需要批量处理大量身份证扫描件的场景,例如: 企业人事部门批量录入新员工身份信息银行或金融机构办理批量开户业务教育机构收集学生身份信息政府部门进行人口信息统计酒店、医院等需要实名登记的场所这些场景…

基于语义网络表示的不确定性推理

前文我们已经了解了: 1.不确定与非单调推理的基本概念:不确定与非单调推理的基本概念-CSDN博客 2.不确定与非单调推理的概率方法:不确定与非单调推理的概率方法-CSDN博客 3.不确定与非单调推理的可信度方法:不确定与非单调推理的可信度方法-CSDN博客 4.不确定与非单调推…

ICMAN防水触摸芯片 - 复杂环境下精准交互,提升触控体验

▍核心优势 ◆ 超强抗干扰能力 ◆ 工业级设计&#xff0c;一致性和稳定性好 ▍提供场景化解决方案 【智能厨电矩阵】抽油烟机档位调节 | 电磁炉火力触控 | 洗碗机模式切换 【卫浴设备方案】淋浴房雾化玻璃控制 | 智能马桶触控面板 | 浴缸水位感应 【工业控制应用】仪器仪…

【java实现+4种变体完整例子】排序算法中【希尔排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是希尔排序的详细解析&#xff0c;包含基础实现、常见变体的完整代码示例&#xff0c;以及各变体的对比表格&#xff1a; 一、希尔排序基础实现 原理 希尔排序是插入排序的改进版本&#xff0c;通过分步缩小增量间隔&#xff0c;将数组分成多个子序列进行插入排序&#…

matlab 处理海洋数据并画图的工具包--ocean_data_tools

matlab 处理海洋数据并画图的工具包–ocean_data_tools matlab 处理海洋数据并画图的工具包–ocean_data_tools ocean_data_tools 简化了提取、格式化和可视化免费可用的海洋学数据的过程。虽然可以在线访问大量海洋学数据&#xff0c;但由于获取这些数据并将其格式化为可用数据…

MCP:AI时代的“万能插座”,开启大模型无限可能

摘要&#xff1a;Model Context Protocol&#xff08;MCP&#xff09;由Anthropic在2024年底开源&#xff0c;旨在统一大模型与外部工具、数据源的通信标准。采用客户端-服务器架构&#xff0c;基于JSON-RPC 2.0协议&#xff0c;支持stdio、SSE、Streamable HTTP等多种通信方式…

静态网页的开发

文章目录 基于 idea 开发静态网页添加web框架前端配置服务器并启动服务资源名字不是 index 静态网页 流转 基于 idea 开发静态网页 添加web框架 方法1 方法2 前端 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&quo…

【CPU】结合RISC-V CPU架构回答中断系统的7个问题(个人草稿)

结合RISC-V CPU架构对中断系统七个关键问题的详细解析&#xff0c;按照由浅入深的结构进行说明&#xff1a; 一、中断请求机制&#xff08;问题①&#xff09; 硬件基础&#xff1a; RISC-V通过CLINT&#xff08;Core Local Interrupter&#xff09;和PLIC&#xff08;Platfor…

uCOS3实时操作系统(任务切换和任务API函数)

文章目录 任务切换任务API函数 任务切换 C/OS-III 将 PendSV 的中断优先级配置为最低的中断优先级&#xff0c;这么一来&#xff0c; PendSV 异常的中断服务函数就会在其他所有中断处理完成后才被执行。C/OS-III 就是将任务切换的过程放到 PendSV 异常的中断服务函数中处理的。…

科学养生指南:解锁健康生活新方式

在快节奏的现代生活中&#xff0c;健康养生已成为人们关注的焦点。科学合理的养生方式&#xff0c;能帮助我们增强体质、预防疾病&#xff0c;享受更优质的生活。​ 饮食是健康养生的基石。遵循 “均衡饮食” 原则&#xff0c;每日饮食需包含谷类、蔬菜水果、优质蛋白质和健康…

第十四届蓝桥杯 2023 C/C++组 有奖问答

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; 核心思路&#xff1a; 思路详解&#xff1a; 代码&#xff1a; 代码详解&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 蓝桥云课 有奖问答 思路&…

transformer注意力机制

单头注意力机制 import torch import torch.nn.functional as Fdef scaled_dot_product_attention(Q, K, V):# Q: (batch_size, seq_len, d_k)# K: (batch_size, seq_len, d_k)# V: (batch_size, seq_len, d_v)batch_size: 一次输入的句子数。 seq_len: 每个句子的词数。 d_mo…

QT 5.15 程序打包

说明&#xff1a; windeployqt 是 Qt 提供的一个工具&#xff0c;用于自动收集并复制运行 Qt 应用程序所需的动态链接库&#xff08;.dll 文件&#xff09;及其他资源&#xff08;如插件、QML 模块等&#xff09;到可执行文件所在的目录。这样你就可以将应用程序和这些依赖项一…

【路由交换方向IE认证】BGP选路原则之AS-Path属性

文章目录 一、路由器BGP路由的处理过程控制平面和转发平面选路工具 二、BGP的选路顺序选路的前提选路顺序 三、AS-Path属性选路原则AS-Path属性特性AS-Path管进还是管出呢&#xff1f;使用AS-Path对进本AS的路由进行选路验证AS-Path不接收带本AS号的路由 四、BGP邻居建立配置 一…

Linux系统下docker 安装 redis

docker安装最新版的redis 一、docker拉取最新版redis镜像 拉取镜像若没有指定版本&#xff0c;代表拉取最新版本 二、查询redis镜像 三、挂载配置文件 在docker容器内修改redis配置文件不方便&#xff0c;所以挂载配置文件&#xff0c;这样可以在外边修改redis配置 3.1 创建…

深度学习框架PyTorch——从入门到精通(3.3)YouTube系列——自动求导基础

这部分是 PyTorch介绍——YouTube系列的内容&#xff0c;每一节都对应一个youtube视频。&#xff08;可能跟之前的有一定的重复&#xff09; 我们需要Autograd做什么&#xff1f;一个简单示例训练中的自动求导开启和关闭自动求导自动求导与原地操作 自动求导分析器高级主题&…

【基础算法】二分算法详解

🎯 前言:二分不是找某个数,而是找一个满足条件的位置/值 所以最关键的是:找到单调性,写好 check() 函数,剩下交给模板! 什么是二分算法 二分算法是一种在有序区间中查找答案的方法,时间复杂度:O(log n)。核心思想是: 每次把搜索区间分成两半,只保留可能存在答案的…