1. 中断概述
    1.1 什么是中断?
    1.2 中断的作用
  2. 中断的实现
    2.1 中断的入口
    2.2 中断优先级
  3. ARM单片机中断体系
    3.1 NVIC优先级说明
    3.2 NVIC优先级分配方式
    3.3 STM32fxx中断体系
  4. STM32中断配置
    4.1NVIC相关配置函数
    4.2设置优先级分组函数
    4.3设置中断优先级函数
    4.4NVIC响应中断使能
  5. 内部中断
  6. 外部中断
  7. 软件中断

中断概述

什么是中断?

当开始学习中断时,首先需要了解中断在STM32是什么,他是怎么来的,是用来干什么的,又是怎么干的,这是在学之前心里必须要提出的问题。
那么什么是中断呢?
中断就是程序在正常运行的过程中发生了不正常的事情,必须要暂停一下去处理这个不正常的事情,然后跑回来继续干正常的事情。
对于STM32来说,正常运行的程序是主函数(main),代码是由CPU运行的。CPU在主函数里运行是正常的执行过程,当在这个过程中突然发生了异常事件(中断),CPU必须暂停当前的工作(设下断点),然后跑去能处理这个异常事件的函数中做异常处理(中断服务函数),处理完这个异常事件后(执行完中断服务函数),CPU就会跑回刚才的断点处,继续正常运行下去。然而在程序运行当中,中断发生的时间并不确定、所以一旦发生必须立马处理、处理完异常再执行正常事件。(快进快出)。

中断是用来干什么的?

在这里举个例,例如串口收发数据时,查询式用法在每次应用在主程序当中,都需要经过一个查询是否有数据收发的过程,而在此过程当中,都需要经过一个while()的循环进行查询,而在循环执行的过程当中,就会导致程序卡死在此处,必须等执行完才能进入下一步,而中断便是解决这方面问题,在需要处理的时候让主函数去处理,不需要的时候正常的执行程序。

中断的实现

中断的入口

在主程序的运行过程中,想要执行一些其他的事件,这时候该事件抢占CPU去优先处理它,那要去处理它就必须要有一个入口,而这个入口便是在暂停主程序时产生的断点,通过该断点进入响应的中断服务函数入口,进入中断,而对于中断来说,它不能去干扰主函数中之前做过的事,这边存在了一个将数据保存下来的一个操作,即数据入栈,数据出栈。

中断优先级

既然中断是异常事件,那么难保不会同时出现多个异常事件,那对于程序来说,事件的处理顺序又该怎么办呢,那么优先级这一概念就出来了。
优先级的分类
对于STM32来说,中断优先级分三类,即:占先(抢占)优先级,次级(响应)优先级,自然优先级。
中断优先级数字越小,优先级越高
UCOSII/III: 数字越小优先级越高
FreeRTOS:数字越小优先级越低
中断嵌套

ARM单片机中断体系

在我们了解的中断的相关含义,我们再来思考一下,中断优先级,中断服务函数这些又是什么来定义划分的呢?
首先,我们知道ARM公司是制作芯片架构的公司,而STM32系列单片机作为ARM架构下的单片机所采用的中断体系都是同一套而中断体系就是管理中断的一种体系,在芯片内核里专门有一个管理中断机制的模块–NVIC控制器
NVIC控制器属于内核级的模块,专门做中断管理,包括中断响应,优先级的设置,相关中断的使能。

NVIC优先级说明

如果同时到来两个事件、先对比占先、占先一致再对比次级

事件 占先 次级
A 1 5
B 2 2
C 2 3
事件A与B同时到来、先处理A
事件B与C同时到来、先处理B
事件C正在执行、事件B到来、不能打断C的执行、占先一致
事件C正在执行、事件A到来、直接打断执行A

总结:1.占先优先级相同的形况下,事件之间不能进行打断
   2.占先优先级相同的情况再比较次级优先级
   3.自然优先级不可更改,它是内核当中已经规定好的
   4.中断嵌套时,当高占先优先级的中断执行时,低占先优先级或同占先优先级的中断产生了,低优先级的中断不响应。

NVIC优先级分配方式

