历史上的今天
返回首页

历史上的今天

今天是:2025年01月02日(星期四)

正在发生

2020年01月02日 | stm32中断嵌套全攻略

2020-01-02 来源:eefocus

断断续续学习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);    

}

}


推荐阅读

史海拾趣

Alliance Memory公司的发展小趣事

Alliance Memory是一家专注于存储器产品的公司,以下是其发展历程的五个相关故事:

  1. 成立与发展初期: Alliance Memory成立于2006年,总部位于美国南卡罗来纳州。公司专注于提供DRAM(动态随机存取存储器)和SRAM(静态随机存取存储器)解决方案。在成立之初,公司致力于与全球供应链建立紧密的合作关系,以确保产品的质量和可靠性。通过与先进制造厂商合作,Alliance Memory能够提供高品质的存储器产品,满足客户的需求。

  2. 扩大产品线: 随着市场需求的增长,Alliance Memory不断扩大其产品线,涵盖各种容量和类型的DRAM和SRAM产品。公司不断改进和优化其制造工艺,并与全球领先的技术合作伙伴密切合作,以确保产品的性能和稳定性。通过不断提供新的存储器解决方案,Alliance Memory成功吸引了更多的客户,并在行业中树立了良好的声誉。

  3. 全球市场拓展: Alliance Memory的产品销售遍布全球各个地区,包括美国、欧洲、亚洲等市场。公司与全球各地的分销商和代理商建立了稳固的合作关系,以扩大其产品的市场份额。通过在全球范围内提供及时和高效的客户服务,Alliance Memory不断增强了其在国际市场上的竞争力。

  4. 技术创新与研发投入: 作为一家技术驱动型公司,Alliance Memory不断投入研发和创新,以提供最先进的存储器产品。公司的研发团队与业界领先的技术合作伙伴密切合作,不断推出具有竞争优势的新产品。通过持续的技术创新,Alliance Memory得以不断满足客户不断增长的需求,并保持在行业中的领先地位。

  5. 可持续发展与社会责任: 除了致力于业务发展,Alliance Memory还积极履行企业社会责任,关注环境保护和社会公益事业。公司采取了一系列可持续发展的举措,包括节能减排、资源循环利用等,努力降低对环境的影响。此外,Alliance Memory还参与各种公益活动,支持教育、环保和社区发展等领域的项目,为社会做出积极贡献。

Compact公司的发展小趣事

随着电子市场的日益成熟,Compact公司意识到单纯的技术创新已不足以支撑其长期发展。于是,公司开始积极寻求市场拓展和战略合作的机会。通过与国内外知名企业建立合作伙伴关系,Compact公司成功将其产品打入国际市场,进一步扩大了市场份额。同时,通过与上下游企业的紧密合作,Compact公司实现了产业链的整合,提高了整体运营效率。

Eurotechnique公司的发展小趣事

随着全球对环保和可持续发展的关注度不断提高,Eurotechnique也开始注重环保和可持续发展。公司采用环保材料和生产工艺,降低产品对环境的影响。同时,Eurotechnique还积极参与环保公益活动,推动电子行业的绿色发展。此外,公司还致力于研发更加节能、环保的产品,以满足市场的需求。

ATP [ATP Electronics]公司的发展小趣事

ATP深知,优质的产品需要优质的服务来支撑。因此,公司一直致力于提升客户服务水平,为客户提供最优质的产品、最具竞争力的价格和最优质的服务。ATP通过建立完善的售后服务体系,及时解决客户在使用过程中遇到的问题,赢得了客户的信任和好评。同时,公司还积极开展市场调研,了解客户需求,不断优化产品和服务,以满足市场的不断变化。

这五个故事展示了ATP Electronics在电子行业中的发展历程和取得的成就。通过技术创新、推出工业级产品、践行环保理念、实施全球化战略以及提升优质服务,ATP成功地在激烈的市场竞争中脱颖而出,成为了闪存卡市场的领军企业。

乐鑫(espressif)公司的发展小趣事

