1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > STM32F103ZET6+EXTI中断处理

STM32F103ZET6+EXTI中断处理

时间:2021-09-06 03:41:32

相关推荐

STM32F103ZET6+EXTI中断处理

STM32F103ZET6+EXTI中断处理

一、 中断的相关概念

计算机在执行程序过程中(这里主要指单片机执行主程序),当出现异常情况(断电等)或特殊请求(数据传输等)时,计算机暂时停现行程序的运行,转向对这些异常情况或特殊请求的处理,调用相应的中断处理程序处理该事件),处理完毕后再返回到现行程序的中断处继续执行原程序,这就是中断

能够打断当前正常执行流程的事件有两种,一种是中断,一般由外部事件触发,一种是异常,由CPU内部事件产生。中断和异常其本质都是对主程序的中断,中断其实是异常的一种形式

二、 中断处理流程

一个完整的中断处理过程分为4个步骤:中断请求、中断响应、中断服务和中断返回

1、中断请求

中断请求是中断源向CPU发出的中断请求信号,此时中断控制系统的中断请求寄存器被置位,向CPU请求中断

2、中断响应

中断响应是指CPU的中断系统判断中断源的中断请求是否符合中断响应条件,若符合条件,则暂时中断当前程序并控制程序跳转到中断服务程序,完成相应的中断服务操作。

CPU响应中断一般需要满足以下条件

(1)中断源发出中断请求

(2)系统允许中断提出中断请求,即中断没有被屏蔽

(3)无同级或更高级的中断正在被处理

CPU根据中断类型号进行中断优先级的判断,若无更高优先级的中断请求,则保护断点和现场,根据中断类型获得中断服务程序入口地址,转入相应的中断服务程序。

保护现场主要是只保护当前程序的断点和保存当前通用寄存器、状态寄存器的内容,即将这些寄存器的内容压入堆栈。这部分底层操作已经有硬件自动实现,不需要开发人员进行处理

3、中断服务

为处理中断而编写的程序称为中断服务程序,中断类型不同,其中断服务也不同。中断服务程序的入口地址称为中断向量,将所有中断的中断服务程序的入口地址汇成一张表,称为中断向量表

4、中断返回

中断返回是指CPU退出中断服务,返回到中断请求响应前中止的位置继续执行主程序。中断服务程序的最后一条指令通常是一条中断返回指令,使其返回到原来程序的断点处,以便继续执行原来的程序。若在中断处理过程中,又产生了一个优先级更高的中断。则CPU会暂停当前的中断服务,将断点和相关的寄存器入栈后,转而去处理优先级更高的中断,在中断服务完成后,需要将中断的现场(即断点)进行恢复,将压入堆栈的寄存器内容送回到原来的寄存器中(即出栈)。这部分操作同样由硬件来实现,不需要开发人员进行处理

三、 STM32中断优先级

STM32通过Cortex-M3内核集成的NVIC实现中断优先级管理。理论上,除3个固定的高优先级(Reset、NMI、硬件失效)不可编程外,Cortex-M3支持256级中断,其优先级都是可以设置的

NVIC中断配置的相关函数存放在标准外设库misc.c文件和misc.h文件中,共定义了5个相关函数及NVIC初始化结构体

其中,中断分组管理函数void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)用于设置中断的优先级分组,此函数只有一个参数NVIC_PriorityGroup,从源代码中可以看到其取值共有5组,每组的抢占优先级和响应优先级所占位数均不同,且取值范围也有不同,故每组可供设置优先级的数值不一样

通过函数void NVIC_PriorityGroupConfig()设置中断分组,对于具体的中断,其抢占优先级和响应优先级设置是通过中断初始化函数void NVIC_Init(NVIC_InitTypeDef *NVIC_InitStruct)实现的,其中NVIC_InitTypeDef是结构体,参数NVIC_InitStruct是指向NVIC_InitTypeDef结构体的指针

(1)NVIC_IRQChannel:用于指定某个具体的IRQ通道,即具体是哪个中断,在标准外设库stm32f10x.h文件中包含了所有中断所对应的名称

(2)NVIC_IRQChannelPreemptionPriority:用于设置NVIC_IRQChannel的抢占优先级

(3)NVIC_IRQChannelSubPriority:用于设置NVIC_IRQChannel的响应优先级

(4)NVIC_IRQChannelCmd:用于IRQ通道使能或失能,取值为ENABLE或者DISABLE

