【嵌入式之中断】

Cortex-M4集成了嵌套式矢量型中断控制器(Nested Vectored Interrupt Controller (NVIC))来实现高效的异常和中断处理。NVIC实现了低延迟的异常和中断处理,以及电源管理控制。它和内核是紧密耦合的。

凡是打断程序顺序执行的事件都称为异常(exception),比如HardFault,外部中断等。所以中断​也可以说是异常的一种。

一、中断基础知识

程序顺序执行,遇到中断使能,跳转执行中断函数。

在这里插入图片描述

1、中断分类(中断源)

(1)外部中断

  • 按键
  • 外部通讯中断

(2)内部中断

  • CPU内部中断,如重置,遇到突发事件处理的中断
  • 相关外设中断

注意:具体哪些端口可以中断需要看具体数据手册

2、中断的作用

全局中断使能位控制着“所有”中断,它如果关闭,则会屏蔽其它中断。

在使用过程中,常关闭全局中断,以防止其他中断的干扰。
当GPIO模拟某个时序时,在GPIO传输数据过程中,若被某个中断干扰,会导致时序不准确问题,通常的做法是关闭全局中断,数据传输完成后打开全局中断
同样在RTOS中对全局变量的保护基本上都使用了全局中断。

__disable_irq();
//数据传输
__enable_irq();

但关中断时间较长,导致串口接收FIFO溢出,数据丢失。

所以需要注意:全局中断关闭时间都不是太长,且严禁出现长时间关中断,严禁出现关中断时间不可控,这样会影响实时性。
时间不可控比如:长链表操作、环形缓冲区操作、循环操作等。

3、编程基本配置

(1)配置所需中断功能相关寄存器,开启功能中断以及全局中断

  • 中断源
  • 中断优先级
  • 中断使能

(2)编写中断处理子程(ISR)(CPU硬件自动调用)

  • 中断触发源判断(中断触发,相关标志位置1)
  • 中断标志位清零

(3)在中断函数中处理相关任务

二、中断优先级

异常包括系统异常(异常编号1-15)和外部中断(异常编号16往上)。HardFault(-1)这三个异常优先级都是负数且固定不变,优先级高于其他异常,除了这三个异常之外其他异常优先级都是可以编程的。

1、中断抢占

每个中断优先级都包含两个部分,一部分称作抢占优先级,另一部分称作子优先级。

(1)抢占优先级(中断嵌套)
在执行低中断优先级中断函数时,高优先级中断到来,低优先级中断被打断,执行高优先级中断,高优先级中断执行完后回到低优先级中断继续执行。

在这里插入图片描述

具有高抢占优先级的中断能够抢占低抢占优先级的中断,也称之为中断嵌套。

(2)抢占优先级相同,子优先级不同

当两个中断的抢占优先级设置为相同级别时,这两个中断不会出现中断嵌套。

如果其中一个中断正在执行时,另外一个中断到来,后来的中断将会等到前一个中断执行完才能执行。如果这两个中断都处在等待响应状态,执行条件到来时,首先响应子优先级高的中断。

(3)抢占优先级相同,子优先级也相同

这种情况也不会出现中断嵌套,内核将会按照向量表中的排位选择,优先执行靠前的异常。

2、优先级分组

在Cortex-M4内核中,优先级分组是一个用于配置中断优先级的重要机制。它决定了在8位的中断优先级字段中,多少位用于表示抢占优先级,多少位用于表示子优先级。

Cortex-M4内核允许通过配置优先级分组寄存器(例如,ARM Cortex-M3中的AIRCR寄存器)来设置不同的优先级分组方案。优先级分组寄存器通常包含几位用于配置优先级的字段。通过设置这些位,可以选择不同的分组方式,从而决定抢占优先级和子优先级的位数分配。

具体的分组方式可以有多种,例如:

  • 分组0:所有8位都用于表示子优先级,没有抢占优先级。
  • 分组1:最高1位用于表示抢占优先级,最低的7位用于表示子优先级。
  • 分组2:最高2位用于表示抢占优先级,最低的6位用于表示子优先级。
  • 分组3:最高3位用于表示抢占优先级,最低的5位用于表示子优先级。
  • 分组4:所有8位都用于表示抢占优先级,没有子优先级。