乐鑫科技自创立之初,就致力于物联网(IoT)领域的芯片设计和技术创新。公司凭借其独特的芯片设计能力和连接技术,成功开发了一系列具有竞争力的产品,为全球开发者提供了高效、可靠的物联网解决方案。乐鑫科技始终坚持以技术创新为核心,通过自主研发和持续投入,不断提升产品的性能和竞争力。

Datalogic公司的发展小趣事

随着公司业务的不断发展,Datalogic意识到全球市场的巨大潜力。从2000年代开始,公司加快了全球化步伐,通过设立销售和服务中心,覆盖了全球100多个国家。这种全球布局不仅使Datalogic能够更好地服务全球客户,还为公司带来了更多的市场机会。

问答坊 | AI 解惑

有没有纯数字的精确测量信号时间间隔的方法?

十个ns左右的误差范围啊,疯了都,目前我想到两个方法,一个是精确扩展计数时间,一个是多测几次,牺牲测量速度,不好弄…

查看全部问答>

HI-TECH C V9.70 和谐文件

HI-TECH C Compiler for PIC10-12-16 MCUs V9.70 已经测试过,破解成功! 1,先安装HI-TECH C Compiler for PIC10-12-16 MCUs V9.70  安装路径为默认路径 \"C 盘下\" 激活PICC 45天试用版! 2,破解,先写入注册文件,运行破解文件, ...…

查看全部问答>

DDRAW程序问题,在全屏方式下,用创建程序的方式打开一个程序后,程序的界面显示不出来,LCD上显示的还是DDRAW的画面

请问如何解决这个问题 // // Copyright (c) Microsoft Corporation.  All rights reserved. // // // Use of this source code is subject to the terms of the Microsoft end-user // license agreement (EULA) under which you l ...…

查看全部问答>

求助 :最近学习uc/os-ii 用的任哲写的《嵌入式实时操作系统uc/os-ii原理及应用》编译无法通过

最近学习uc/os-ii  用的任哲写的《嵌入式实时操作系统uc/os-ii原理及应用》,把他书中的源码在网上找到了。书中是用的BORLAND C++ 3.1编译的,我用borland c v3.1 dos 界面下直接建立工程文件编译,可是搞了很久编译都无法通过,而且试了 ...…

查看全部问答>

wince usb 驱动问题

我在看wince5.0 usb从驱动源代码具体位置是:/%wince500boot%/public/common/oak/usbfn 这个文件下有3个文件夹: 1.CLASS文件: RNDIS,SERIAL, STORAGE三个文件夹 2.CONTROLLER文件: MDD,NET2280 3.UFNCLIENLIB文件 请问这三个文件都有什 ...…

查看全部问答>

求助 AT89S51与C8051F单片机有什么区别啊?(急)

   各位前辈,我是一名学生菜鸟,要用单片机做采集器,遇到了这么一个问题,AT89S51与C8051F单片机有什么区别,请各位帮忙解决,谢谢!…

查看全部问答>

有木有CH4浓度传感器啊,急求资料,帮忙呀

最还好有单片机程序代码,电路图等等,越全越好.谢谢啊 …

查看全部问答>

4-20ma转换成0-5V

各位高手,本人摸电只是懂点基本的.想请教大家个问题.传感器输出的4-20ma如何转换成0-5V.我以前一直就是用250欧电阻将4-20ma转换成1-5V,再进行A/D转换,感觉这样处理没有0-5V方便.比如4-20ma表示0-50度的温度,0V的时候就表示温度是0度,5V的时候就表示 ...…

查看全部问答>

MSP430 LaunchPad学习笔记之uart

一、摘要本应用报告介绍了如何使用Timer_A实现UART功能。该包括例子是专门为MSP430x11x家庭,但他们能适应任何MSP430家族成员纳入Timer_A。使用硬件UART的功能在Timer_A功能和软件。执行是半双工的,事件驱动,它支持的8N1波特率协议从1200到115200 ...…

查看全部问答>

求一个G2452 SPI模式传输的例程

如题,望大家帮忙,谢谢!!…

查看全部问答>