stm32中断嵌套全攻略

发布者:北极星小鹏最新更新时间:2020-01-02 来源: eefocus关键字:stm32  中断嵌套 手机看文章 扫描二维码
随时随地手机看文章

断断续续学习STM32一学期了,时间过的好快,现在对STM32F103系列单片机的中断嵌套及外部中断做一个总结,全当学习笔记。废话不多说,ARM公司的Cortex-m3 内核,支持256个中断,其中包含16个内核中断和240个外部中断,并且具有256级的可编程中断设置。在ST公司的STM32单片机中最多有84个中断,包括16个内核中断(这16个内部中断是任何半导体商也改不了的),和68个可屏蔽中断,具有16级可编程的中断优先级。但是在STM32F103系列中只有60个可屏蔽中断,(107系列有68个)。

针对这60个可屏蔽中断,重点掌握它的一个中断优先级寄存器组IPR,全称Interrupt Priority Registers。这个寄存器组包含15个32位的寄存器,一个可屏蔽中断占用8bit,那么一个寄存器可以控制4个可屏蔽中断,一共15*4=60。然而在这占用的8bit中又只使用了高4bit,这高4bit的分配才是STM32F103系列单片机中断嵌套的设置所在。STM32F103系列的中断嵌套分为5个组,分别是0、1、2、3、4  这5个组,下面是5个组与中断嵌套的对应关系。

分配结果

0

0位抢占优先级,4位响应优先级

1

1位抢占优先级,3位响应优先级

2

2位抢占优先级,2位响应优先级

3

3位抢占优先级,1位响应优先级

4

4位抢占优先级,0位响应优先级


 

对于抢占优先级和响应优先级,只需记住两点,第一、抢占任何优先级比都比所有响应优先级优先级高。只有抢占优先级更高的具有中断嵌套功能。(即打断其他正在执行的中断)。第二、数字越小优先级越高 ,抢占优先级和响应优先级都一样时,首先响应中断通道对应中断向量地址低的那个中断。

下面对0组和1组的情况做一个分析。
0组对应是0位抢占优先级,4位响应优先级,那么无抢占优先级,响应优先级可设置为0到15级(2的4次方种)中的任意一种。
1组对应是1位抢占优先级,3位响应优先级,那么抢占优先级只可设置为0级或者1级中的任意一种(2的1次方种),响应优先级可设置为0到7级(2的3次方种)中的任意一种。
上电复位时,中断配置为4组,并且60个外部中断都是抢占优先级为0级,无响应优先级。

总结一下:

  1. 高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。

  2. 抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。

  3. 抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。

  4. 如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行。


所以可以看出判断两个中断的优先级时先看抢占优先级的高低,如果相同再看响应优先级的高低。如果全都相同最后看中断通道向量地址。
一般来说在使用过程中,一个系统使用一个组别就完全可以满足需要。所以在使用一个组别后一般不要在系统中再改动组别,骨灰级玩家可以去试试(小心芯片烧了)。

外部中断:
STM32F103的外部中断EXTI支持19个外部中断/事件请求。每个中断/事件都有独立的触发和屏蔽设置。
0到15线:对应外部I/O口输入中断
线16:接到PVD输出
线17:接到RCT闹钟事件
线18:接到USB唤醒事件
线16到线18我自己都没用过,主要对线0到15的I/O输入中断做一个总结,有个注意的地方是这0到15线的外部中断,其中0到4线,这5个外部中断都有自己单独的中断响应函数。5到9线公用一个中断服务函数,10到15线公用一个中断服务函数。
外部中断配置寄存器组EXTICR包含4个32位的寄存器,分别是EXTICR0、EXTICR1、EXTICR2、EXTICR3、但每一个寄存器只用了低16位,每4位控制一个I/O口,一个寄存器控制4个I/O口,EXTICR寄存器组控制16个I/O口,刚好一个GPIO的I/O口数。下面以 EXTICR0为例,用一个表格表示:


I/O口3

I/O口2

I/O口1

I/O口0

