开始学习外部中断的基本知识

中断优先级分组管理

CortexM3内部支持256个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有 256
级的可编程中断设置。STM32F1系列有 84 个中断,包括 16 个内核中断和 68 个可屏蔽中断,具有 16 级可编程的中断优先级。而我们常用的就是这 68 个可屏蔽中断, 但是 STM32 的 68 个可屏蔽中断,在 STM32F103 系列
上面,可屏蔽中断又只有 60 个(在 107 系列才有 68 个)。

中断管理办法:
首先,对STM32中断进行分组,分成5个组:组0~4,该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。 同时,对每个中断设置一个抢占优先级和一个响应优先级。
有4个位来分配抢占优先级和响应优先级。
下面是AIRCR 中断分组设置表

AIRCR[10: 8] bit[7: 4]分配情况 分配结果
0 111 0: 4 0 位抢占优先级, 4 位响应优先级
1 110 1: 3 1 位抢占优先级, 3 位响应优先级
2 101 2: 2 2 位抢占优先级, 2 位响应优先级
3 100 3: 1 3 位抢占优先级, 1 位响应优先级
4 011 4: 0 4 位抢占优先级, 0 位响应优先级

每个中断,可以设置抢占优先级为 0~7,响应优先级为 1 或 0。抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。抢占优先级相同的中断,当两个中断同时发生,哪个响应优先级高,哪个先执行。

这里需要注意两点:第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。

中断优先级分组设置函数NVIC_PriorityGroupConfig

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

分组可以在下面选

(((GROUP) == NVIC_PriorityGroup_0) ||
((GROUP) == NVIC_PriorityGroup_1) || \
((GROUP) == NVIC_PriorityGroup_2) || \
((GROUP) == NVIC_PriorityGroup_3) || \
((GROUP) == NVIC_PriorityGroup_4))

设置好了系统中断分组,那么对于每个中断我们又怎么确定他的抢占优先级和响应优先级呢?通过中断初始化函数void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)

解析一下上式用到的结构体NVIC_InitTypeDef

typedef struct
{
uint8_t NVIC_IRQChannel;
uint8_t NVIC_IRQChannelPreemptionPriority;
uint8_t NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;

成员变量的含义
NVIC_InitTypeDef 结构体中间有三个成员变量,这三个成员变量的作用是:
NVIC_IRQChannel:定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到每个中断对应的名字。例如 USART1_IRQn。
NVIC_IRQChannelPreemptionPriority:定义这个中断的抢占优先级别。
NVIC_IRQChannelSubPriority:定义这个中断的子优先级别。
NVIC_IRQChannelCmd:该中断是否使能。

比如我们要使能串口 1 的中断,同时设置抢占优先级为 1,子优先级位 2,初始化的方法是

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口 1 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化 NVIC 寄存器

NVIC 寄存器结构体NVIC_Type

typedef struct
{__IO uint32_t ISER[8]; /*!< Interrupt Set Enable Register */uint32_t RESERVED0[24];__IO uint32_t ICER[8]; /*!< Interrupt Clear Enable Register */uint32_t RSERVED1[24];__IO uint32_t ISPR[8]; /*!< Interrupt Set Pending Register */uint32_t RESERVED2[24];__IO uint32_t ICPR[8]; /*!< Interrupt Clear Pending Register */uint32_t RESERVED3[24];__IO uint32_t IABR[8]; /*!< Interrupt Active bit Register */uint32_t RESERVED4[56];__IO uint8_t IP[240]; /*!< Interrupt Priority Register, 8Bit wide */uint32_t RESERVED5[644];__O uint32_t STIR; /*!< Software Trigger Interrupt Register */
} NVIC_Type;

外部中断

STM32每一个IO口都可以作为外部中断输入。
STM32的中断控制器支持19个外部中断/事件请求。
线0~15:对应外部IO口的输入中断

每个外部中断线可以独立配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。
GPIO的管脚和中断线有一个对应关系,每个中断线最多对应7个IO口。以线0为例,它对应了GPIOA.0,GPIOB.0,GPIOC.0,GPIOD.0,GPIOE.0,GPIOF.0,GPIOG.0。中断线每次只能连接到一个IO口,所以需要在7个IO口中进行选择。

映射关系

图片来源:正点原子

外部中断的一般配置步骤
初始化IO口为输入GPIO_Init()
开启IO口复用时钟RCC_APB2PeriphClockCmd(RCC_APB2Perith_AFIO,ENABLE);
设置IO口与中断线的映射关系void GPIO_EXTILineConfig()
初始化线上中断,设置触发条件等EXTI_Init()
配置中断分组(NVIC),并使能中断NVIC_Init()
编写中断服务程序EXTIx_IRQHandler()
清除中断标志位EXTI_ClearTPendingBit()

IO口和中断线的映射
在库函数中,配置 GPIO 与中断线的映射关系的函数 GPIO_EXTILineConfig()来实现的:
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
该函数将 GPIO 端口与中断线映射起来,使用范例是:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
将中断线 2 与 GPIOE 映射起来,即GPIOE.2 与 EXTI2 中断线连接了。我们要是用的是PE4(对应的是KEY0),所以这里是

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);

然后我们对中断进行初始化

  //初始化中断EXTI_InitStructure.EXTI_Line=EXTI_Line4;//线号EXTI_InitStructure.EXTI_LineCmd=ENABLE;//使能EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//中断还是事件EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿触发EXTI_Init(&EXTI_InitStructure);

这里笔者有个问题?这里为什么选择下降沿触发呢?原来是因为KEY0接的是低电平,所以让它有效的话,必须是到低电平。

配置中断分组NVIC

 //NVIC中断分组的设置NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE:NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;NVIC_Init(&NVIC_InitStructure);

前五步的初始化函数如下

 void EXITX_Init(){EXTI_InitTypeDef EXTI_InitStructure;//结构体变量NVIC_InitTypeDef NVIC_InitStructure;KEY_Init();//初始化GPIORCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//key0对应PE4//PE4映射到中断线4GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4 );//初始化中断EXTI_InitStructure.EXTI_Line=EXTI_Line4;//线号EXTI_InitStructure.EXTI_LineCmd=ENABLE;EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//中断EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿触发EXTI_Init(&EXTI_InitStructure);//NVIC中断分组的设置NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE:NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;NVIC_Init(&NVIC_InitStructure);}

STM32F1迷你板外部中断相关推荐

  1. hal库开启中断关中断_「正点原子NANO STM32开发板资料连载」第十章 外部中断实验...

    1)实验平台:ALIENTEK NANO STM32F411 V1开发板 2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十章 外 ...

  2. OK6410开发板学习之外部中断(按键点亮led和蜂鸣器)

    中断在嵌入式里面是很常见的一个功能了.通过这个功能,可以让CPU减轻很多负担,不用不断的查询设备的状态.提高了CPU的效率. 中断的大体过程如下: 中断源检测中断信号产生,然后将中断信号发送给中断控制 ...

  3. gd32f303 设计中断优先级_ALIENTEK 阿波罗 STM32F767 开发板资料连载第九章 外部中断实验...

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第九章 外部中断实验 这 ...

  4. 【MM32F5270开发板试用】GPIO输入+EXTI外部中断例程demo试用

    本篇文章来自极术社区与灵动组织的MM32F5270开发板评测活动,更多开发板试用活动请关注极术社区网站.作者:Zeee 前言: 首先,感谢灵动微电子与极术社区给予宝贵的试用机会.借助本次对Plus-F ...

  5. STM32F1笔记(五)外部中断EXTI

    STM32的每个IO都可以作为外部中断的中断输入口. STM32F103的中断控制器支持19个外部中断/事件请求.每个中断设有状态为,每个中断/事件都有独立的触发和屏蔽设置. STM32F103的19 ...

  6. 外部中断---STM32F1

    外部中断概述 STM32的中断控制器支持19个外部中断/事件请求: 线0-15:对应外部IO口的输入中断 线16:连接到PVD输出 线17:连接到RTC闹钟事件 线18:连接到USB唤醒事件 STM3 ...

  7. ATmega16开发板教程(5)——外部中断

    ​6.外部中断 这里主要编写外部中断0和1的边沿触发,通过LED状态显示. 外部中断0 外部中断我们要知道的是:①如何触发?上升沿.下降沿还是高低电平:②外部中断使能:③中断服务函数的编写. AVR提 ...

  8. 【单片机学习笔记】(31):串口调试技巧、TFT触摸屏初识别、stm32F4与F1对比使用(全系列初始化概览)、YSF4的光耦隔离保护、外部中断与定时器消抖相结合的按键检

    串口调试技巧 可以将调试时会用到,但实际演示是不需要用到的代码用 #if xxx   //这里放调试代码 #endif xxx是 一个宏定义,如果等于0则不编译相关代码,如果为1则编译相关代码 TFT ...

  9. 一起学mini2440裸机开发(十)--mini2440外部中断实验

    我今天一整天都在试着将TQ2440的那种处理中断的方法(即安装中断向量表)移植到MDK中的mini2440,但是一直没成功,这种方法一直没成功,后来又想,还是先从最简单的开始吧,就是不利用中断向量表, ...

最新文章

  1. The FBX plug-in does not support objects set to By Object mode in the Object Properties Display
  2. 使用.NET中的Action及Func泛型委托
  3. 手机淘宝轻店业务 Serverless 研发模式升级实践
  4. IAR在写结构体时不提示_智能物流装车系统的结构优化与改进
  5. 转]从一个男人关注的事情上 可以看出他的修养和抱负
  6. SQL Server cast() 批量更新列内容
  7. arduino串口输入改变模式模块
  8. atitit 编程语言课程 v1 t55.docx 1. 编程语言概念(what 5 1.1. 自然语言与编程语言的关系 5 1.2. 开发中常用的编程语言 5 1.3. 编程语言代际 5 1.4
  9. python xps_XPS 15 9560 安装 Ubuntu 18.04
  10. 【推荐】实现跟随鼠标移动的浮动提示框、气泡框、Tip效果
  11. httpd三种MPM的原理剖析
  12. AcWing 145 超市
  13. 手机wps怎么改html文件后缀名,手机WPS如何制作个人简历 WPS一键修改文档重命名方法分享...
  14. 基于MPC的自适应巡航控制
  15. 为什么感觉期货交易越做越难?
  16. 《C++ Primer》学习笔记
  17. spring中tx:advice/tx:advice是什么意思?作用是什么?谁能简单说下
  18. PAT甲级1062 Talent and Virtue
  19. iOS URL Schemes 使用详解 什么是 URL Schemes
  20. 安装skimage报错解决方案

热门文章

  1. 并查集(disjoint set)的实现及应用
  2. 代码坏味道 - 耦合
  3. doctype的种类
  4. 解決BufferedReader读取UTF-8文件中文乱码(转)
  5. 作品[RFileRead/WriteStream 练习] for s60 fp2
  6. [CPP]--Unicode 字符编码
  7. 在WINDOW 系统下如何用批处理命令生成代码
  8. arm交叉编译器gnueabi、none-eabi、arm-eabi、gnueabihf的区别
  9. 我的书法记录--2018.12.2
  10. LTE轻松进阶之帧结构