STM32的中断介绍
目录
一、STM32中断应用概览
(1)简介
(2)中断编程的顺序:
1.使能中断请求:
2.中断优先级分组:
3.配置NVIC寄存器,初始化NVIC_InitTypeDef;
4.编写中断服务函数
二、EXTI—外部中断/事件控制器
(1)简介
(2)EXTI结构图
(3)初始化结构体成员
(4)程序设计:
1.初始化要连接到EXTI的GPIO。
2.初始化EXTI用于产生中断/事件
3.初始化NVIC,用于处理中断
4.编写中断服务函数
5.main函数
一、STM32中断应用概览
(1)简介
STM32 中断非常强大,每个外设都可以产生中断,所以中断的讲解放在哪一个外设里面去讲都不合适,这里单独抽出一章来做一个总结性的介绍。
中断:把正常正在运行的程序打断,运行中断服务函数,运行完之后再回到主程序,与51大体相仿。
外部中断,体现在外设水平,系统异常,体现在内核水平。下面,中断就是异常,异常就是中断。
以上向量表中,灰色标住的是体现在内核水平的(异常),其余的是外设水平的(外部中断)。
中断由NVIC这个外设来控制。
NVIC:嵌套向量中断控制器,属于内核外设,管理着包括部分内核和片上所有外设的中断相关的功能。 两个重要的库文件:core_cm3.h(定义所有内核上面的寄存器,NVIC寄存器就在这里面)和misc.h(相关的函数)。
对于中断而言,最重要的是优先级,由NVIC->IPRx(中断优先级寄存器)设定。打开内核寄存器的手册,
这个表里面的0-80对应着向量表里面外部中断的位置0-59,每一位都有8位位宽,真正起作用的只有4位。
函数:
NVIC_SetPriority (IRQn_Type IRQn, uint32_t priority)// core_cm3.h 1586行
两个形参:中断号和优先级。中断号对应手册向量表的位置编号。
配置的时候先判断中断号是否大于0,小于0是内核的中断;大于0是外部中断。如果是外部中断,让优先级左移4位。如果是小于0,就配置另一个寄存器,SCB->SHP。
(2)中断编程的顺序:
1-使能中断请求
2-配置中断优先级分组
3-配置NVIC寄存器,初始化NVIC_InitTypeDef;
4-编写中断服务函数
1.使能中断请求:
这个与具体外设相关。以串口为例,发送数据完成之后,产生一个中断。我们去具体寄存器寻找,在控制寄存器 1(USART_CR1)里面有一位如下图,将这一位置即可。
2.中断优先级分组:
内核和外设的寄存器的优先级哪个更高取决于优先级分组,这个则是由寄存器SCB->AIRCR:PRIGROUP[10:8] 来配置的。
函数:
NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) // misc.c 96行
优先级分组1:一个位表示主优先级,剩下三个位表示子优先级。
判断优先级:分组>主优先级>子优先级.如果都相同,则看硬件中断编号(中断向量表)。
3.配置NVIC寄存器,初始化NVIC_InitTypeDef;
初始化的成员在 //misc.h 50行
typedef struct
{uint8_t NVIC_IRQChannel; //指定中断源 uint8_t NVIC_IRQChannelPreemptionPriority; //设置抢占优先级(主优先级),//中断优先级分组不同,抢占优先级的位数不同。//如果分组为1,主优先级位数为1,//那么主优先级只能为0或1uint8_t NVIC_IRQChannelSubPriority; //设置子优先级如果前面分组为1,主优先级为1,//子优先级就为3,2的3次方为8//(即0-78个数随便写),让他等于0即可。FunctionalState NVIC_IRQChannelCmd; //使能或者失能} NVIC_InitTypeDef;
注意:
无论是抢占优先级(主优先级)还是响应优先级(子优先级),优先级数值越小,就代表优先级越高。
优先级较高的中断可以打断优先级较低的中断。
抢占优先级相同且响应优先级相同的中断,假如同时发生,会按照硬件内部固定的优先级执行。
中断优先级的分组对内核和外设同样适用。当比较的时候,只需要把内核外设的中断优先级的四个位按照外设的中断优先级来分组来解析即可,即人为的分出抢占优先级和子优先级。
4.编写中断服务函数
中断服务函数名一定要与中断向量表里面的名称一样。工程很大的话,就把所有的中断放在一个文件下,一般把中断服务函数放在stm32f10x_it.c中。
二、EXTI—外部中断/事件控制器
(1)简介
EXTI管理了控制器的20个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
外部:芯片里的GPIO。可以对外输出0或1,输入的时候也可以检测输入的是0还是1.当出现0和1之间变化的时候,就会产生一个中断,也可以产生一个事件。
(2)EXTI结构图
红色是中断,绿色是事件。
输入线:EXTI 0-15是连接到GPIO的(每一个GPIO端口都有16个引脚),当我们使用EXTI0的时候,控制的是所有端口的第0个引脚。具体是哪个端口,在AFIO_EXTICR1、2、3、4这4个寄存器的EXTIx[3:0]位控制。(x属于0-15)
边沿检测电路:检测上升沿还是下降沿,由上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)控制。
或门:收到边沿检测电路传出的信号和软件中断事件寄存器(EXTI_SWIER)控制。软件中断事件寄存器返回1之后,就不受边沿检测电路控制。
在经过或门之后,分为两路:当中断屏蔽寄存器和请求挂起寄存器相关位都置1的时候就会产生中断,交给NVIC,再交给内核相应。如果事件屏蔽寄存器相关位置1,就会把这个1信号给脉冲发生器,产生脉冲(脉冲就是高电平)。脉冲:ITM定时器开始计数、触发ADC的采集。【作为触发信号】
(3)初始化结构体成员
EXTI_InitTypeDef
1-EXTI_Line:用于产生中断/事件线(框图里的输入线)
2-EXTI_Mode:EXTI模式(中断/事件)(中断屏蔽寄存器/事件屏蔽寄存器)
3-EXTI_Trigger:触发(上升沿/下降沿/上下)
4-EXTI_LineCmd:使能或者失能(IMR/EMR)
(4)程序设计:
通过两个按键控制,PA0上升沿(按下)触发,PC13下降沿(弹开)触发。产生一次中断,LED反转一次。
思路设计:
先配置外设(按键等)用到的外部中断(EXTI)
功能:初始化外设(按键等)要连接到 EXTI 的 GPIO。
配置 EXTI 结构体,初始化 EXTI,产生中断信号。
再配置NVIC中断控制器
功能:配置中断优先级分组,再初始化 NVIC 结构体,然后初始化 NVIC 去处理中断。
1.初始化要连接到EXTI的GPIO。
1.观察外设(GPIO)端口结构体的成员:端口、速度、输出/入方式,我们把常用到的端口、宏定义(与硬件相关的)用我们熟悉的/好理解的名字在bsp_led.h文件里面重新define宏定义一下。一般情况下,GPIO端口的重新宏定义包括APB2时钟、具体哪个GPIOX(ABCD)端口、GPIOX的管脚pin。
2.在bsp_led.c文件里面把GPIO初始化好,详细步骤参见上面初始化I/O口的步骤:打开GPIO的时钟;配置外设初始化结构体;调用外设初始化函数,把配置好的结构体成员写到寄存器里面。
GPIO_InitTypeDef GPIO_InitStruct;//外设的初始化结构体变量EXTI_InitTypeDef EXTI_InitStruct;//外设的初始化结构体变量NVIC_Config();/*第一步:初始化要连接到 EXTI 的 GPIO*//*1:打开外设的时钟(RCC寄存器控制)*/RCC_APB2PeriphClockCmd(KEY1_EXTI_GPIO_CLK |KEY2_EXTI_GPIO_CLK,ENABLE);/*2:配置外设初始化结构体*/GPIO_InitStruct.GPIO_Pin = KEY1_EXTI_GPIO_PIN;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin = KEY2_EXTI_GPIO_PIN;/*3:调用外设(GPIO)初始化函数,把配置好的结构体成员写到寄存器里面*/GPIO_Init(KEY1_EXTI_GPIO_PORT,&GPIO_InitStruct);//初始化端口GPIO_Init(KEY2_EXTI_GPIO_PORT,&GPIO_InitStruct);//初始化端口
2.初始化EXTI用于产生中断/事件
和第一步一样,先观察该外设(EXTI)的初始化结构体成员:
typedef struct
{uint32_t EXTI_Line; //哪一条输入线(总共20条) EXTIMode_TypeDef EXTI_Mode; //这条线的模式(中断/事件)EXTITrigger_TypeDef EXTI_Trigger; //触发选择(上升/下降/同时)FunctionalState EXTI_LineCmd; //使能}EXTI_InitTypeDef;
把需要宏定义的变量定义好:
#define KEY1_EXTI_GPIO_PORTSOURCE GPIO_PortSourceGPIOA//中断输入线属于哪个端口
#define KEY2_EXTI_GPIO_PORTSOURCE GPIO_PortSourceGPIOC#define KEY1_EXTI_GPIO_PINSOURCE GPIO_PinSource0//中断输入线属于哪个引脚
#define KEY2_EXTI_GPIO_PINSOURCE GPIO_PinSource13#define KEY1_EXTI_LINE EXTI_Line0//选择哪条输入线
#define KEY2_EXTI_LINE EXTI_Line13
根据前面讲解的功能框图,打开AFIO的时钟;确定中断输入线用到哪个端口、哪个引脚(函数作用为选择用作EXTI线的GPIO引脚);配置初始化结构体;调用 EXTI 初始化函数,把配置好的结构体成员写到寄存器里面。至此中断信号已经产生。
到这就可以发现,这些配置寄存器的方法都大体相同。
/*第二步:初始化EXTI外设*/ /*1:打开外设的时钟(RCC寄存器控制)*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);/*2.确定中断输入线用到哪个端口、哪个引脚*/GPIO_EXTILineConfig(KEY1_EXTI_GPIO_PORTSOURCE, KEY1_EXTI_GPIO_PINSOURCE);/*3.配置初始化结构体*/EXTI_InitStruct.EXTI_Line = KEY1_EXTI_LINE;//选择哪条输入线EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//这条线的模式(中断/事件)EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//触发选择(上升/下降/同时)EXTI_InitStruct.EXTI_LineCmd = ENABLE;//使能/*4.调用 EXTI 初始化函数,把配置好的结构体成员写到寄存器里面*/EXTI_Init(&EXTI_InitStruct);/*2.确定中断输入线用到哪个端口、哪个引脚*/GPIO_EXTILineConfig(KEY2_EXTI_GPIO_PORTSOURCE, KEY2_EXTI_GPIO_PINSOURCE);/*3.配置初始化结构体*/EXTI_InitStruct.EXTI_Line = KEY2_EXTI_LINE;//选择哪条输入线EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//这条线的模式(中断/事件)EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;//触发选择(上升/下降/同时)EXTI_InitStruct.EXTI_LineCmd = ENABLE;//使能/*4.调用 EXTI 初始化函数,把配置好的结构体成员写到寄存器里面*/EXTI_Init(&EXTI_InitStruct);//至此,中断信号已经产生
3.初始化NVIC,用于处理中断
先配置中断优先级分组,再初始化NVIC的初始化结构体,然后调用初始化NVIC外设函数,把配置好的结构体成员写到寄存器里面。
static void NVIC_Config(void)//配置NVIC中断控制器 静态的函数,表示只能在这个文件中使用
{NVIC_InitTypeDef NVIC_InitTStruct;//初始化结构体的变量/*第一步:配置中断优先级分组*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);/*第二步:初始化 NVIC 的初始化结构体*/NVIC_InitTStruct.NVIC_IRQChannel = KEY1_EXTI_IRQN;NVIC_InitTStruct.NVIC_IRQChannelPreemptionPriority = 1;//前面配置的中断优先级分组为1,主优先级只有一个位来表示NVIC_InitTStruct.NVIC_IRQChannelSubPriority = 0;NVIC_InitTStruct.NVIC_IRQChannelCmd = ENABLE;/*第三步:调用初始化NVIC外设函数,把配置好的结构体成员写到寄存器里面*/NVIC_Init(&NVIC_InitTStruct);/*第二步:初始化 NVIC 的初始化结构体*/NVIC_InitTStruct.NVIC_IRQChannel = KEY2_EXTI_IRQN;NVIC_InitTStruct.NVIC_IRQChannelPreemptionPriority = 1;//前面配置的中断优先级分组为1,主优先级只有一个位来表示NVIC_InitTStruct.NVIC_IRQChannelSubPriority = 1;//这样key1的中断优先级就大于key2的NVIC_InitTStruct.NVIC_IRQChannelCmd = ENABLE;/*第三步:调用初始化NVIC外设函数,把配置好的结构体成员写到寄存器里面*/NVIC_Init(&NVIC_InitTStruct);
}
4.编写中断服务函数
首先,有一个检测是否产生中断的函数,如果产生了中断,就……
void KEY1_EXTI_IRQHandler(void)
{if(EXTI_GetITStatus(KEY1_EXTI_LINE) != RESET )//如果产生了中断{LED1_TOGGLE;//LED1 亮灭反转}EXTI_ClearITPendingBit(KEY1_EXTI_LINE);//清除相关的中断标志位
} void KEY2_EXTI_IRQHandler(void)
{if(EXTI_GetITStatus(KEY2_EXTI_LINE) != RESET )//如果产生了中断{LED2_TOGGLE;//LED1 亮灭反转}EXTI_ClearITPendingBit(KEY2_EXTI_LINE);//清除相关的中断标志位
}
5.main函数
等待外部中断的到来,然后去中断服务函数里面执行程序。
int main(void)
{/*在程序来到main函数这里的时候,系统时钟已经配置成72M*/LED_GPIO_Config();//初始化函数/*等待外部中断的到来,然后去中断服务函数里面执行程序*/EXTI_KEY_Config();while(1){}
}
STM32的中断介绍相关推荐
- STM32:中断的详细介绍及使用流程
一.中断介绍 1.中断概念 >>CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序或中断处理程序),以处 ...
- stm32之中断模式
stm32之中断模式 一.中断简介 二.外部中断配置 (一)外部中断简介 (二)配置外部中断 1.配置外部中断 2.配置中断优先级 3.生成并查看代码 (三)编写中断函数 (四) 实例演示 三.使用串 ...
- STM32学习--中断
这里写目录标题 什么是中断? 中断的作用 中断的特点 STM32与中断 NVIC 中断通道 中断优先级 中断服务函数 SysTick中断(内核中断) SysTick中断函数 NVIC库函数 NVIC初 ...
- STM32定时器中断显示时间
前言 利用STM32的定时器中断,实现时间的显示.我们知道利用定时器中断只能进行tick的计算,然而用来显示时间我们应该怎么办呢?经过项目的实际运用,我发现利用定时器中断配合串口通讯也能实现时间显示. ...
- STM32外部中断与(NVIC)中断优先级管理
文章目录 1.中断介绍 1.中断的概念 2.中断的产生 3.中断处理的流程 2.STM32内嵌向量中断控制器NVIC 1.NVIC控制器的寄存器 2.STM32中断配置 3.STM32外部中断EXIT ...
- STM32F103(五)——关于EXIT外部中断介绍
前言 本节将会对 STM32(五)进行一个归纳 STM32 的每个 IO 都可以作为外部 中断的中断输入口,这点也是 STM32 的强大之处, STM32F103 的中断控制器支持 19 个外部中 断 ...
- STM32的中断体系和FSMC控制LCD-第3季第7部分视频课程-朱有鹏-专题视频课程
STM32的中断体系和FSMC控制LCD-第3季第7部分视频课程-861人已学习 课程介绍 本课程是<朱有鹏老师单片机完全学习系列课程>第3季第7个课程,本课程详细讲解ST ...
- STM32外部中断与各通道对应关系
EXTI0_IRQn的值,其实就是EXTI0中断向量在中断向量表中的位置(STM32技术参考手册中断向量表position栏中的数值) 一:外部中断使用配置过程: (1)配置时钟信号 (2)引脚属性 ...
- (二)stm32之中断配置
一.stm32的中断和异常 Cortex拥有强大的异常响应系统,它能够打断当前代码执行流程事件分为异常和中断,它们用一个表管理起来,编号为0~15为内核异常,16以上的为外部中断,这个表就是中断向量表 ...
最新文章
- configure_file路径疑惑
- 用 Flask 来写个轻博客 (22) — 实现博客文章的添加和编辑页面
- Logistics Regression公式推导
- 微信jssdk 图片上传 JAVA_微信jssdk图片上传
- get中添加header
- AIX环境安装DB2 数据库
- 三维计算机软件图,三维cad看图
- 〖免杀〗.net程序一键免杀Win10 20H2 Defender
- 大型综合办公管理系统源码(OA+HR+CRM)源码免费分享
- 数据库无法插入Could not set property ‘id‘ of ‘class com.XXX‘ with value ‘1481832253064073217‘
- html标签各属性之间用空格隔开对吗,03-HTML标签(二)
- 解决虚拟机与宿主机不在同一个网段中,不能相互ping通的问题
- 1.请求和响应(phalapi框架总结)
- 魏鹏机器人_3D打印室、机器人工程挑战室……山东这所学校的“网红教室”火了!...
- Oracle EBS 笔记8
- 工作面试总遇秒杀? 看了京东 T8 大咖私藏的秒杀系统笔记, 已献出膝盖
- Codeforces 417D.Cunning Gena (状压DP)
- 利用python对gif图片进行压缩处理,简单案例
- python readcsv读取gbk编码文件_python读写csv文件
- 【论文翻译】Generation of Non-Deterministic Synthetic Face Datasets Guided by Identity Priors(21.12)
热门文章
- CALayer 2 详解 -----转自李明杰
- css !important的用法
- 写了这么多年代码,你真的了解设计模式么?
- 第十七天学习记录:工作相关:Qt控件设置setEnabled(false)的问题。
- 鸿蒙哪些机型可以用,鸿蒙系统可以在哪些手机上使用 鸿蒙系统升级名单
- 适用于AG的AI:农业生产机器学习
- Kafka安全认证SASL/PLAINTEXT,账号密码认证
- (爱加密系列教程十三) 如何防止工具(八门神器)进行内存修改
- python爬取数据的原理_Python爬虫原理
- python爬取数据的原理_python学习之python爬虫原理