0000    GPIOA

0000    GPIOA

0000    GPIOA

0000    GPIOA

0001    GPIOB

0001    GPIOB

0001    GPIOB

0001    GPIOB

0010    GPIOC

0010    GPIOC

0010    GPIOC

0010    GPIOC

0011    GPIOD

0011    GPIOD

0011    GPIOD

0011    GPIOD

0100    GPIOE

0100    GPIOE

0100    GPIOE

0100    GPIOE

0101    GPIOF

0101    GPIOF

0101    GPIOF

0101    GPIOF

0110    GPIOG

0110    GPIOG

0110    GPIOG

0110    GPIOG



 

比如配置GPIOA.0就是将EXTICR0的低4位配置成0000,若配置GPIOB.1就是配置EXTICR0的4到7位,为0001。
这里有一个问题,如果要配置GPIOA.0和GPIOB.0,会引起冲突,不知道是不是分时配置解决的。我用的固体库的方式,不需要考虑这些,呵呵。注意使用固件库时中断复位函数是写在stm32f10x_it.c这个文件里的。


下面结合外部中断附上固件库版本的程序:

主函数里:

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitSructure;


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);          //设置为优先级组2


NVIC_InitSructure.NVIC_IRQChannel = EXTI15_10_IRQn;       //定义外部中断线13中断通道

NVIC_InitSructure.NVIC_IRQChannelPreemptionPriority = 0;        //抢占优先级0

NVIC_InitSructure.NVIC_IRQChannelSubPriority = 0;                       //响应优先级0

NVIC_InitSructure.NVIC_IRQChannelCmd = ENABLE;                               //使能指定通道

NVIC_Init(&NVIC_InitSructure);                                                                      


NVIC_InitSructure.NVIC_IRQChannel = EXTI15_10_IRQn;        //定义外部中断线15中断通道

NVIC_InitSructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitSructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitSructure.NVIC_IRQChannelCmd = ENABLE;                               //使能指定通道

NVIC_Init(&NVIC_InitSructure);


NVIC_InitSructure.NVIC_IRQChannel = EXTI0_IRQn;        //定义外部中断线0中断通道

NVIC_InitSructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitSructure.NVIC_IRQChannelSubPriority = 1;

NVIC_InitSructure.NVIC_IRQChannelCmd = ENABLE;                               //使能指定通道

NVIC_Init(&NVIC_InitSructure);



}


void EXTI_Configuration(void)

{       

  EXTI_InitTypeDef EXTI_InitStructure;                                                    //初始化结构


  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource13);  //指明当前哪个引脚为外部中断触发引脚

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);


  EXTI_ClearITPendingBit(EXTI_Line13);                                      //清除中断标志位 EXTI_Line13对应相应的中断线13

  EXTI_ClearITPendingBit(EXTI_Line15);


  EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt;                            //选择中断模式请求

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;                    //下降沿触发

  EXTI_InitStructure.EXTI_Line = EXTI_Line13|EXTI_Line15;  // 选择待使能的外部中断线

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                                                        // 定义选中线的新状态  使能

  EXTI_Init(&EXTI_InitStructure);                     //把EXIT_InitStructure中的每一个参数按缺省值填入


  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);     //指明当前哪个引脚为外部中断触发引脚

  EXTI_ClearITPendingBit(EXTI_Line0);  

  EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt;                            //选择中断模式请求

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;                    //上升沿触发

  EXTI_InitStructure.EXTI_Line = EXTI_Line0;            // 选择待使能的外部中断线

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                                                        // 定义选中线的新状态  使能

  EXTI_Init(&EXTI_InitStructure);                     //把EXIT_InitStructure中的每一个参数按缺省值填入


}


stm32f10x_it.c这个文件里

void EXTI15_10_IRQHandler(void)

