2、STM32--EXTI(外部中断)&中断函数配置

目录

一、时钟配置

二、与  AFIO  有关的函数与配置

2.1 与 AFIO  有关的函数

2.1 AFIO 的配置

三、关于 EXTI 的函数与配置

3.1  EXTI 的函数

3.2 EXTI 的配置

四、关于 NVIC 的函数与配置(位于msci.h文件)

4.1关于 NVIC 的函数

4.2  NVIC的配置

五、中断函数

六、中断源码


一、NVIC基本介绍

1.1、NVIC基本结构

NVIC被称为做嵌套中断向量控制器,其作用是统一分配中断优先级管理中断的。

  • NVIC可以有多个输入,但是只有一个输出,输入可以是 EXTI、TIM、ADC等外设,其中红色框选部分代表着一个外设可能占有多个中断通道。
  • NVIC根据优先级排序,指引CPU处理不同任务。

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

抢占优先级:抢占优先级高的中断,可以在CPU暂停处理当前中断,转而处理抢占优先级较高的中断事件,处理完抢占优先级较高的中断事件后,继续处理之前暂停的中断。

优先级和响应优先级均相同:按以下表格中的中断顺序排队。

1.2、NVIC介绍

  1. EXTI(Extern Interrupt)外部中断。
  2. EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
  3. 支持的触发方式:上升沿/下降沿/双边沿/软件触发
  4. 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
  5. 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
  6. 触发响应方式:中断响应/事件响应

第四点中, 但相同的Pin不能同时触发中断,即PA0 与PB0等不可同时使用。

1.3、整体结构

AFIO是选择开启需要GPIOx引脚。对应1.2、中的第四点,相同的Pin不能同时触发中断,即PA0 与PB0等不可同时使用。因为选择GPIOA后无法再使其他GPIOx口的引脚信号输入。

引脚5-9引脚10-15共用一个中断函数。

1.4、电路结构

1.4.1、AFIO

在STM32中,AFIO主要完成两个任务:复用功能引脚重映射中断引脚选择

1.4.2、NVIC

二、对射红外传感计次

 上图为硬件线路接线。

我们要配置中断函数就需要知道我们需要配置那些外设。下图可以清晰的了解我们需要配置的外设

此时,我选择的红外连接在GPIOB--14引脚,所以我需要配置外设GPIOB的时钟信号,而AFIO在图一中也是必不可少的,所以我们还需要配置AFIO外设。由于EXTI由MVIC模块直接控制,是默认开启时钟的,所以并不需要单独设置。以下就是我们的配置代码

2.1、CountSensor.c文件

2.1.1、开启GPIO时钟

uint8_t CountSensor_Init()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
      
//开启外设AFIO时钟  EXTI由MVIC模块直接控制,并不需要单独外设
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);  
    
    GPIO_InitTypeDef GPIO_InitStruct;
 //上拉输入,高电平输入;不知道配置什么模式,可以查看芯片手册
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;    

    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
}

 2.1.2、选择用作EXTI线的GPIO引脚

即选择哪个GPIO口作为EXTI输入

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);

2.1.3、EXTI边沿检测及控制

    EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line=EXTI_Line14;								
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;									
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;				
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;				
	EXTI_Init(&EXTI_InitStructure);

【1】EXTI_Line: 指定要启用或禁用的EXTI行。

【2】EXTI_LineCmd:指定选定EXTI线的新状态。

【3】EXTI_Mode:指定EXTI线的模式。即选择事件模式还是中断模式。事件模式一般是外设与外设的联系。

【4】EXTI_Trigger:指定EXTI线的触发信号激活边缘模式。即是继续上升沿、下降沿还是其他边沿触发。

 2.1.4、配置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=1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructure);

【1】 NVIC_PriorityGroupConfig()://配置优先级分组:抢占优先级和次优先级。

【2】NVIC_IRQChannel:指定要启用或禁用的IRQ通道。即选择图中黄色框选进入NVIC的通道。为节省资源在该系列中引脚10-15、引脚5-9共用一个通道。本例中使用的是14引脚,因此使用EXTI15_10_IRQn。

【3】NVIC_IRQChannelCmd:指定在NVIC_IRQChannel中定义的IRQ通道将被启用或禁用。即选择禁用或启用【2】中选中的通道。本例中是启用 。

【4】NVIC_IRQChannelPreemptionPriority:指定NVIC_IRQChannel中指定的IRQ信道的抢占优先级。

【5】NVIC_IRQChannelSubPriority:指定NVIC_IRQChannel中指定的IRQ通道的响应优先级级别。由于本例子中并无太多中断,因此可以【4】【5】自行选择。

2.1.5、调用中断

在STM32里,中断函数的名字都是固定的,需要在启动文件  startup_stm32f10x_md.s 中找到对应的函数名字,由于本例程中使用的NVIC_IRQChannel 通道为 EXTI15_10_IRQn,因此使用的中断函数名称应为 EXTI15_10_IRQHandler。 

uint16_t CountSensor_Get(void)							//返回计次值
{
	return CountSensor_Count;
}