知道了优先级的作用,我们需要了解一下NVIC中断体系中,又是如何去分配优先级的呢,既然自然优先级不能更改,那占先和次级优先级又是如何分配的呢。
在内核的中断体系当中,对于占先和次级优先级的分配与设置都是在一个8位寄存器当中实现的,在该寄存器来防止设置的占先和次级优先级,它们一起被放在该寄存器中,那对于寄存器中优先级位数的划分又是怎么规定的呢?
在ARM的中断体系当中,因为一共有8位来防止优先级,那么对于占先和次级优先级的分配有8种

STM32fxx中断体系

对于ARM的优先级分配方式,其实不是每个芯片都利用8位来设置优先级,对于STM32单片机而言,它所用的是其中四位[7:4],且在我们编写工程当中,每个工程只能有一个分组号,写优先级时第一步必须先分组、才能写入占先和次级的值。

了解完中断及其体系的理论知识过后,接下来了解STM32单片机相关的中断配置。

STM32中断配置

NVIC相关配置函数

优先级相关的配置函数、只需要配置相关即可

NVIC_SetPriorityGrouping:设置优先级分组
NVIC_EnableIRQ:使能优先级
NVIC_SetPriority:设置优先级

设置优先级分组函数

函数原型:void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
函数功能:优先级分组
形参:PriorityGroup
返回值:无
参数说明:参数+分组号=7 分组号=7-参数
例如需要配置分组为第五组:NVIC_SetPriorityGrouping(7-5)
注: 对于该分组函数的使用,我查阅网上的一些资料,认为此处函数形参就是分组号,但是所学的内容是上面的理解,如果有疑问的可以观察该函数原型,查找相关资料自行理解。

设置中断优先级函数

函数原型:void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
函数功能:设置优先级(占先+次级)
形参:
IRQn:Interrupt number 中断号
Priority:Priority to set 设置优先级
返回值:无
例如:
NVIC_SetPriorityGrouping(7-5)//第五组
NVIC_SetPriority(USART1_IRQn,5) 占先=1 次级=1

NVIC_SetPriorityGrouping(7-6)//第六组
NVIC_SetPriority(USART2_IRQn,6) //占先=0 次级=6
该函数第二参数优先级的设置也可通过 NVIC_EncodePriority 函数合成占先和次级优先级
即:NVIC_SetPriority(EXTI15_10_IRQn,NVIC_EncodePriority(7-5,1,1))

NVIC响应中断使能

函数原型:void __NVIC_EnableIRQ(IRQn_Type IRQn)
函数功能:使能
形参:USART1_IRQn 中断号(中断号可查询系统中断向量表知道)
返回值:

内部中断

了解完NVIC相关的中断配置后,那么我们就要了解下中断的请求是哪来的,又该如何配置。
对于内部中断而言,我所了解到的是关于芯片片上外设上的中断,而且每一种外设不止一种中断,那么对于程序而言,要使中断能实现,需要打开两个中断开关,一个是片上外设的中断开关,一个是NVIC中断控制器上的。例如:串口USART1上的RXNE接受中断使能。


由上可知,串口不知一种中断,那么在对于串口的中断进入的又是同一个中断服务函数,我们要做的就是要在中断服务函数当中要判断是哪种中断。
注: 且外设上产生的中断,我们配置中断之前配置好外设的各种寄存器。
内部中断的相关初始化如下:
配置流程:
1.配置好相关片上外设
2.打开片上外设上相关中断的响应
3.设置优先级分组,优先级和NVIC中断响应等
4.片上外设使能
5.中断服务函数
6.进入中断服务函数先判断是哪种中断,在进行相关操作。
7.最后判断程序是否进入中断,可以自定义相关的功能函数,如电灯,串口通信等操作,调用至中断服务函数中,主函数中不需要进行调用,查看功能是否实现,或定义全局变量中断标志,到主函数中通过标志位的变化,查看是否进入中断。