{

              if(EXTI_GetITStatus(EXTI_Line13)!=RESET)

        {               GPIO_WriteBit( GPIOA,GPIO_Pin_8,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_8))); //LED0翻转

                      EXTI_ClearITPendingBit(EXTI_Line13);

  }

             if(EXTI_GetITStatus(EXTI_Line15)!=RESET)

        {               GPIO_WriteBit( GPIOD,GPIO_Pin_2,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_2))); //LED0翻转

                EXTI_ClearITPendingBit(EXTI_Line15);  


  }


}


void EXTI0_IRQHandler(void)

{

          if(EXTI_GetITStatus(EXTI_Line0)!=RESET)

{ GPIO_WriteBit( GPIOA,GPIO_Pin_8,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_8))); //LED0翻转

    GPIO_WriteBit( GPIOD,GPIO_Pin_2,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_2))); //LED0翻转


  EXTI_ClearITPendingBit(EXTI_Line0);    

}

}


关键字:stm32  中断嵌套 引用地址:stm32中断嵌套全攻略

上一篇:stm32与HC-SR04超声波传感器测距
下一篇:keil(MDK-ARM)的调试使用

推荐阅读最新更新时间:2024-11-17 02:52

STM32串口通信USART(二)---DMA方式
刚接触到DMA的时候,一头雾水,只知道方便、快捷,但不知道该怎么使用,后来弄明白原理之后就轻松了很多,但理解的还不是很透,所以希望把自己的理解写出来,和大家分享一下! 形象的说,DMA就像一个快递中转站,负责把数据从始发地搬到目的地,只要他负责的仓库有货,他就开始搬运,没货就等着,除非你把它关了。就像机器人搬东西一样,首先要告诉它从哪搬,搬到哪?东西有多大?需要搬几趟?需要搬运的东西是不是都在一起?搬完后是不是扔在那就行了,还是要放好? 到芯片里,数据就是货物,把数据从一个地方移到另一个地方。你只要告诉它怎么移到就行了,就像控制一个机器人一样。并不是多有的外设都能有机会使用DMA通道,而且,一条通道上被外设使用后,通道上的
[单片机]
<font color='red'>STM32</font>串口通信USART(二)---DMA方式
详解stm32的CAN控制器
首先简单介绍一下CAN总线,关于CAN总线是谁发明的,CAN总线的历史,CAN总线的发展,CAN总线的应用场合,这些,通通不说。这里只是以我个人理解,简单说说CAN通信。CAN总线的端点没有地址(除非自己在帧里定义地址),CAN总线通信不用地址,用标识符,不是单独的谁发给谁,而是,你总是发送给整个网络。然后每个节点都有过滤器,对网络上的传播的帧的标识符进行过滤,自己想要什么样的帧,可以设置自己的过滤器,接收相关的帧信息。如果两个节点同时发送怎么办?这个不用我们担心,CAN控制器会自己仲裁,让高优先级的帧先发。 然后我们可以了解一下stm32的CAN控制器。 如上图所示,stm32有两个can控制器,can1(主),和can2
[单片机]
详解<font color='red'>stm32</font>的CAN控制器
STM32驱动MAX6675读取K型热电偶温度
MAX6675 进行热电偶冷端补偿和数字化 K 型热电偶信号。输出 12 位分辨率、 SPI 兼容、只读的数据。转换器的精度为 0.25℃,最高可读+1024℃,如果使用数据的 8LSB 则温度范围为 0℃到+700℃。 MAX6675模块的原理图: 从网上看到max6675模块并不便宜,正好手头又有MAX6675的芯片于是自己便根据原理图在洞洞板上搭建了一个测试模块 测试结果:将测得的温度信息通过串口1输出到上位机显示 max6675模块部分的测试代码: #include stm32f10x.h #include usart.h #include delay.h #include max6675.h
[单片机]
<font color='red'>STM32</font>驱动MAX6675读取K型热电偶温度
GPRS模块与STM32的数据传输
函数清单和注意事项 (底层驱动部分) 1. IO口初始化:控制 IO 和通讯 IO,控制包括电源控制,复位和低功耗模式,通讯就是串口啦,相信大家应该都很熟悉了。 当然在这个基础上还可以组合出复位的功能,复位在GPRS连接出错的时候会用到。 2. 串口初始化:模块的波特率为115200,8位数据位,1位停止位,没有校验位和流控。 串口还需要两个发送函数,发送一个字节和发送一串字符串的。串口中断处理函数放到后面说。 3. AT指令操作:发送AT指令 设置GPRS数据长度 发送GPRS数据内容 接收GPRS数据内容
[单片机]
STM32与FPGA通信写数据出错问题解决方法
项目中需要使用STM32和FPGA通信,使用的是地址线和数据线,在FPGA中根据STM32的读写模式A的时序完成写入和读取。之前的PCB设计中只使用了8跟数据线和8根地址线,调试过程中没有发现什么问题,在现在的PCB中使用了8根地址线和16根数据线,数据宽度也改成了16位,刚开始是读取数据不正确,后来发现了问题,STM32在16位数据宽度下有个内外地址映射的问题,只需要把FPGA中的设定的地址乘以2在STM32中访问就可以了,但是在写操作的时候会出现写当前地址的时候把后面的地址写成0的情况,比如说我给FPGA中定义的偏移地址0x01写一个16位数据,按照地址映射,在STM32中我把地址写入0x02,。实际测试发现这个地址上的数据是
[单片机]
STM32单片机-CorTexM3位带操作的理解
一、STM的位带 STM32支持了位带操作(bit_band),有两个区中实现了位带。其中一个是SRAM 区的最低1MB范围,第二个则是片内外设区的最低1MB范围。这两个区中的地址除了可以像普通的RAM一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个32 位的字。 每个比特膨胀成一个32 位的字,就是把1M扩展为32M , 于是RAM地址 0X200000000(一个字节)扩展到8个32 位的字,它们是:(STM32中的SRAM依然是8位的,所以RAM中任一地址对应一个字节内容) 0X220000000 ,0X220000004,0X220000008,0X22000000C,0X220000010,
[单片机]
<font color='red'>STM32</font>单片机-CorTexM3位带操作的理解
一文详解STM32串口通信
1 什么是串口通讯? 串行通讯是指仅用一根接收线和一根发送线就能将数据以位进行传输的一种通讯方式。尽管串行通讯的比按字节传输的并行通信慢,但是串口可以在仅仅使用两根线的情况下就能实现数据的传输。 典型的串口通信使用3根线完成,分别是地线、发送、接收。由于串口通信是异步的,所以端口能够在一根线上发送数据同时在另一根线上接收数据。串口通信最重要的参数是波特率、数据位、停止位和奇偶的校验。对于两个需要进行串口通信的端口,这些参数必须匹配,这也是能够实现串口通讯的前提。如下是串行通讯示数据传输意图。 2 串口通讯的通讯协议 最初数据是模拟信号输出简单过程量,后来仪表接口出现了RS232接口,这种接口可以实现点对点的通信方式,但这
[单片机]
一文详解<font color='red'>STM32</font>串口通信
基于STM32 MCU的太阳能-LED街灯解决方案
随着化石类能源的日益减少,以及温室气体的过度排放导致全球变暖问题越来越受到重视,人们一方面在积极开发各类可再生新能源,另一方面也在倡导节能减排的绿色环保技术。太阳能作为取之不尽、用之不竭的清洁能源,成为众多可再生能源的重要代表;而在照明领域,寿命长、节能、安全、绿色环保、色彩丰富、微型化的LED固态照明也已被公认为世界一种节能环保的重要途径。太阳能-LED街灯同时整合了这两者的优势,利用清洁能源以及高效率的LED实现绿色照明。 本文介绍的太阳能-LED街灯方案,能自动检测环境光以控制路灯的工作状态,最大功率点追踪(MPPT)保证最大太阳能电池板效率,恒电流控制LED,并带有蓄电池状态输出以及用户可设定LED工作时间等
[电源管理]
基于<font color='red'>STM32</font> MCU的太阳能-LED街灯解决方案
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved