【STM32】EXTI与NVIC标准库使用框架

本篇博客重点在于标准库函数的理解与使用,搭建一个框架便于快速开发

目录

EXTI简介

EXTI配置

使能AFIO的时钟

配置GPIO端口为外部中断 

外部中断初始化

NVIC介绍与配置

NVIC中断优先级分组

 NVIC初始化

NVIC框架

 EXTI配置图

中断函数

中断函数配置

获取中断挂起位

清楚中断挂起标志位 

 中断函数框架

EXTI框架


EXTI简介

EXTI(Extern Interrupt),外部中断,也可配置事件,又可称事件控制器

EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序

支持的触发方式:上升沿/下降沿/双边沿/软件触发

支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断

中断通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒

后个主要用于低功耗的停止模式下使用外部中断唤醒

触发响应方式:中断响应/事件响应,中断由CPU响应,事件由外设响应

EXTI配置

使能AFIO的时钟

外部中断需要写事件控制寄存器(AFIO_EVCR),外部中断配置寄存器(AFIO_EXTICRX)

对寄存器AFIO_EVCR,AFIO_MAPR和AFIO_EXTICRX进行读写操作前,应当首先打开AFIO 的时钟。

事件控制寄存器(AFIO_EVCR)

故要开启AFIO的时钟,而AFIO在APB2外设总线上

 再由RCC时钟树,需要使能APB2外设的AFIO时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

配置GPIO端口为外部中断 

有关GPIO的详细配置请阅读这篇博客,这里不再赘述

【STM32】GPIO和AFIO标准库使用框架-CSDN博客

外部中断的GPIO_Mode为输入模式,设置为输入信号的默认电平对应的模式,更多见STM32F10xxx参考手册8.1.11 外设的GPIO配置

输入电平默认为高电平,上拉输入;输入电平默认为低电平,下拉输入。输入电平不确定选浮空输入

相同的Pin不能同时触发中断,比如GPIOX0只能有一个可以触发中断,GPIOA0映射到中断了,GPIOB0就不可以了

GPIO_PortSourceGPIOX  ,X为A,B,C... 

GPIO_PinSourcexX,             X为0,1,2 ...

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);

GPIO_EXTILineConfig函数将指定端口配置到中断通道

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出速度,输入无用
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);

外部中断初始化

中断

要产生中断,必须先配置好并使能中断线。根据需要的边沿检测设置2个触发寄存器,同时在中断屏蔽寄存器的相应位写’1’允许中断请求。当外部中断线上发生了期待的边沿时,将产生一个 中断请求,对应的挂起位也随之被置’1’。在挂起寄存器的对应位写’1’,将清除该中断请求。

事件

如果需要产生事件,必须先配置好并使能事件线。根据需要的边沿检测通过设置2个触发寄存 器,同时在事件屏蔽寄存器的相应位写’1’允许事件请求。当事件线上发生了需要的边沿时,将产生一个事件请求脉冲,对应的挂起位不被置’1’。 通过在软件中断/事件寄存器写’1’,也可以通过软件产生中断/事件请求。

使能中断线

要产生中断,必须先配置好并使能中断线。

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

触发边沿选择

这个配置的是进入中断函数的电平变化边沿

 上升沿EXTI_Trigger_Rising
下降沿EXTI_Trigger_Falling
双边沿EXTI_Trigger_Rising_Falling
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

选择模式

中断模式EXTI_Mode_Interrupt
事件模式EXTI_Mode_Event
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

 选择中断通道

对于互联型产品,外部中断/事件控制器由20个产生事件/中断请求的边沿检测器组成,对于STM32F10xxx其它产品(小容量、中容量和大容量),则有19个能产生事件/中断请求的边沿检测器

那我这个有19个能产生事件/中断请求的边沿检测器

 EXTI_LineX,  X为0到19

EXTI_InitStructure.EXTI_Line = EXTI_Line12;

 EXTI初始化

	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line12;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&EXTI_InitStructure);

● EXTI线0~15连接到GPIO口

● EXTI线16连接到PVD输出

● EXTI线17连接到RTC闹钟事件

● EXTI线18连接到USB唤醒事件

● EXTI线19连接到以太网唤醒事件(只适用于互联型产品)

后四个主要用于低功耗的停止模式下使用外部中断唤醒

NVIC介绍与配置

NVIC是CPU的助手,管理中断,使中断有序执行

NVIC在内核里,不是外设,标准库函数声明在 misc.h 文件

NVIC特性

68个可屏蔽中断通道(不包含16个Cortex™-M3的中断线);

● 16个可编程的优先等级(使用了4位中断优先级);

● 低延迟的异常和中断处理;

● 电源管理控制;

● 系统控制寄存器的实现; 嵌套向量中断控制器(NVIC)和处理器核的接口紧密相连,可以实现低延迟的中断处理和高效地 处理晚到的中断。

嵌套向量中断控制器管理着包括内核异常等中断

NVIC中断优先级分组

NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级,抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

具体中断号见参考手册中断向量表

中断个数比较少的话,就比较随意了,这个函数整个文件只需配置一次,多次配置会覆盖

 示例代码为分组二

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

 NVIC初始化

中断通道接入NVIC

NVIC_IRQChannel,参数在stm32f10x.h 文件

NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;

 使能NVIC通道

NVIC_IRQChannelCmd,指定NVIC_IRQChannel中定义的IRQ通道是启用还是禁用

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

抢占优先级

NVIC_IRQChannelPreemptionPriority

	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

响应优先级

NVIC_IRQChannelSubPriority

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

 NVIC初始化框架

	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStructure);

NVIC框架

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//多个中断只配置一次
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStructure);

 EXTI配置图

 图片来源:STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili

中断函数

中断函数位置不固定

中断函数配置

中断函数名要与启动文件内中断向量名一样

中断函数快进快出,尽量不要加延时,不要在主函数和中断函数同时使用OLED等外设,易导致错误

中断函数不在主函数内使用,空闲时,不执行。检测到通道对应的边沿,立刻跳转,跳转后清除中断标志位,执行完中断函数,返回主函数里中断函数执行前的位置。

获取中断挂起位

FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);//main中调用
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);//中断函数中调用

清楚中断挂起标志位 

void EXTI_ClearFlag(uint32_t EXTI_Line);//main中调用
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);//中断函数中调用

 中断函数框架

	
	void EXTI15_10_IRQHandler(void)
	{
		if(EXTI_GetITStatus(EXTI_Line12) == SET)
		{
			
			EXTI_ClearITPendingBit(EXTI_Line12);
		}
}

EXTI框架

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出速度,输入无用
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);
	
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line12;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructure);
	
	
	
	void EXTI15_10_IRQHandler(void)
	{
		if(EXTI_GetITStatus(EXTI_Line12) == SET)
		{
			
			EXTI_ClearITPendingBit(EXTI_Line12);
		}
}
  • 15
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值