void EXTI15_10_IRQHandler()
{
		if(EXTI_GetITStatus(EXTI_Line14)==SET)
		{
			CountSensor_Count++;							//计次
			Delay_ms(200);										//消除抖动
			EXTI_ClearITPendingBit(EXTI_Line14);
		}
}

2.2、CountSensor.c & main.c文件源码

#include "stm32f10x.h"                  // Device header
#include "Delay.h" 

uint16_t CountSensor_Count;

void CountSensor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);    //开启外设AFIO时钟  EXTI由MVIC模块直接控制,并不需要单独外设
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;						//上拉输入,高电平输入
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
	
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line=EXTI_Line14;								
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;									
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;				
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;				//  EXTI_Trigger_Falling 下降沿触发  /EXTI_Trigger_Rising  上升沿触发
	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=1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructure);
}

uint16_t CountSensor_Get(void)							//返回计次值
{
	return CountSensor_Count;
}

void EXTI15_10_IRQHandler()
{
		if(EXTI_GetITStatus(EXTI_Line14)==SET)
		{
			CountSensor_Count++;							//计次
			Delay_ms(200);										//消除抖动
			EXTI_ClearITPendingBit(EXTI_Line14);
		}
}
#include "stm32f10x.h"                  // Device header
#include "Delay.h"                  // Device header
#include "OLED.h" 
#include "CountSensor.h"

int main(void)
{
	CountSensor_Init();
	OLED_Init();												//OLED初始化
	CountSensor_Get();
	OLED_ShowString(1,1,"Count:");
	
	while(1)
	{	
	
	}
}

 三、与  AFIO  & EXTI 有关的函数简介

3.1 与  AFIO  有关的函数

3.1.1、GPIO_AFIODeInit(void)

 //清除 AFIO 外设配置 

GPIO_AFIODeInit(void)

3.1.2、GPIO_PinLockConfig()

//锁定GPIO配置,参数指定某个引脚,该引脚配置被锁定,无法更改              

GPIO_PinLockConfig((GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin))   

3.1.3、GPIO_EXTILineConfig()

//配置 AFIO的数据选择器,选择想要的中断引脚;参数1、选择某个GPIO外设作为外部中断源

参数2、指定要配置的外部中断线

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);

3.1.4、GPIO_PinRemapConfig()

//引脚重映射  参数1、选择重映射的方式; 参数2、新的状态

GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

3.1.5、GPIO_EventOutputConfig()&GPIO_EventOutputCmd()

//这两个函数用来配置AFIO的时间输出功能(使用频率不多)

GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);

GPIO_EventOutputCmd(FunctionalState NewState);

3.1.6、GPIO_ETH_MediaInterfaceConfig()

//与以太网有关

GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);

3.2 AFIO 的配置

//参数1、选择某个GPIO外设作为外部中断源    参数2、指定要配置的外部中断线

本实验中我选择的红外连接在GPIOB--14引脚,所以参数配置如下

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);

3.2、关于 EXTI 的函数与配置

3.2 .1、 GPIO_EXTILineConfig()

//清除EXTI的配置 并回复成上电默认的转态.

GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)

3.2.2、EXTI_DeInit()

//清除EXTI配置

EXTI_DeInit(void)

3.2.3、EXTI_Init()

//根据结构体参数配置EXTI外设,与GPIO_Init 用法类似

EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)

3.2.4、EXTI_StructInit()

//把参数传递的结构体变量赋一个默认值

EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct)

3.2.5、EXTI_GenerateSWInterrupt()

//软件触发外部中断

EXTI_GenerateSWInterrupt(uint32_t EXTI_Line)

3.2.6、EXTI_GetFlagStatus()

//获取指定的标志位是否被置1

EXTI_GetFlagStatus(uint32_t EXTI_Line);

3.2.7、EXTI_ClearFlag()

//对被置1的标志位进行清除
EXTI_ClearFlag(uint32_t EXTI_Line);

3.2.8、EXTI_GetITStatus()

//获取中断位是否被置1
EXTI_GetITStatus(uint32_t EXTI_Line);

3.2.9、EXTI_ClearITPendingBit()

//清除中断挂起的标志位
EXTI_ClearITPendingBit(uint32_t EXTI_Line);

若想在主程序中查看和清除标志位,使用5/6这两个函数,

若想在中断函数中查看和清除标志位,使用7/8这两个函数

 

四、关于 NVIC 的函数与配置(位于msci.h文件)

4.1关于 NVIC 的函数

4.1.1、NVIC_PriorityGroupConfig()

//中断分组,参数为中断分组的方式

 NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)

4.1.2、NVIC_Init

//初始化NVIC

NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)

4.1.3、NVIC_SetVectorTable()

//设置中断向量表(本实验中暂未用到)

NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);

4.1.4、NVIC_SystemLPConfig

//系统低功耗配置(本实验中暂未用到)

NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState)

以上为更新后的EXTI以及中断函数使用,主要优化了文章代码思路以及简介。本文将不定期优化更新。

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘洲青年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值