前言:这一节以及后面的定时器部分都是学习所有的单片机时的最重要的部分,我也花了很多时间去理解手册和程序,我争取尽量全面并且细致的记录我的体会。


一、中断的概念

这里就省略了,相信你学过单片机就会懂。


二、stm32里面的NVIC是什么

NVIC的中文意思是嵌套向量中断控制器,控制着中断的相关功能(其中包括中断源、抢占优先级、响应优先级、中断的使能与失能),具体的配置方法后面会提到。


三、stm32里面的优先级

在stm32中,一个中断的优先级由两部分决定,一个是抢占式优先级,还有一个是响应优先级。两个优先级组成了一个4位的控制字。
如图:

那么我们就会问,这有四位,那两个优先级各占多少位。就像图中所展示的,抢占式优先级(黄色)可以沾满四位,也可以一位都不占,如果占满四位,则抢占式优先级共有0-15这些等级,占满2位,就有0-3这些等级。同理响应优先级也是这样。分配他们各占多少位的函数为:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);后面这个数字代表的是抢占式优先级的位数

抢占式优先级和响应优先级分析

这两个优先级中,抢占式优先级占主导地位,抢占式优先级高的中断会优先打断主程序或者另外一个中断程序
1.如果两个中断的抢占式优先级一样高,当两个中断同时发生时,响应优先级高的先发生,完了再发生另一个。但是要注意,响应优先级高的中断不会打断低的中断,也就是当一个高响应优先级的中断来时,如果正在执行一个低的中断,他不会打断他,而是等待低的执行完在执行。也就是说只有高抢占式优先级可以阻断。


四,中断运用过程

1.中断的相关配置(其中包括很多很多步骤)

2.设置优先级分组,也就是前面提到的两个优先级的位数

3.书写中断服务函数

注意:第一个步骤对应一个总的函数my_exti_init();第二步骤单独写在主函数中,第三个步骤的中断服务函数直接写在头文件中不写在第一个函数中,不用写在主函数中。总的来说这三个步骤是指主函数中的步骤。
这三个步骤都在后面详细分析


五、配置过程详细分析

首先需要知道,stm32f4中有23个外部中断,也就是有23个外部中断线路,但是只有0-15线是用来连到io口的(平时没有连上,需要用库函数来连上

到这里你一定会发现,0-15这有16条线,而stm32刚好每个端口有16个针脚,于是你自然也会想到阵脚的编号肯定是与中断线路编号刚好对应上的,事实上你很聪明,就是这样。至于是哪一个端口的针脚,就需要库函数配置。

配置步骤一:因为用到io口,所以首先要配置io口,就是打开时钟,设为输入模式等操作,至于为上啦还是下拉就看外设了,因为这里外设为按键,就好判断。

配置步骤二:像前面说的,要将中断线路和io口连接起来,用到的函数是:

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);//这里就是将A端口的0管脚接在0线路上,用到几个线路就写多少个这个函数

但是SYSCFG是接在APB2总线上的,所以在SYSCFG_EXTILineConfig之前需要用RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);使能SYSCFG。

配置步骤三:配置NVIC(用到多少中断就写多少组)

NVIC_InitTypeDef NVIC_InitStructure;//声明一个结构体NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;//中断通道,根据线路修改数字
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//设置抢占式优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;//设置响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//通道使能
NVIC_Init(&NVIC_InitStructure);//最后在申明下

配置步骤四:初始化外部中断EXTI(用到多少中断就写多少组)

EXTI_InitTypeDef EXTI_InitStructure;//声明结构体EXTI_InitStructure.EXTI_Line=EXTI_Line0;//选择线路
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//选模式,这里为中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//上升沿触发,下降沿为Falling
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//使能
EXTI_Init(&EXTI_InitStructure);

配置步骤五:编写中断服务函数(写在头文件中)
格式:

void EXTI0_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line0)==1)//看是否确实触发了中断,值为1就为触发了{delay_ms(10);//消抖   if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1)//再一次确定,只不过这一次是确定按钮是否按下{while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0));GPIO_ResetBits(GPIOF,GPIO_Pin_10);//open the led}}EXTI_ClearITPendingBit(EXTI_Line0);//注意,这一步非常重要,经常容易忘记,写在中断服务函数的最后。用于清空中断的状态,以便于下次再次使用

注意:中断函数名不是自己取得,是有规定的


线路一用第一个,线路二用第二个,但是线路5到9用的是一样的倒数第二个,线路10-15用的最后一个。


完整程序:
exti.c

#include "exti.h"void my_exti_init()
{NVIC_InitTypeDef NVIC_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);//ÖжÏÏß·µÄÓ³É䣬¾ÍÊÇ°ÑÄĸö¶Ë¿Ú¿´×öÖжÏÊäÈëSYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2);//ÖжÏÏß·µÄÓ³É䣬¾ÍÊÇ°ÑÄĸö¶Ë¿Ú¿´×öÖжÏÊäÈëSYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3);//ÖжÏÏß·µÄÓ³É䣬¾ÍÊÇ°ÑÄĸö¶Ë¿Ú¿´×öÖжÏÊäÈëSYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);//ÖжÏÏß·µÄÓ³É䣬¾ÍÊÇ°ÑÄĸö¶Ë¿Ú¿´×öÖжÏÊäÈëNVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel=EXTI2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStructure);//Line0EXTI_InitStructure.EXTI_Line=EXTI_Line0;EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//ģʽÅäÖÃΪÖжÏģʽEXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;EXTI_InitStructure.EXTI_LineCmd=ENABLE;EXTI_Init(&EXTI_InitStructure);//Line2EXTI_InitStructure.EXTI_Line=EXTI_Line2;EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//ģʽÅäÖÃΪÖжÏģʽEXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd=ENABLE;EXTI_Init(&EXTI_InitStructure);//Line3EXTI_InitStructure.EXTI_Line=EXTI_Line3;EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//ģʽÅäÖÃΪÖжÏģʽEXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd=ENABLE;EXTI_Init(&EXTI_InitStructure);//Line4EXTI_InitStructure.EXTI_Line=EXTI_Line4;EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//ģʽÅäÖÃΪÖжÏģʽEXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd=ENABLE;EXTI_Init(&EXTI_InitStructure);
}void EXTI0_IRQHandler(void)//ÖжÏÏß·0
{if(EXTI_GetITStatus(EXTI_Line0)==1)//¿´ÊÇ·ñȷʵ´¥·¢ÁËÖжϣ¬¼´¿´°´Å¥ÊÇ·ñÕæµÄ°´Ï£¬µ«×¢ÒâÕâÀïµÄ1²»ÊÇÖ¸°´Å¥µÄ״̬£¬ÊÇÖ¸ÖжϵÄ״̬{delay_ms(10);   if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1){while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0));GPIO_ResetBits(GPIOF,GPIO_Pin_10);//open the led}}EXTI_ClearITPendingBit(EXTI_Line0);
}void EXTI2_IRQHandler(void)//ÖжÏÏß·¶þ
{if(EXTI_GetITStatus(EXTI_Line2)==1)//¿´ÊÇ·ñȷʵ´¥·¢ÁËÖжϣ¬¼´¿´°´Å¥ÊÇ·ñÕæµÄ°´Ï£¬µ«×¢ÒâÕâÀïµÄ1²»ÊÇÖ¸°´Å¥µÄ״̬£¬ÊÇÖ¸ÖжϵÄ״̬{delay_ms(10);   if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)));GPIO_SetBits(GPIOF,GPIO_Pin_8);}}EXTI_ClearITPendingBit(EXTI_Line2);
}void EXTI3_IRQHandler(void)//ÖжÏÏß·Èý
{if(EXTI_GetITStatus(EXTI_Line3)==1)//¿´ÊÇ·ñȷʵ´¥·¢ÁËÖжϣ¬¼´¿´°´Å¥ÊÇ·ñÕæµÄ°´Ï£¬µ«×¢ÒâÕâÀïµÄ1²»ÊÇÖ¸°´Å¥µÄ״̬£¬ÊÇÖ¸ÖжϵÄ״̬{delay_ms(10);   if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)));GPIO_SetBits(GPIOF,GPIO_Pin_10);//turn off the led}}EXTI_ClearITPendingBit(EXTI_Line3);
}void EXTI4_IRQHandler(void)//ÖжÏÏß·ËÄ
{if(EXTI_GetITStatus(EXTI_Line4)==1)//¿´ÊÇ·ñȷʵ´¥·¢ÁËÖжϣ¬¼´¿´°´Å¥ÊÇ·ñÕæµÄ°´Ï£¬µ«×¢ÒâÕâÀïµÄ1²»ÊÇÖ¸°´Å¥µÄ״̬£¬ÊÇÖ¸ÖжϵÄ״̬{delay_ms(10);   if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0){while(!(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)));GPIO_ResetBits(GPIOF,GPIO_Pin_8);}}EXTI_ClearITPendingBit(EXTI_Line4);
}

main.c

int main()
{RCC_HSE_Config(8,336,2,7);Beep_Init();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);SysTick_Init(168);key_init();LED_Init();my_exti_init();while(1){}}

说明:去前面一节的按钮实验现象虽然相同,但是原理不同,前面的按钮实验是通过不断检测按钮的状态,而这里是用的中断,满足触发条件自动执行。