以上通过两个函数确定了具体中断的抢占优先级和响应优先级。若系统中存在多个中断,则一般遵循以下原则判断中断优先级。

(1)高抢先优先级的中断可以打断低抢先优先级的中断服务,构成中断嵌套。

(2)中断优先级的数值越小,优先级级别越高。

(3)抢占优先级的优先级总是高于响应优先级。

(4)中断优先级判断:先判断抢占优先级的大小;若抢占优先级相同,则比较响应优先级的大小;若抢占优先级和响应优先级均相同,则根据中断向量表中的顺序来决定。

(5)Reset NMI Hard Fault的优先级为负,且不可修改,高于其他普通的中断优先级。

四、STM32外部中断EXTI

1、 GPIO初始化

GPIO初始化配置的相关代码

2、 开启I/O端口的时钟和复用时钟

GPIO不仅可以作为通用的输入/输出引脚,还可以用作片上外设(如USART、ADC等)的输入/输出引脚,称为复用I/O端口,当GPIO用作复用引脚时,必须开启AFIO时钟。这里I/O端口不是作为GPIO来使用的,而是用作EXTI外部中断功能引脚,所以必须开启复用功能,通过调用RCC_APB2PeriphClockCmd()函数打开相应引脚的AFIO时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE);

3、 设置I/O引脚与中断线路的映射关系

当GPIO引脚作为中断功能引脚用来触发外部中断时,需将GPIO引脚与相应的中断线关联在一起,使用库函数GPIO_EXTILineConfig来实现这种映射关系。如将PE3引脚与外部中断EXTI3_IRQn关联在一起

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);

4、 初始化EXTI,配置EXTI相关参数并使能

如选择具体的中断引脚、中断线路、触发模式等,实例代码如下:

5、 初始化NVIC,配置NVIC参数并使能

NVIC相关的配置主要包括配置中断优先级的中断分组,确定各具体中断的抢占优先级和响应优先级的大小,选择中断通道,在stm32f10x.h文件中通过IRQn_Type中断通道结构体定义所有的中断通道,不同的引脚对应不同的终端通道,使能相应的中断

6、 编写中断服务程序

中断服务程序主要包括检测中断线路的状态、中断处理的内容和清除相关的中断

在之前的LED灯工程上,新建两个文件,一个是exti.h文件,另一个是exti.c文件

exit.h文件的代码如下:

#ifndef __EXTI_KEY_H#define __EXTI_KEY_H#include "stm32f10x.h"void EXTI_init(void);#endif

exit.c文件的代码如下:

#include "exti.h"#include "misc.h"void EXTI_init(void){GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE); //开启PE3的时钟,并开启复用时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//选择要使用的I/O引脚,此处选择PE3引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置引脚输入模式为浮空输入模式GPIO_Init(GPIOE,&GPIO_InitStructure); //调用初始化库函数初始化GPIO端口//初始化EXTI,外部中断EXTI_ClearITPendingBit(EXTI_Line3); //清空外部中断3中断挂起,清空中断标志GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);//将PE3用作外部中断线路EXTI_InitStructure.EXTI_Line = EXTI_Line3;//设置外部中断线3中断EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设置为中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //设置为下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能该外部中断线EXTI_Init(&EXTI_InitStructure);//初始化NVIC,中断优先级NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断优先级分组2NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //外部中断3中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//设置抢占优先级为0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //设置响应优先级为1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//外部中断处理函数NVIC_Init(&NVIC_InitStructure); }//外部中断处理函数void EXTI3_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line3) != RESET){GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5)))); //PE5的电平状态翻转EXTI_ClearITPendingBit(EXTI_Line3); //清除中断标志位}}

main.c文件的代码如下:

#include "stm32f10x.h"#include "delay.h"#include "led.h"#include "exti.h"int main(void){delay_init();LED_Init();EXTI_init();GPIO_ResetBits(GPIOB,GPIO_Pin_5); while(1){}}

总结,如果使用STM32的外部中断,则需要以下几个步骤。

(1) 使用RCC_APB2PeriphClockCmd()函数配置时钟,初始化GPIO引脚作为复用功能。

(2) 使用GPIO_EXTILineConfig()函数配置I/O引脚与外部中断线路的映射关系。

(3) 使用EXTI_Init()函数配置外部中断,

(4) 使用NVIC_Init()配置中断优先级等

(5) 编写中断服务函数

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。