深入解析STM32中断机制:从原理到外部中断实战

知识点1【中断的介绍】

单片机的中断——硬件中断

Linux操作系统的中断——软件中断

中断是指计算机运行过程中,出现某种意外情况需要主机干预,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后有返回原本暂停的程序继续运行。

1、程序中断和简单中断

程序中断:系统外部、内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的中断服务程序,待处理完毕后,再返回原来的程序运行,这整个过程称为程序中断

简单中断:当处理机接收中断后,只需暂停一个或几个周期而不执行对应的中断服务函数,称为简单中断

2、中断相关的概念

中断是一种硬件处理机制——一旦触发,就不需要程序判断,CPU内部自动执行。

中断源:能够触发中断的事件(如按键:按压按键会产生一个跳变沿),串口的收发也可以触发中断。一旦中断源被触发,那么在芯片内部就会产生一个中断请求。

事件:在中断部分,我们在使用中断之前,需要首先确定产生中断的事件。

在单片机中不是所有的事件都可以触发中断的,在手册中我们可以查到,那些事件可以触发中断。我们以串口为例

上图便是USART能够触发中断的请求。

中断服务程序:一旦中断触发,CPU需要停止当前的任务,去执行其他的任务,我们称其他任务为中断服务程序。

优先级:当有多个中断触发的时候,中断的处理顺序——数字越大,优先级越低

中断嵌套,在一个中断中可以出发另一个中断。

(1)中断优先级

抢占优先级:决定一个中断能否打断当前正在执行的中断

抢占优先级高的可以抢占抢占优先级低的中断。 如果抢占优先级相同,则无法互相抢占

次级优先级:当多个中断共享相同抢占优先级时,决定它们的处理顺序

刺激优先级高的中断先被处理,但不能打断正在执行的同抢占优先级的中断

次级优先级 是不具有打断功能的。

那么 抢占优先级 和次级优先级是如何管理的呢?

是通过优先级分组 来管理的

(2)优先级分组

在ARM Cortex-M中,优先级数值的位数的分配是由 优先级分组 决定的。通过分组,可以分配抢占优先级次级优先级的位数。

NVIC(嵌套向量中断控制器)

NVIC可配置的中断最大数目是240,每个中断的中断优先级 是1-256级

如上图使用8位来配置中断优先级的

那么 如果小于八位是如何配置呢?

——通过牺牲低位来配置,如 如果配置4位,就只有4-7位有效

3、中断注意事项:

终端服务函数中,不能出现死循环,也不能写入大量的循环语句。

原则:快进快出

知识点2【外部中断】

1、外部中断框图

流程介绍:

1、触发条件判断

外部中断信号 通过输入线进入,首先经过边沿检测电路,判断是上边沿,下边沿还是双边沿触发

判断方式即是由上边沿触发选择寄存器下边沿触发选择寄存器决定。

2、经过 或门

软件硬件都可以触发中断事件

3、事件屏蔽寄存器

用来选择传递的中断事件。

未被屏蔽的事件可以继续传递到后续模块

4、脉冲发生器

被筛选后的事件被转换为单周期脉冲信号,发出 事件请求信号

以上两个步骤是事件的处理流程,满足事件不一定会触发中断,可能是为了实现其他功能。

5、中断状态记录

请求挂起寄存器:锁存当前有效的中断请求状态,知道处理器响应后清除

6、二次屏蔽

中断屏蔽寄存器,通过APB总线 过滤请求,避免非使能中断占用NVIC资源

2、外部中断请求

外部中断/事件控制器 是由19个产生事件/中断请求边沿检测器组成

所以说:外部中断,其实就是IO口跳变产生的中断

知识点3【外部中断配置寄存器介绍】

1、外部中断配置寄存器

我们从上一张图片可以看到,每一个外部中断端口,都对应着很多个引脚如EXTI1对应这A1,B1……,因此我们需要配置其定义关系。

这里我们以外部中断寄存器2为例

可见上面有EXTI4-EXTI7,那么可以这样的寄存器一共4个。

注意

我们配置的时候,这个寄存器是按照数组的方式 来操作的。

详细配置 看下面的代码演示即可,很易理解,写代码的时候细心就好。

2、中断屏蔽寄存器

这里是配置 哪一个中断使能的

3、上 下边沿寄存器

知识点4【外部中断代码演示】

exti.c

