STM32HAL库-中断篇

news2025/1/24 8:46:48

中断

中断简介

中断是一种事件处理机制,可以暂停主程序的运行,转而处理特定事件程序。

中断的作用和意义:

实时控制  在确定事件内对响应事件做出相应

故障处理  检测到故障需要第一时间处理

数据传输  如串口通信,不确定数据何时会来

意义:高效处理紧急程序,不会一直占用cpu资源

GPIO外部中断简图

信号从外部进来,首先遇到的外设是GPIO

然后会走到SYSCFG系统配置控制器,将GPIOXy映射到EXTIy

SYSCFG系统配置控制器是一种常见外设,其作用是配置系统的各种控制和配置寄存器,用于管理系统的各种配置参数和功能。

接着信号进入到EXTI来判断是否触发响应

触发EXTI响应后会进入NVIC判断响应优先级

最后优先级高的先进入CPU去处理中断

NVIC

NVIC基本概念

Nested vectored interrupt controlelr,嵌套向量中断控制器,属于内核的一部分(M3/4/7)

NVIC支持256个中断(16个内核+240外部),支持256个优先级,允许裁剪

中断向量表

中断向量表是一块固定的内存,4字节对齐,存放各个中断对应的中断服务函数首地址

中断向量表定义在启动文件,也就是.s文件里,当发生中断,CPU会自动执行对应的中断服务函数

 .s文件中__Vectors标注的代码块就是中断向量表开始的地方

DCD表示4字节对齐

NVIC相关寄存器介绍

中断使能寄存器                          ISER,Interrupt Set-Enable Register

中断除能寄存器                          ICER,Interrupt Clean-Enable Register

应用程序中断及复位控制寄存器 AIRCR,Application Interrupt and Reset Controller Register

中断优先级寄存器                       IPR,Interrupt Priority Register

 NVIC还有中断挂起、解挂、激活标志等不常用的功能,此处不做介绍

NVIC工作原理

经过EXTI判断后触发响应的外部中断会来到中断使能寄存器(ISER)中断失能寄存器(ICER),

再走到中断优先级寄存器(IPR),经过优先级判断后交由CPU处理

内核中断直接到达SHPR

SHPR,System Handler Priority Registers 系统处理器优先级寄存器

STM32中断优先级基本概念

1、抢占优先级(pre):高抢占优先级可以打断正在执行的低抢占优先级的中断

2、响应优先级(sub):当抢占优先级相同时,响应优先级高的先执行,但是不能互相打断

3、自然优先级:抢占和响应都相同的话,自然优先级高的先执行。自然优先级看向量表上到下

STM32中断优先级分组

NVIC中通过AIRCR的[10:8]位,可支持8种优先级分组

STM32只用到了其中5个。

如果优先级分组为0,

则IPR的[7:4]位全部用于响应优先级配置,也就是0个抢占优先级,2^4=16个响应优先级

如果分组为1,

则IPR的[7]位用于抢占优先级,[6,4]用于分配响应优先级,也就是2个抢占优先级,8个响应优先级

以此推类。

 一个工程中一般只设置一次优先级分组。设置多次会以最后一次为准。

STM32 NVIC的使用

使用流程:

1、设置中断分组     AIRCR[10:8],HAL_NVIC_SetPriorityGrouping

2、设置中断优先级 IPRx bit[7:4],HAL_NVIC_SetPriority  //STM32只用了IPR的高四位

3、使能中断            ISERx,HAL_NVIC_EnableIRQ

 /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);    //设置中断优先级分组为2
 /****************************************************************/
  HAL_NVIC_SetPriority(KEY0_INT_IRQn, 0, 2);               /* 抢占0,子优先级2 */
  HAL_NVIC_EnableIRQ(KEY0_INT_IRQn);                       /* 使能中断线3 */
//设置中断优先级分组源代码
__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
  uint32_t reg_value;
  uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL);             /* only values 0..7 are used          */

  reg_value  =  SCB->AIRCR;                                                   /* read old register configuration    */
  reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change               */
  reg_value  =  (reg_value                                   |
                ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
                (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos)  );              /* Insert write key and priority group */
  SCB->AIRCR =  reg_value;
}
//设置中断优先级源代码
__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
  if ((int32_t)(IRQn) >= 0)
  {
    NVIC->IP[((uint32_t)IRQn)]               = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
  }
  else
  {
    SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
  }
}

 设置中断优先级源代码中的