stm32之中断系统相关推荐

  1. 基于STM32外部中断系统的秒表的设计

    1.项目简介 硬件平台:基于某STM32F103开发板. 软件平台:KEIL5 MDK V5.38,基于LCD屏幕库函数例程库为模板,添加了外部中断,定时器中断相关代码,稍加修改而成. 功能简介:有三 ...

  2. stm32中断优先级_STM的中断系统

    STM32的中断系统 STM32具有十分强大的中断系统,将中断分为了两个类型:内核异常和外部中断.并将所有中断通过一个表编排起来,下面是stm32中断向量表的部分内容: 上图-3到6这个区域被标黑了, ...

  3. STM32笔记 (七)中断系统与NVIC嵌套向量中断控制器

    简介 STM32拥有一个强大的中断系统,几乎所有外设都能产生中断,对于F103系列的单片机,ARM公司在Cortex‐M3 的内核水平上搭载了一个异常响应系统(异常就是中断), 支持为数众多的系统异常 ...

  4. 带你了解STM32中断系统

    4.3 中断 中断是指计算机运行过程中,出现某些意外情况需要计算机处理时,技能能自动暂停正在运行的程序并转入处理新情况的程序,处理完毕后又返回原先被暂停的程序继续运行的功能. 举一个生活例子来说明:小 ...

  5. ARM(IMX6U)ARM Cortex-A7中断系统(GPIO按键中断驱动蜂鸣器)

    参考:Linux之ARM Cortex-A7 中断系统详解 作者:一只青木呀 发布时间: 2020-09-16 16:07:22 网址:https://blog.csdn.net/weixin_453 ...

  6. Linux(十二)中断系统

    STM32 的中断系统主要有以下几个关键点: ①. 中断向量表. ②. NVIC(内嵌向量中断控制器). ③. 中断使能. ④. 中断服务函数. 中断向量表 中段向量表就是说明都有什么中断,这些中断服 ...

  7. 深入浅出地理解STM32中的中断系统——从原理到简单工程示例——保姆级教程

    深入浅出地理解STM32中的中断系统 一.什么是中断?什么是异常? 二.如何管理中断? 三.NVIC 1 NVIC 特点 2 中断优先级 (1) 优先级分组 3 中断向量表 4 中断服务函数 (1)中 ...

  8. STM32学习笔记(三)丨中断系统丨EXTI外部中断(对射式红外传感器计次、旋转编码器计次)

    本篇文章包含的内容 一.中断系统 1.1 中断的定义 1.2 中断优先级 1.3 中断的嵌套 1.4 STM32中的中断系统 1.4.1 STM32的中断资源 1.4.2 嵌套中断向量控制器 NVIC ...

  9. STM32中断系统的基本概念

    STM32中断系统 基本概念 一.日常生活中的中断 *图片来源网络 二.处理器中的中断 在处理器中,中断是一个过程,CPU在正常运行的过程中,遇到内部/外部的紧急事情需要处理,那么这个时候先终止当前程 ...

最新文章

  1. webstorm命令行提示‘node‘ 或‘npm‘不是内部或外部命令,也不是可运行的程序
  2. 求求你了,配个GC日志呗,不然咋分析故障原因
  3. 如何创建一个定时管理的页面
  4. Azure 内容审查器之羞羞图审查
  5. 2020 CSP-S 游记
  6. 从零开始nodejs系列文章
  7. android scrollview焦点,scrollview里面的edittext,当它获得焦点时如何滚动到edittext
  8. 【Python】mmSegmentation语义分割框架教程(自定义数据集、训练设定、数据增强)
  9. 如何上好网课 — 老师录课和在线上课教学经验谈
  10. php没有输出报错信息的解决
  11. win7录屏_谁说Windows7没有自带录屏功能?教你一招轻松录制,不会用可惜了
  12. coff2omf matlab,OMF和COFF格式有什么区别?
  13. linux tc 限速,TC限速
  14. 解决阿里云Workbench登录失败
  15. 错误: 找不到或无法加载主类 com.sxt.ceshi.Demo166
  16. 深度学习跑项目的注意事项
  17. 7-3 计算平均成绩(15 分)(转载)
  18. 对小样本数据进行数据增强
  19. web应用商城部署(gpmall)
  20. 【装机至尊】《中关村GHOSTXPSP3纯净装机自选DVD特别版V201011A》(海量驱动)

热门文章

  1. 【实战】python以及opencv实现信用卡的数字识别
  2. 在计算机中 汉字系统把一个汉字表示为,计算机问题汉字系统在计算机内把一个汉字表示 – 手机爱问...
  3. Python 把csv文件转换为excel文件
  4. (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  5. 【MySQL基础知识】查询、过滤数据关键字
  6. RIP1实验1(实现不同路由器 不同PC机之间的通信)
  7. java 解决倒水问题
  8. Eclypse-Z7 + Zmod ADC 1410 基础环境搭建(vivado部分)
  9. 小程序实现图片上传,并获取fileID存入数据库
  10. 平安居家养老服务上市