不同的分组方式可以根据具体的应用需求来选择。抢占优先级用于决定在中断发生时哪个中断应该被优先处理,而子优先级则在抢占优先级相同的情况下用于进一步区分中断的优先级。

示例:

nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
nvic_irq_enable((uint8)USBFS_IRQn,2U,0U);
nvic_irq_enable((uint8)USBFS_WKUP_IRQn,1U,0U);

三、中断配置

在使用ARM Cortex-M系列微控制器时,中断处理是一个非常重要的部分。在Cortex-M4(或类似的Cortex-M系列)中配置中断示例如下。(实际的实现细节可能会根据您使用的具体硬件和库有所不同。)

1、选择中断源:
首先确定要使用的中断源。这可能是外部中断、定时器中断或其他内部中断。

2、配置中断优先级:
Cortex-M4支持中断优先级。根据应用的需求为每个中断分配优先级

3、配置NVIC (Nested Vectored Interrupt Controller):
NVIC是Cortex-M系列中的中断控制器。需配置NVIC以启用和配置所需的中断。

4、编写中断服务程序 (ISR):
为每个中断编写中断服务程序。当中断发生时,这些程序将被执行。

以下示例基于ARM Cortex-M4 内核的 GD32 微控制器。

示例1:如何配置一个外部中断(EXTI)(例如,来自某个GPIO引脚的中断)

#include "gd32f3xx.h"  //确保已经包含了必要的头文件
  
// 假设您已经有一个系统时钟初始化的函数  
void SystemClock_Config(void);  
  
// EXTI0 的中断服务程序  
void EXTI0_IRQHandler(void)  
{  
    if (RESET != exti_interrupt_flag_get(EXTI_0)) // 检查 EXTI0 的中断标志  
    {  
        // 清除中断标志  
        exti_interrupt_flag_clear(EXTI_0);  
          
        // 在这里处理中断逻辑  
    }  
}  
  
int main(void)  
{  
    // 系统时钟初始化  
    SystemClock_Config();  
      
    // GPIO 端口时钟使能  
    rcu_periph_clock_enable(RCU_GPIOA);  
      
    // 配置 GPIOA 的第 0 号引脚为中断模式  
    gpio_mode_set(GPIOA, GPIO_MODE_IT, GPIO_PUPD_NONE, GPIO_PIN_0);  
    gpio_interrupt_enable(GPIOA, GPIO_INT_FALLING); // 下降沿触发  
      
    // 配置 EXTI 的中断线 0  
    exti_interrupt_flag_clear(EXTI_0); // 清除可能存在的挂起中断  
    exti_line_config(EXTI_SOURCE_GPIOA, EXTI_LINE_0);  
    exti_mode_set(EXTI_MODE_INTERRUPT, EXTI_LINE_0);  
    exti_trigger_type_set(EXTI_TRIGGER_FALLING, EXTI_LINE_0); // 下降沿触发  
      
    // 配置 NVIC  
    nvic_irq_enable(EXTI0_IRQn, 0, 0); // 使能 EXTI0 的中断,并设置优先级  
      
    while (1)  
    {  
        // 主循环代码  
    }  
}

四、扩展示例

配置内部中断(如定时器中断)

配置相关步骤为:

1、初始化定时器:
首先,需要初始化定时器,并设置其参数,如预分频值、自动重载值等,以决定定时器的计数周期和中断触发频率。

2、配置定时器中断:
启用定时器的中断功能,并设置中断触发条件(如溢出中断、比较匹配中断等)。

3、配置NVIC:
使用嵌套向量中断控制器(NVIC)来配置中断的优先级和使能中断。

4、编写中断服务程序(ISR):
编写一个中断服务程序,该程序将在定时器中断发生时被执行。

#include "gd32f3xx.h"  
  
// 假设您已经有一个系统时钟初始化的函数  
void SystemClock_Config(void);  
  
// 定时器中断服务程序  
void TIMERx_IRQHandler(void) // 这里的x代表具体的定时器编号,如TIMER2  
{  
    if (RESET != timer_interrupt_flag_get(TIMERx, TIMER_INT_FLAG_UP)) // 检查定时器的中断标志  
    {  
        // 清除中断标志  
        timer_interrupt_flag_clear(TIMERx, TIMER_INT_FLAG_UP);  
          
        // 在这里处理中断逻辑  
    }  
}  
  