NVIC->IP[IRQn] 代表设置外部中断优先级的 IPR 寄存器小知识,IP[0]就是WWG窗口看门口

SCB->SHP[IRQn] 代表设置内核中断优先级的SHPR寄存器

EXTI

EXTI基本概念

External(Extended) interrupt/event Controlelr 外部(扩展)中断事件控制器

如F4系列包含23个产生事件/中断请求的边沿检测器,即总共:23条EXTI线

中断和事件的区别:

中断要进入NVIC,有响应的中断服务函数,需要CPU处理

事件不进入NVIC,仅用于内部硬件自动控制,如:TIM、DMA、ADC

EXTI支持的外部中断/事件请求

EXTI主要特性

F1/F4/F7系列每条EXTI线都可以单独配置:

选择类型(中断或者事件)

触发方式(上升沿、下降沿、双边)

支持软件触发

开启/屏蔽

有挂起状态位

H7系列

由其他外设对EXTI产生的事件可分为可配置事件和直接事件

可配置事件:基本和F1/F4/F7类似

直接时间:固定上升沿触发、不支持软件触发、无挂起状态位(由其他外设提供)

EXTI工作原理(F4)

一个信号从EXTI线输入进来,首先到达 边沿检测线路

接着到达 软硬件触发选择线路

最后到达 中断屏蔽/清除(挂起)线路事件屏蔽线路

边沿检测线路:通过EXTI_RTSR/EXTI_FTSR上升下降触发选择寄存器的配置来决定是否允许信号通过。比如上升下降两个选择寄存器对应位都置1,代表来了上升沿或者下降沿都允许通过

软硬件触发选择:然后信号经过或门,不管是选择软件触发还是硬件触发,只要触发了到左边就是1

中断屏蔽/清除(挂起):之后可以通过与门,也可以通过请求挂起寄存器,如果到达EXTI_PR请求挂起寄存器的信号是1,就会自动让EXTI_PR请求挂起寄存器置 1;如果EXTI_IMR屏蔽掉了,输出的就是0,与门得到的也是0,中断信号就无法到达NVIC也就无法产生中断

事件屏蔽线路:EXTI_EMR事件屏蔽寄存器如果屏蔽了信号,则与门会让信号无法到达脉冲发生器,也就无法使外设产生事件(触发外设功能)

上升/下降沿触发选择寄存器 EXTI_RTSR/EXTI_FTSR(Rising/Falling trigger selection register)

        上升/下降沿触发选择器RTSR为32位,用到了20位,每一位TRx控制一个线x的上升沿中断/事件触发的允许和禁止

软件中断事件寄存器 EXTI_SWIER(Software Interrupt Event Register)

挂起寄存器  EXTI_PR(Pending Register)

       请求挂起寄存器可以挂起/清除中断标志位。32位寄存器,20位有效,如果外部中断线上发生了选择的边沿事件,该位被置1,也就是硬件触发中断,清除时主动往该位写1,或改变边沿触发的极性(上升沿改下降沿)

中断屏蔽寄存器 EXTI_IMR(Interrupt Mask Register)

        IMR事件屏蔽寄存器是32位,只用到了20位,想屏蔽或者开启某条线的中断置1获置0即可

事件屏蔽寄存器 EXTI_EMR(Event Mask Register)

EXTI_RTSR 和 EXTI_FTSR都是32位的,具体多少位有效就看有多少EXTI线,比如F1系列有20根EXTI线那么RTSR和FTSR就是20位有效,F4系列有23根EXTI线就是23位有效

STM32F4的EXTI控制器框图

EXTI和IO的映射关系

SYSCFG简介(F4/F7/H7)

System configuration controller,即系统配置寄存器,用于外部中断映射配置等功能(F1为AFIO模块)

SYSCFG模块的外部中断配置主要使用SYSCFG_EXTICR1~4,配置EXTI中断线0~15对应到哪个具体IO口

SYSCFG_EXTICR1~4 (Configuration Register)

特别注意:配置SYSCFG寄存器之前要使能SYSCFG时钟,方法如下:

__HAL_RCC_SYSCFG_CLK_ENABLE();

EXTI与IO对应关系

EXTI0与Px0对应

当Px0映射到EXTI0时,其他分组的Pin0就不能映射到EXTI0了