void Uart_Config(u32 brr)
{float div;u32 div_m,div_f;     //div_m  分频整数部分  div_f分频比小数部分NVIC_SetPriorityGrouping(7-5); //设置中断优先级分组     抢占:2位  响应:2位RCC->AHB1ENR |= (1<<0);             //打开GPIOA时钟RCC->APB2ENR |= (1<<4);                //打开USART1时钟GPIOA->MODER &= ~(0xf<<18);     //清零PA9/PA10GPIOA->MODER |= (0xa<<18);      //GPIOA复用功能模式GPIOA->OTYPER &= ~(3<<9);            //输出推挽模式GPIOA->AFR[1] |= (7<<4);          //PA9  复用功能高位寄存器(UART1 AF7)GPIOA->AFR[1] |= (7<<8);         //PA10 复用功能高位寄存器(UART1 AF7)div = 84000000.0f/16/brr;     //84MHz 16倍过采样div_m = (u32)div;                                        //取出DIV整数部分div_f = (div-div_m)*16+0.5f;               //得出来得小数放不进寄存器当中需乘回16倍过采样,并进行四舍五入USART1->BRR |= (div_m<<4)|div_f;      //BRR寄存器需放入DIV的值//设置接受中断优先级NVIC_SetPriority(USART1_IRQn,NVIC_EncodePriority(7-2,1,1));//使能NVIC响应接受中断NVIC_EnableIRQ(USART1_IRQn);USART1->CR1 |= (1<<5);        //RXNEIE,USART1中断使能(读取数据寄存器不为空中断)USART1->CR1 |= (1<<4);        //IDLE检测到空闲电路,空闲中断使能USART1->CR1 |= (1<<2);     //接收器使能USART1->CR1 |= (1<<3);     //发送器使能USART1->CR1 &= ~(1<<10);       //禁止奇偶校验USART1->CR1 &= ~(1<<12);      //字长 8数据位USART1->CR1 &= ~(1<<15);     //16倍过采样USART1->CR2 &= ~(3<<12);      //1个停止位USART1->CR1 |= (1<<13);            //USART1使能
}
void USART1_IRQHandler(void)    //USART1所有中断共用一个入口
{u32 temp;//判断是哪种中断if(USART1->SR & (0x1 << 5))//接受中断,数据寄存器不为空{uart_data.revBuf[uart_data.position] = USART1->DR;//读DR清除标志uart_data.position++;                                    //标志下一次的位置}else if(USART1->SR & (0x01<<4))     //空闲中断{//清标志        空闲中断标志清零temp = USART1->SR;temp = USART1->DR;temp = temp;       //防止警告未使用uart_data.revOK = 1;                          //数据接受完成uart_data.revBuf[uart_data.position] = '\0';     //拼接成字符串uart_data.position = 0;                        //为下一次接受做准备}}

外部中断

Stm32F4XX异常向量表(中文手册)
阴影部分是系统级的,触发必须响应的。
82个外部中断(非阴影部分)

…………………

外部中断概述
GPIO发生电平变化产生的中断(外部中断)
23个中断源(16+7)即23个EXTI外部中断线
因为系统中断中的中断向量并没有GPIO口,所以需要通过SYSCFG_EXTICR1寄存器来映射到EXTI中断线上

EXTI0~15对应IO引脚

中断线的配置流程:
例如配置PC13的中断线
1.打开SYSCFG时钟(APB2 14位)
2.SYSCFG->EXTICR4 |=(2<<4);

外部中断/事件控制器框架


两个线:红色和绿色
红色的表示产生中断
绿色的表示产生事件
分析红色:

  1. 输入线:一共23根, GPIO占16根,另外七根是片上外设
  2. 边沿检测器:对应着有两个寄存器分为上升沿触发选择寄存器和下降沿触发选择寄存器。如果输入线产生的边沿和上升沿触发寄存器或者下降沿触发寄存器匹配,就会输出一个有效信号”1”;
  3. 或门:信号输入端有两个:边沿检测器输出端和软件中断事件寄存器,因为我们要做外部电平变化,所以要将软件中断事件寄存器输出”0”,此时或门输出端才受到边沿检测电路的输出端控制。
  4. 与门:信号来源有两个:或门的输出端和中断屏蔽寄存器,如果想要与门输出端输出有效信号,必须中断屏蔽寄存器输出”1”,此时在产生一个有效电平触发。
  5. 挂起寄存器:标志位

分析绿色部分
前面1-3都是与中断一样
6. 与门:信号来源有两个:或门的输出端和事件屏蔽寄存器,如果想要与门输出端输出有效信号,事件屏蔽寄存器输出”1”,此时产生一个有效电平触发。
7. 脉冲信号发生器:与门输出端输出有效信号“1”,就能让脉冲信号发生器产生一个脉冲去触发硬件工作。
中断:产生异常事件,CPU就回去执行中断服务函数
事件:产生异常事件,不需要CPU参与,只能去触发其它硬件工作
相应的外部配置函数如下:
配置流程:
1.打开系统配置控制时钟(挂接再APB2总线上)
2.将相应GPIO口管脚映射至EXTI中断线上
3.配置相应上升沿/下降沿触发选择寄存器
4.打开中断屏蔽寄存器
5.关闭软件中断寄存器
6.设置中断优先级,使能中断响应
7.中断服务函数中通过判断PR寄存器进入中断,再将PR寄存器写1清零。

void EXTI13_Config(void)
{RCC->APB2ENR |= (1<<14);                 //打开系统配置控制寄存器时钟SYSCFG->EXTICR[3] |= (0x2<<4);     //PC13管脚(按键)映射到EXTI外部中断线上   EXTI->RTSR &= ~(1<<13);                       //禁止上升沿触发选择寄存器EXTI->FTSR |= (1<<13);                      //打开下降沿触发选择寄存器EXTI->IMR |= (1<<13);                           //打开中断屏蔽寄存器EXTI->EMR &= ~(1<<13);                     //关闭事件屏蔽寄存器EXTI->SWIER &= ~(1<<13);                 //关闭软件中断寄存器NVIC_SetPriority(EXTI15_10_IRQn,NVIC_EncodePriority(7-5,1,1));     //设置EXTI13的中断优先级NVIC_EnableIRQ(EXTI15_10_IRQn);             //使能EXTI13中断响应}void EXTI15_10_IRQHandler(void)
{if(EXTI->PR & (0x01<<13))                 //进入EXTI13中断{   EXTI->PR |= (0x01 << 13);             //挂起寄存器写1清零Exti_Flag = 1;while(EXTI->PR & (0x01<<13));        //等待清零完成}
}

软件中断

软件中断的使用其实和外部中断(硬件中断)没有很大区别,只是不需要去配置GPIO映射EXTI中断线,边沿检测那些,后续与外部中断无多大差别,在配置软件中断时,先将软件中断寄存器清零,等待需要进入软件中断时再将之置1。

void EXTI6_soft_Config(void)
{EXTI->SWIER &= ~(0x1<<6);                //EXTI6软件中断寄存器指令EXTI->IMR    |=  (0x01<<6);           //打开中断屏蔽寄存器EXTI->EMR   &= ~(0x01<<6);         //关闭事件屏蔽寄存器NVIC_SetPriority(EXTI9_5_IRQn,NVIC_EncodePriority(7-5,0,2));     //设置EXTI6中断优先级NVIC_EnableIRQ(EXTI9_5_IRQn);     //使能EXTI6中断响应
}
void EXTI9_5_IRQHandler(void)
{if(EXTI->PR & (0x01<<6)){EXTI->PR |= (0x01<<6);LED3_TOGGLE;}
}

以上就是我对中断的学习过程,如有疏漏,谢谢指教。

中断(STM32FXX系列单片机)相关推荐

  1. 开发STC89C51系列单片机需要的单片机技术

    文章目录 1. 端口操作 1.1. 设置端口方向 1.2. 读取端口状态 1.3. 控制端口状态 1.4. 实现按键检测 2. 中断处理 2.1. 定时器/计数器中断 2.2. 外部中断 2.3. 串 ...

  2. 51单片机除c语言 中断嵌套,关于51系列单片机中断嵌套 - 关于单片机中断嵌套总结...

    关于51系列单片机中断嵌套 说最基本的,老的51单片机(80C51系列)有5个中断源,2个优先级,可以实现二级中断服务嵌套.现在很多扩展的51单片机已经有4个优先级(或更多)和更多的中断源了. 在说到 ...

  3. 关于STM32系列单片机中断触发时间问题

    在使用STM32系列单片机的时候,经常要使用到中断,但是STM32参考手册上关于中断只说明了有哪些中断源和中断向量表相关问题.没有具体说明触发中断的信号至少需要多长时间?中断检测到中断源需要多长时间? ...

  4. PIC18F系列单片机外部中断

    PIC18F系列单片机外部中断 以外部中断0为例,代码如下 void INTx_Init (void)//外部中断 {TRISBbits.TRISB0 = 1;INTCON2bits.INTEDG0 ...

  5. GD32系列单片机EXTI外部中断配置

    文章目录 前言 一.EXTI-外部中断 二.程序说明 1.主函数 2.中断函数 总结 前言 学习嵌入式的时候不可避免会接触到中断这个概念,我们平时接触也是最多的,在刚开始学习stm32单片机的时候,听 ...

  6. 鸿蒙51单片机,基于C51系列单片机的交通控制系统设计

    2.2 数码时间显示电路 七段LED数码管是由八个发光二极管构成,通过给其引脚不同的高低电平,从而显出0~9的数字和小数点,本文通过四个一位数码管并联通过P3口当中的P3.0与P3.1与STATIC ...

  7. 8051系列单片机汇编语言指令速查表(汇编语言的111条指

    8051系列单片机汇编语言指令速查表(汇编语言的111条指_纳兰容若的左手_新浪博客 http://blog.sina.com.cn/s/blog_6486c0b30100gqew.html 编号 指 ...

  8. pic单片机内部时钟校准c语言,PIC系列单片机片内定时器实时时钟的实现(转)

    PIC系列单片机片内定时器实时时钟的实现(转) (2008-08-11 14:24:59) 标签: 杂谈 1. 1 振荡频率的考虑 工作频率为4MHz 的单片机, 选择32. 768kHz 的晶振显然 ...

  9. stm32f1系列单片机实战应用

    最近有一个小项目,测量运动自行车速度,上传给上位机软件,处理VR视频播放.正好公司有现成的stm32f1系列单片机开发板,所以我就想到了使用它来实现这个小功能. 1. 硬件配置: 1.1. 运动自行车 ...

最新文章

  1. Linux系统的目录绑定配置
  2. 【工具】更新国内使用谷歌日历解决方案——飞书日历,谷歌输入法下载
  3. Mysql主从和redis集群哪个好_Redis的三种模式:主从、哨兵、集群
  4. Scanner类、Random类、ArrayList类
  5. Linux如何进入微服务看日志,Linux日志查找与服务器重启
  6. sonar 报错日志分析(根据日志跟踪源码执行)
  7. 点击Cell中的按钮时,如何取所在的Cell
  8. 创建维护计划时,提示“代理XP”组件已作为此服务器安全配置的一部分被关闭...
  9. 卡尔曼滤波,高斯函数
  10. Linux特殊权限set_uid、set_gid、stick_bit命令和软链接文件、硬连接文件
  11. arm linux驱动 知乎_引导 ARM Linux
  12. 蒙特卡洛方法习题_蒙特卡洛方法
  13. thinkpad 开启虚拟服务器,ThinkPad笔记本怎么开启处理器虚拟化技术
  14. VMware15 Pro激活密钥
  15. Linux常用软件包(常用命令)
  16. 【010】Excel宏编程相关封装模块(字体设置、写入表格内容)_003_#VBA
  17. FIR滤波器的FPGA实现方法
  18. vue、Steps 步骤条、Steps 属性、vue Steps 所有步骤条样式、vue Steps 步骤条全部属性
  19. 11-20什么是内网,外网,局域网,如何判断
  20. layui的layer的用法

热门文章

  1. 顶点支配、独立与覆盖
  2. 百度ERNIE——百度快车道记录
  3. java面向字符的输入流_Java编程开发中面向字节的输入输出流
  4. SuperMap iManager云套件iServer镜像定制与更新-以定制达梦依赖为例
  5. Idea做spring项目所遇到的一些问题
  6. 开放封闭原则(SCP:Open-Closed Principle)
  7. DDR SDRAM 学习笔记 —— DDR4 内存初始化过程 之 Multi Purpose Register (MPR Read)
  8. 日常管理的五条小建议
  9. 多少开发人员 饿了么_开发一款类似美团饿了么APP要多少钱?
  10. 景联文科技提供自动驾驶DMS系统-图像采集标注服务