int main(void)  
{  
    // 系统时钟初始化  
    SystemClock_Config();  
      
    // 定时器时钟使能  
    rcu_periph_clock_enable(RCU_TIMERx); // 这里的x代表具体的定时器编号,如TIMER2  
      
    // 定时器初始化结构体定义和初始化  
    timer_parameter_struct timer_initpara;  
    timer_initpara.prescaler         = 7199;  // 预分频值  
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;  
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;  
    timer_initpara.period            = 9999;  // 自动重载值  
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;  
    timer_initpara.repetitioncounter = 0;  
    timer_init(TIMERx, &timer_initpara); // 初始化定时器  
      
    // 启动定时器  
    timer_enable(TIMERx);  
      
    // 配置定时器中断  
    timer_interrupt_enable(TIMERx, TIMER_INT_FLAG_UP); // 使能定时器中断  
      
    // 配置NVIC  
    nvic_irq_enable(TIMERx_IRQn, 0, 0); // 使能定时器的中断,并设置优先级  
      
    while (1)  
    {  
        // 主循环代码  
    }  
}

以上示例中:首先初始化了系统时钟,然后使能了定时器的时钟。接着,定义了定时器的初始化参数,并调用timer_init函数来初始化定时器。之后,我们启动了定时器,并配置了定时器中断。最后,使用nvic_irq_enable函数来使能定时器的中断,并设置了其优先级。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Gitlab: Python项目CI/CD实践

目录 1. 说明 2. 准备工作 2.1 服务器 2.2 开发机hosts文件 2.3 项目 3. 步骤过程 3.1 建仓Fastapi T1 3.2 开发机测试构建与推送 ​编辑 3.3 在工作站添加gitlab-runner 3.4 提交代码,查看Pipelines结果 3.5 观察部署情况 4. 参考 1. 说明 分别以一个…

线程互斥及基于线程锁的抢票程序

我们实现一个简单的多线程抢票程序。 #include<iostream> #include<thread> #include<unistd.h> #include<functional> #include<vector> using namespace std; template<class T> using func_tfunction<void(T)>;//返回值为void,…

leetcode刷题(python)——(四)

01.02.03 练习题目&#xff08;第 04 天&#xff09; 1. 0048. 旋转图像 1.1 题目大意 描述&#xff1a;给定一个 n n n \times n nn 大小的二维矩阵&#xff08;代表图像&#xff09; m a t r i x matrix matrix。 要求&#xff1a;将二维矩阵 m a t r i x matrix matr…

点云的投影------PCL

点云的投影 /// <summary> /// 参数化模型投影点云 /// </summary> /// <param name"cloud">点云</param> /// <param name"x">投影平面x面的系数</param> /// <param name"y"></param> /// &…

【Qt-Qt Creator使用技巧】

工具-Qt Creator ■ 使用技巧■ 定义触发片段■ Qt Creator 行编辑■ 代码注释■ 代码补全■ 快速给函数添加定义■ 创建书签■ 同步列输入■ 局部替换■ 源代码阅读■ 源码调试■ 使用技巧 ■ 定义触发片段 ■ Qt Creator 行编辑 shift + alt + up / down来获得多个游标。 …

第二部分 Python提高—GUI图形用户界面编程(三)

简单组件学习 Radiobutton 单选按钮、Checkbutton 复选按钮和canvas 画布 文章目录 Radiobutton 单选按钮Checkbutton 复选按钮canvas 画布 Radiobutton 单选按钮 Radiobutton 控件用于选择同一组单选按钮中的一个。Radiobutton 可以显示文本&#xff0c;也可以显示图像。 f…

CUDA编程---线程束洗牌指令

从Kepler系列的GPU&#xff08;计算能力为3.0或更高&#xff09;开始&#xff0c;洗牌指令&#xff08;shuffle instruction&#xff09;作为一种机制被加入其中&#xff0c;只要两个线程在相同的线程束中&#xff0c;那么就允许这两个线程直接读取另一个线程的寄存器。 洗牌指…

程序员购车指南

哈喽大家好&#xff0c;我是咸鱼。 爱车可以说是大部分男人的天性&#xff0c;而我对汽车的热情却远不及对手表的钟爱&#xff08;痴迷劳力士&#xff09;。以至于我的朋友掏出车钥匙指着上面的苹果树标志跟我介绍奔驰 AMG 系列的强劲性能和马力时&#xff0c;我只能尽量假装自…