可以看到EXTI0与引脚号为0的IO口对应。SYSCFG有SYSCFG_EXTICR1~4共4个外部中断配置寄存器,即EXTI0~EXTI15,EXTIx寄存器的[3:0]位用来选择相同x引脚号的不同分组。以EXTICR0为例,外部中断配置寄存器EXTICR0为32位,高16位保留,低16位拆分为4个EXTI寄存器,控制不同分组外部中断引脚的映射。EXTI0可选择对应A0、B0~I0,EXTI1可选择A1、B1~I1,依次推类

SYSCFG外部中断配置寄存器1

如何使用中断

既然是GPIO外部中断,肯定首先是要使用GPIO的,

1、设置GPIO的输入模式,比如上拉、下拉、浮空

经过GPIO以后又和EXTI有一个映射关系,就需要

2、使用AFIO或SYSCFG配置IO引脚和EXTI线映射

3、之后针对EXTI可以设置中断的屏蔽、打开,上升下降双边沿触发方式

4、经过EXTI后需要使用NVIC来设置中断分组、中断优先级和中断使能

5、最后CPU会按照优先级顺序依次处理中断

需要到达EXTI中断的可以统称为EXTI中断

GPIO中断对应的是EXTI0~15这16根线,而EXTI16 ~23是来自其他外设,如RTC闹钟事件、USB唤醒事件等等,这些EXTI16之后的外部中断不经过SYSCFG直接到达EXTI

不经过EXTI直接到达NVIC的中断统称为外设中断

USART/TIM/SPI等外设中断则不需要经过EXTI,直接由外设自己的寄存器进行中断开启和触发方式选择,可以直接到达NVIC

EXTI的HAL库配置步骤(GPIO外部中断) 

1、使能GPIO时钟                                         __HAL_RCC_GPIOx_CLK_ENABLE

/*******************************************HAL_GPIO_Init()一步到位**********************************/

2、设置GPIO输入模式                                   上/下拉/浮空输入

3、设置AFIO/SYSCFG时钟                           设置AFIO/SYSCFG时钟开启寄存器

4、设置EXTI和IO对应关系                            AFIO_EXTICR/SYSCFG_EXTICR

5、设置EXTI屏蔽,上下沿触发方式              IMR设置EXTI对应通道的屏蔽,、RTSR/FTSR设                                                                             置上升沿/下降沿触发方式

/*********************************************HAL_GPIO_Init()一步到位**********************************/

6、设置NVIC                                                 设置优先级分组、设置优先级、中断使能                                                                                           HAL_NVIC_SetPriorityGrouping

                                                                       HAL_NVIC_EnableIRQ

7、设置中断服务函数                                    编写对应中断服务函数,清中断标志

                                                                       EXTIx_IRQHandler

STM32仅有7个外部中断服务函数,EXTI 0~4有5个中断服务函数,EXTI 9_5共用一个中断服务函数,EXTI 15_10共用一个中断服务函数

通用外设驱动模型(四步法)

HAL库中断回调处理机制介绍

HAL库的中断回调处理异常复杂,知道大概原理即可,按需去看即可

大概流程就是从main()进入到中断服务函数HAL库中断处理公用函数HAL库数据处理回调函数,再依次往上回到上一级函数,最后回到main函数

通过外部中断控制一个灯亮灭

Key按键原理图

首先分析按键IO应该配置为什么模式

KEY_UP外接高电平,连接时应该给到一个上升沿触发,断开的时候是高阻态,高阻态电平不确定,因此为了确保稳定性初始状态应该配置为下拉输入

KEY0、KEY1、KEY2这三个按键是反过来的,按下时输入低电平,会给到一个下降沿触发,因此初始状态应该配置成上拉输入

当外部中断产生之后会调用中断服务函数,中断处理函数会调用中断处理公用函数,处理公用函数会调用数据处理回调函数

通常重写数据处理回调函数处理自己的业务逻辑

#define KEY0_INT_IRQHandler             EXTI3_IRQHandler
#define __HAL_GPIO_EXTI_GET_IT(__EXTI_LINE__) (EXTI->PR & (__EXTI_LINE__))

/**
  * @brief  This function handles EXTI interrupt request.
  * @param  GPIO_Pin Specifies the pins connected EXTI line
  * @retval None
  */
//Pin口引脚与EXTI线由SYSCFG_EXTI1~3的EXTI0~3(共0~15)进行映射
//映射规则不可能有两条EXTI线映射到相同的Pin号引脚
//PR寄存器的20位有效每一位对应被映射到EXTI的引脚Pin号。因此Pin号确定PR寄存器的对应位也就可确定
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) //***中断处理公用函数***
{
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);  //***数据处理回调函数***
  }
}