void Exit1_Key_Config()
{//配置时钟:按键(PE4)和复用按键RCC->APB2ENR |= (0x01 << 0);RCC->APB2ENR |= (0x01 << 6);//中断配置//由于映射到EXIT2的端口有很多,因此需要选择AFIO->EXTICR[1] |= (0x04 << 0);//下边沿触发(线4)EXTI->FTSR |= (0x01 << 4);//中断屏蔽设置EXTI->IMR |= (0x01 << 4);//NVIC配置NVIC_SetPriority(EXTI4_IRQn,0x06);NVIC_EnableIRQ(EXTI4_IRQn);
}//按键中断服务函数
void EXTI4_IRQHandler(void)
{//中断触发条件判断if(EXTI->PR & (0x01 << 4)){//清除中断挂起位EXTI->PR &= ~(0x01 << 4);//执行中断函数while(1){//延时消抖if((GPIOE->IDR & (0x01 << 4)) == 0){Delay_ms(40);if((GPIOE->IDR & (0x01 << 4)) == 0){while((GPIOE->IDR & (0x01 << 4)) == 0);printf("你好\\n");}}}}
}

main.c

#include "stm32f10x.h"   // 相当于51单片机中的  #include <reg51.h>
#include "stdio.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
int main(void)
{// 来到这里的时候,系统的时钟已经被配置成72M?//第五组NVIC_SetPriorityGrouping(0X05);Exit1_Key_Config();Usart1_Config(9600);printf("USART1 is ok!!\\r\\n");while(1){		}}

代码感悟

1、串口一次只能接收 / 发送一位数据

2、中断服务函数 需要 软件清除中断标志位

3、外部中断是通过 辅助接口(AFIO) 来设置的

知识点5【事件中断】

首先我们要清楚,不是所有事件都能触发中断的,因此我们要实现知道那些事件能够产生中断,我们以串口为例。可以在寄存器手册中查到。

可见,事件中断触发,的前提是 使能对应事件的中断标志位,如当 接收事件完毕即RXNE被置位 后,并且软件置为RXNEIE,会产生一个对应的串口中断

在事件触发,并且对应的中断标志位被置位 的情况下,事件中断就会被触发,即会执行对应的中断服务程序。

这里寄存器不过多介绍 我们直接进入实战

知识点6【事件中断代码演示】

逻辑:

只有RXNE 被置位,且RXNEIE 被置位,才会发生中断

我们知道串口每次接收到一个数据,RXNE会被置位,又由于我们循环软件置为RXNEIE 是的接收数据中断持续生效。

那么我们该如何判断所有位的数据 都被接收呢

我们就需要利用串口的空闲中断 即 IDLE状态位,详细大家看手册。

这是我们就 引入一个flag位,当进入空闲状态,flag置1,即接收全部数据完成。

代码演示

exti.c文件

#include "exti.h"u8 over_flag=0;
u8 rev_data[64]={0};
u8 rev_count=0;
void USART1_IRQHandler(void)
{u8 data=0;if((USART1->SR &(0X01<<5))){USART1->SR &=~(0X01<<5);//进入了接收中断,可以接受外部传输过来的数据rev_data[rev_count++]=USART1->DR;}//当数据接受完成的时候,就会进入空闲中断if((USART1->SR &(0X01<<4))){USART1->SR &=~(0X01<<4);//清除空闲中断标志data=USART1->DR;//设置一个接收完成的标志位over_flag=1;	}
}//中断接受完成数据之后,在以下函数中处理数据void Usart1_CtrlLED(void)
{int i=0;if(over_flag==1){over_flag=0;//避免影响下一次的数据接收中断//处理接收到的数据printf("接收到的数据个数:%d\\r\\n",rev_count);for(i=0;i<rev_count;i++){printf("rev_data[%d]=%x\\r\\n",i,rev_data[i]);}if(rev_data[0]==0xaa && rev_data[2]==0xff){//控制LED1if(rev_data[1]==0x11) GPIOB->ODR &=~(0X01<<5);else GPIOB->ODR |=(0X01<<5);}rev_count=0;memset(rev_data,0,sizeof(rev_data));}
}int fputc(int c, FILE * stream)
{while(!(USART1->SR &(0X01<<7)));USART1->DR=c;return c;	
}

main函数

#include "stm32f10x.h"   // 相当于51单片机中的  #include <reg51.h>
#include "stdio.h"
#include "delay.h"
#include "led.h"
#include "usart.h"
int main(void)
{// 来到这里的时候,系统的时钟已经被配置成72M?//第五组NVIC_SetPriorityGrouping(0X05);Led_Config();Usart1_Config(9600);printf("USART1 is ok!!\\r\\n");while(1){Usart1_RevInterrupt();Usart1_CtrlLED();}
}

结束

最近的分析是关于寄存器的,当然后面我会分享标准库的,因为寄存器是基础,我们先学习寄存器有利于我们深度理解后面标准库的原理,我的分享是一个由繁入简的过程,希望大家能够理解。

补充:

        这两天由于身体状态原因,没有正常更新,但学习过程没有间断。大家也注意身体,毕竟身体是革命的本钱。

        望体谅!

最后:

        代码重在练习!

        代码重在练习!

        代码重在练习!

今天的分享就到此结束了,希望对你有所帮助。如果你喜欢我的分享,请点赞收藏加关注,谢谢大家!!!

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

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

相关文章

【入门】打印字母塔

描述 输入行数N,打印图形. 输入描述 输入只有一行&#xff0c;包括1个整数。(N<15) 输出描述 输出有N行. #include <bits/stdc.h> using namespace std; int main() { char t;int n,f;cin>>n;for(int i1;i<n;i){tchar(65i);for(int j1;j<n-i;j){cout…

CentOS 7.9 安装详解:手动分区完全指南

CentOS 7.9 安装详解&#xff1a;手动分区完全指南 为什么需要手动分区&#xff1f;CentOS 7.9 基本分区说明1. /boot/efi 分区2. /boot 分区3. swap 交换分区4. / (根) 分区 可选分区&#xff08;进阶设置&#xff09;5. /home 分区6. /var 分区7. /tmp 分区 分区方案建议标准…

油冷式电动滚筒设计:关键技术解析与应用前景

引言 电动滚筒作为一种集动力传输、减速和驱动功能于一体的机电一体化设备&#xff0c;在输送机械、矿山设备、食品加工等领域广泛应用。随着工业设备向高效化、紧凑化和智能化发展&#xff0c;传统风冷式电动滚筒的散热效率与负载能力已逐渐难以满足需求。油冷式电动滚筒凭借…

Android开发-Activity附加信息

在Android应用开发中&#xff0c;除了基本的界面跳转和数据传递之外&#xff0c;我们还经常需要为Activity添加一些附加信息&#xff08;Metadata&#xff09;&#xff0c;以支持更复杂的配置需求或与系统进行交互。这些附加信息可以通过<meta-data>标签在AndroidManifes…

2025第九届御网杯网络安全大赛线上赛 区域赛WP (MISC和Crypto)(详解-思路-脚本)

芜湖~ 御网杯线上分是越来越精细 区域赛都有了 然后不过多评价 整体不算难 以下是我自己的一些思路和解析 有什么问题或者建议随时都可以联系我 目录 芜湖~ MISC #被折叠的显影图纸 #光隙中的寄生密钥 #ez_xor #套娃 #easy_misc #ez_pictre Crypto #easy签到题 …

‌中继器:网络中的“血包”与“加时器”‌

在探讨网络技术时&#xff0c;我们往往会遇到各种专业术语和设备&#xff0c;中继器便是其中之一。然而&#xff0c;对于非技术人员或初学者来说&#xff0c;这些概念可能显得抽象且难以理解。今天&#xff0c;我将通过一个生动的比喻——将中继器比作网络中的“血包”与“加时…

MySQL----高级查询

目录标题 ⭐**多表查询的格式**⭐**查询前说明**一.**使用内连接**inner join**进行多表查询****1.介绍****2.事例** 二.**使用外连接**outer join**进行多表查询**1.**介绍** ⭐多表查询的格式 其一 select *&#xff5c;字段列表 from 表1[查询类型] join 表名2 on 连接条件…

SpringBoot主入口类分析

1 &#xff09;SpringBoot主入口类 SpringBoot 主入口类如下所示&#xff0c;这个类的main方法就是整个springboot项目的入口。 package com.example.demo3;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootA…

【RabbitMQ】 RabbitMQ高级特性(一)

文章目录 一、消息确认1.1、消息确认机制1.2、手动确认方法1.2.1、AcknowledgeMode.NONE1.2.2、AcknowledgeMode.AUTO1.3.3、AcknowledgeMode.MANUAL 二、持久性2.1、 交换机持久化2.2、队列持久化2.3、消息持久化 三、发送方确认3.1、confirm确认模式3.2、return退回模式3.3、…

探索Hello Robot开源移动操作机器人Stretch 3的技术亮点与市场定位

Hello Robot 推出的 Stretch 3 机器人凭借其前沿技术和多功能性在众多产品中占据优势。Stretch 3 机器人采用开源设计&#xff0c;为开发者提供了灵活的定制空间&#xff0c;能够满足各种不同的需求。其配备的灵活手腕组件和 Intel Realsense D405 摄像头&#xff0c;显著增强了…

expo多网络请求设定。

在使用 npx expo start 启动 Expo 开发服务器时&#xff0c;你可以通过设置网络模式来控制你的应用如何连接到开发服务器。Expo 提供了几种网络模式供你选择&#xff1a; LAN (Default): 这是默认模式。在这种模式下&#xff0c;你的应用会通过本地局域网 (LAN) 连接到你的开发…

Nginx 安全防护与HTTPS部署

目录 一、核心安全配置 1、隐藏版本号 2、限制危险请求方法 3、请求限制&#xff08;CC攻击防御&#xff09; &#xff08;1&#xff09;使用Nginx的limit_req模块限制请求速率 &#xff08;2&#xff09;压力测试验证 4、防盗链 &#xff08;1&#xff09;修改 Window…

windows 环境下 python环境安装与配置

运行环境安装 第一步安装包下载 python开发工具安装包下载官网&#xff1a; https://www.python.org/ 根据自己的实际需求选择。 这里记录了各个版本的区别和差异。根据区别和差异选择适合自己的版本。 Windows Installer和Windows embeddable package是两种不同的软件包类…

TB6600HG是一款PWM(脉宽调制)斩波型单芯片双极性正弦波微步进电机驱动集成电路。

该驱动器支持电机的正向和反向旋转控制&#xff0c;并具有多种激励模式&#xff0c;包括2相、1-2相、W1-2相、2W1-2相和4W1-2相。 使用这款驱动器&#xff0c;只需时钟信号即可驱动2相双极性步进电机&#xff0c;且振动小、效率高。 主要特点&#xff1a; 单芯片双极性正弦波…

【JS逆向基础】爬虫核心模块:request模块与包的概念

前言&#xff1a;这篇文章主要介绍JS逆向爬虫中最常用的request模块&#xff0c;然后引出一系列的模块的概念&#xff0c;当然Python中其他比较常用的还有很多模块&#xff0c;正是这些模块也可以称之为库的东西构成了Python强大的生态&#xff0c;使其几乎可以实现任何功能。下…

极狐Gitlab 里程碑功能介绍

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 里程碑 (BASIC ALL) 极狐GitLab 中的里程碑是一种跟踪议题和合并请求的方法&#xff0c;这些请求是为了在特定时间段内实现更…

【日撸 Java 三百行】Day 10(综合任务 1)

目录 Day 10&#xff1a;综合任务 1 一、题目分析 1. 数据结构 2. 相关函数基本知识 二、模块介绍 1. 初始化与成绩矩阵的构建 2. 创建总成绩数组 3. 寻找成绩极值 三、代码与测试 小结 拓展&#xff1a;关于求极值的相关算法 Day 10&#xff1a;综合任务 1 Task&…

c++:库(Library)

目录 什么是库&#xff1f; C中库的两种形态&#xff1a;静态库 和 动态库 静态链接 vs 动态链接&#xff08;链接 ≠ 库&#xff09; &#x1f512; 静态链接&#xff08;Static Linking&#xff09; &#x1f517; 动态链接&#xff08;Dynamic Linking&#xff09; C标…

Java线程池深度解析:从使用到原理全面掌握

在高并发场景下&#xff0c;线程管理是提升系统性能的关键。本文将深入探讨Java线程池的核心机制&#xff0c;带你从基础使用到底层实现全面掌握这一重要技术。 一、线程池存在的意义 1.1 线程的隐形成本 尽管线程相比进程更轻量&#xff0c;但当QPS达到万级时&#xff1a; 频…

PostgreSQL 的 pg_advisory_lock_shared 函数

PostgreSQL 的 pg_advisory_lock_shared 函数详解 pg_advisory_lock_shared 是 PostgreSQL 提供的共享咨询锁函数&#xff0c;允许多个会话同时获取相同键值的共享锁&#xff0c;但排斥排他锁。 共享咨询锁 vs 排他咨询锁 锁类型共享锁 (pg_advisory_lock_shared)排他锁 (pg…