C++的继承

目录 前言 继承的概念和定义 访问权限表 基类和派生类对象的赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 复杂的菱形继承和菱形虚拟继承 菱形虚拟继承 观察内存 注意事项&#xff1a;对象在内存中的存储顺序是按声明的顺序存储的 …

Python分析之3 种空间插值方法

插值是一个非常常见的数学概念,不仅数据科学家使用它,而且各个领域的人们也使用它。然而,在处理地理空间数据时,插值变得更加复杂,因为您需要基于几个通常稀疏的观测值创建代表性网格。 在深入研究地理空间部分之前,让我们简要回顾一下线性插值。 为了演示的目的,我将使…

ansible模块实战-部署rsync服务端

目录 1、根据部署流程所用到的命令找出模块 2.实战部署 2.1 服务部署&#xff1a;yum 安装 2.2 准备好rsync服务的配置文件 &#xff0c;并将配置文件通过copy模块分发给192.168.81.136这台受控主机 2.3 创建虚拟机用户 2.4 创建密码文件和改权限 2.5 模块对应目录&…

2024百度网盘超级会员怎么购买才能最省钱且不会踩坑?我来给你分享一下

不知道百度网盘超级会员怎么买最便宜&#xff0c;我来告诉你通过百度网盘最新优惠活动最低仅需188元/年。下面就和大家详细分享百度网盘会员最便宜的购买方法&#xff0c;值得你收藏和点赞&#xff01;当我们需要选择网盘时&#xff0c;大部分同学都会选择百度网盘&#xff0c;…

2024年五一杯数学建模B题思路分析

文章目录 1 赛题思路2 比赛日期和时间3 组织机构4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

python聊天室

python聊天室 文章目录 python聊天室chat_serverchat_client使用方式1.局域网聊天2.公网聊天 下面是一个简单的示例&#xff0c;包含了chat_client.py和chat_server.py的代码。 chat_server chat_server.py监听指定的端口&#xff0c;并接收来自客户端的消息&#xff0c;并将消…

蓝桥杯2024年第十五届省赛真题-好数

思路&#xff1a;枚举所有数&#xff0c;每个数分别判断。代码时间复杂度虽然是n^2&#xff0c;但是由于判断的数长度最长是7位&#xff0c;用字符串处理最多只循环7次&#xff0c;所以最大时间复杂度小 7*10的七次方&#xff0c;不会超时。库中的to_string时间复杂度太大&…

自己的事情自己做:使用 Python Turtle 绘制 Python Logo

以下代码中&#xff0c;将向你展示一个有趣的程序&#xff0c;如何使用 Python Turtle 中绘制 Python Logo。Python 翻译成汉语是蟒蛇的意思&#xff0c;Python 的 Logo 也是两条缠绕在一起的蟒蛇。 import turtlepen turtle.Turtle() turtle.bgcolor("black") pe…

元宇宙VR虚拟线上展馆满足企业快速布展的需要

想要拥有一个VR线上虚拟展馆&#xff0c;展现您的城市风采或企业特色吗? 相比实体展馆搭建&#xff0c;VR线上虚拟展馆投入资金少&#xff0c;回报周期短&#xff0c;只需几个月的时间&#xff0c;您就能开始资金回笼。那么一个VR线上虚拟展馆多少钱呢? 深圳VR公司华锐视点基…

LeetCode701:二叉搜索树中的插入操作

题目描述 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 代码 递归法 class Solution { public…

5GNR刷题

5G帧结构 5G NR帧结构的基本时间单位是( C ) A) subframe B) slot C) Tc D) symbol 5G无线帧长是多少ms&#xff08;B&#xff09; A) 5 B) 10 C) 20 D) 40 下面哪种子载波间隔是中国移动白皮书中规定必选(B ) A) 15KHz B) 30KHz C) 60KHz D) 120KHz 5G参数集包含哪…

【学习笔记二十】EWM TU运输单元业务概述及后台配置

一、EWM TU运输单元业务流程概述 TU是指车辆和运输单元在货场中,移动车辆或运输单元。 车辆是特定运输方式的专用化工具,车辆可以包含一个或多个运输单元,并代表运输车辆的实际实体。 运输单元是用于运输货物的车辆的最小可装载单位,运输单元可以是车辆的固定部分。 …
最新文章