void KEY0_INT_IRQHandler(void)          //***中断服务函数***
{
    HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN);         /* 调用中断处理公用函数,清除中断标志位 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY0_INT_GPIO_PIN);         /* 退出时再清一次中断,避免按键抖动误触发 */
//不清除中断的话,长按就会持续进入数据处理回调函数里面
}


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(20);                                       /* 消抖 */
    switch (GPIO_Pin)
    {
        case KEY0_INT_GPIO_PIN:
            if (KEY0 == 0)
            {
                LED1_TOGGLE();                          /* LED1状态取反 */ 
                LED0_TOGGLE();                          /* LED0状态取反 */ 
            }
            break;

        case KEY1_INT_GPIO_PIN:
            if (KEY1 == 0)
            {
                LED1_TOGGLE();                          /* LED1 状态取反 */ 
            }
            break;

        case KEY2_INT_GPIO_PIN:
            if (KEY2 == 0)
            {
                LED0_TOGGLE();                          /* LED0 状态取反 */ 
            }
            break;

        case WKUP_INT_GPIO_PIN:
            if (WK_UP == 1)
            {
                LED1_TOGGLE();                          /* LED1状态取反 */

                if (HAL_GPIO_ReadPin(LED1_GPIO_PORT, LED1_GPIO_PIN) == 1)
                 {
                   LED0(0);
                 }
                 else 
                 {
                     LED0(1);
                 }
            }
            break;

        default : break;
    }
}

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

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

相关文章

基于springboot+vue+Mysql的交流互动系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

程序员的实用神器之——通义灵码

通义灵码介绍 “通义灵码”是一款基于阿里云通义代码大模型打造的智能编码助手&#xff0c;产品于2023年10月31日云栖大会上&#xff0c;正式对外发布。新手亦能驾轻&#xff0c;老手恒常运&#xff0c;唯手熟尔。 通义灵码产品介绍_智能编码助手_AI编程_云效(Apsara Devops)…

测试图像中的环与透镜效果。

我做了三张图片&#xff0c;发现我之前提出的环与带居然都存在。 这个图片的环不明显&#xff0c;需要放大才能看得出来&#xff0c;但是透镜效果&#xff0c;这里只能称之为带了。 这张图的环比较清晰&#xff0c;因为我做了更小的缩放。 制作环和带的过程是需要抗干扰&#…

Spring Boot 自动配置-响应式编程-022

🤗 ApiHug {Postman|Swagger|Api...} = 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱,有温度,有质量,有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Next Generation API Development Platform…

【Unity-Timeline进度条显示与拖动】

利用Unity 自带的Timeline 可轻松实现场景的巡检漫游效果&#xff0c; 基本使用参考以下链接: Unity中的Timeline Unity学习笔记——TimeLine的简单使用方法&#xff08;一&#xff09; 这里主要介绍如何通过滑动条控制播放的进度&#xff0c;效果图附上。 话不多说&#xff…

上海亚商投顾:沪指低开低走 两市成交额跌破8000亿

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 市场全天震荡走低&#xff0c;三大股指尾盘均跌近1%。地产股逆势走强&#xff0c;光大嘉宝、天地源、云南城投…

数据库-索引(高级篇)

文章目录 索引概念&#xff1f;索引演示&#xff1f;索引的优劣&#xff1f;为什么使用索引就快&#xff1f;本篇小结 更多相关内容可查看 索引概念&#xff1f; 索引&#xff08;index&#xff09;是帮助MySQL高效获取数据的数据结构(有序)。在数据之外&#xff0c;数据库系统…

分布式与一致性协议之PBFT算法(一)

PBFT算法 概述 前面提到了拜占庭将军问题之后&#xff0c;有人可能会感到困惑:口信消息型拜占庭问题直接在实际项目中是如何落地的呢&#xff1f;事实上&#xff0c;它很难在实际项目中落地&#xff0c;因为口信消息型拜占庭问题之解是一个非常理论化的算法&#xff0c;没有与…

宝塔助手是以宝塔Linux面板提供的API开发的一款可以随时随地管理服务器的APP

【软件介绍】手机操控云服务器的神器软件&#xff0c;本人亲测在用&#xff0c;好用极了&#xff01; 【软件名称】宝塔助手 【软件包名】com.lensyn.zsbt 【软件版本】1.4.1 【软件大小】29.00M 【适用系统】安卓 【软件特色】宝塔助手是以宝塔Linux面板提供的API开发的一款可…

Unity 2021 升级至团结引擎

UnityWebRequest 报错 InvalidOperationException: Insecure connection not allowed 解决方法 不兼容jdk 8 需要安装 JDK11 64bit 必须JDK 11&#xff0c;高版本也不行 安卓环境hub 未给我安装完全。 Data\PlaybackEngines\AndroidPlayer 并没有NDK,SDK。但是 HUB 显示已经…

Maven 依赖排查

先从项目去看显而易见&#xff0c;假如我们有一个项目&#xff0c;父工程中包含一些子工程&#xff0c;如下&#xff1a; 我们想看一下samples-account中的依赖关系&#xff0c;那么我们可以打开 samples-account的pom文件&#xff0c;查看其maven依赖关系图。 我们可以看到此项…

【算法】基础算法005之位运算

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 1.基础位运算 &&#xff1a;…

计算机丢失concrt140.dl是什么意思,concrt140.dll丢失的8个修复方法

concrt140.dll是一个核心的系统文件&#xff0c;属于Microsoft Visual C 2015 Redistributable组件集的一部分&#xff0c;其全称为并发运行时库&#xff08;Concurrency Runtime&#xff09;。此动态链接库&#xff08;DLL&#xff09;文件在Windows操作系统中扮演着至关重要的…

iOS plist文件增删改查

一. plist简介 plist文件&#xff0c;即属性列表文件&#xff0c;全名是Property List&#xff0c;这种文件的扩展名为.plist&#xff0c;因此&#xff0c;通常被叫做plist文件。它是一种用来存储串行化后的对象的文件&#xff0c;在iOS开发中通常用来存储用户设置&#xff0c…

【Mac】Dreamweaver 2021 for mac v21.3 Rid中文版安装教程

软件介绍 Dreamweaver是Adobe公司开发的一款专业网页设计与前端开发软件。它集成了所见即所得&#xff08;WYSIWYG&#xff09;编辑器和代码编辑器&#xff0c;可以帮助开发者快速创建和编辑网页。Dreamweaver提供了丰富的功能和工具&#xff0c;包括代码提示、语法高亮、代码…

win编写bat脚本启动java服务

新建txt&#xff0c;编写&#xff0c;前台启动&#xff0c;出现cmd黑窗口 echo off start java -jar zhoao1.jar start java -jar zhoao2.jar pause完成后&#xff0c;重命名.bat 1、后台启动&#xff0c;不出现cmd黑窗口&#xff0c;app是窗口名称 echo off start "名…

视觉叙事的艺术:StoryDiffusion打造一致性图像/视频故事创作

论文&#xff1a;https://arxiv.org/pdf/2405.01434 主页&#xff1a;StoryDiffusion: Consistent Self-Attention for Long-Range Image and Video Generation 一、摘要总结 本文提出了一种名为StoryDiffusion的新方法&#xff0c;用于生成一系列内容一致的图像和视频&#…

异地组网群晖不能访问怎么办?

在日常使用群晖网络储存设备时&#xff0c;我们常常会遇到无法访问的情况&#xff0c;特别是在异地组网时。这个问题很常见&#xff0c;但也很让人困扰。本文将针对异地组网群晖无法访问的问题进行详细解答和分析。 异地组网的问题 在异地组网中&#xff0c;群晖设备无法访问的…

UE5 升级插件时报:位域的默认成员初始值设定项至少需要 “/std:c++20“错误的解决办法

UE5.3之后的代码默认以C20标准来进行编译&#xff0c;所以找到会产生报错的插件的build.cs里查看有没有关于设置版本的代码&#xff0c;如果有改成Cpp20就行了 以及可以在build.cs内打印调试信息 System.Console.WriteLine($"CppStandard set: {CppStandard}");编译后…

偶然发现了Python的一个BUG。。。

一般情况下&#xff0c;dict(id1, **{id: 1})这句代码应该报TypeError。但如果在捕获了其他异常的情况下&#xff0c;再来执行这句代码&#xff0c;却是会报KeyError&#xff0c;如下图&#xff1a; Python3.10和Python3.9也能复现该情况&#xff0c;正当我摩拳踩掌&#xff0c…