STM32之外部中断

STM32之外部中断

  • 开发环境:Window 10
  • 开发工具:Keil uVision5 MDK
  • 硬件:STM32F103

资料参考:

【正点原子】STM32F103开发板资料(A盘);



STM32F103ZE 简介

https://www.keil.com/dd2/stmicroelectronics/stm32f103ze/

内核:ARM Cortex-M3,72MHz

内存:64kB RAM,512kB ROM

时钟和电源:2.00V—3.60V,72 MHz

通信 :SPI、I2C、UART、I2S、CAN、USART、USB、Device

定时器/计数器/PWM :8 × 16 位定时器

模拟:2通道 12位DAC,21通道 12位ADC

I/O 和封装: -40℃—85℃,144-QFP,144-BGA


外部中断介绍

STM32 的每个IO都可以作为外部中断的中断输入口,STM32F103的中断控制器共支持19个外部中断事件请求。每个中断事件都有独立的触发和屏蔽设置。 STM32 F103 的19 个外部中断为:

线0~15 :对应外部 IO 口的输入中断。

线16 :连接到 PVD 输出。

线17 :连接到 RTC 闹钟事件。

线18 :连接到 USB 唤醒事件。

GPIO跟中断线的映射关系如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9Ac0h1Q-1629201693748)(…/2.笔记图片/STM32之外部中断/01.GPIO映射.png)]

GPIO 的管脚 GPIOx.0~GPIOx.15(x=A,B,C,D,E F,G 分别对应中断线 0~ 15 ,如PA0对应中断线0,PA1对应中断线1,…,PA15对应中断线15,同样,B~G系列的各个引脚与A系列相同。

且中断线每次只能连接到1个 IO 口上,也就是说如果已经设置了中断线0连接PA0口,同样对应中断线0的PB0,PC0,…,PG0就不能再设置了。


外部中断的使用步骤

1)使能时钟

2)配置GPIO与中断线的映射关系

3)外部中断的初始化

4)配置中断分组优先级

5)编写中断服务函数


1)使能时钟

外部中断(ADIO)来自于APB2总线

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能复用功能时钟

2)配置GPIO与中断线的映射关系

在库函数中,配置GPIO 与中断线的映射关系用 GPIO_EXTILineConfig() 来实现

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t
GPIO_PinSource)

第一个参数:连接映射的IO口的系列号(GPIO_PortSourceGPIOx,x=A~G)

第二个参数:映射IO口系列的具体引脚(GPIO_PinSourcen,n=0~15)

针对 GPIOE.3 端口与中断线3映射起来的范例:

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);

根据上面提及的映射关系可以知道,IO口PE3 对应中断线3,通过该配置函数,即可将二者连接起来。


3)外部中断的初始化

中断线上中断的初始化用 EXTI_Init() 来实现。

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

参数 EXTI_InitTypeDef 是配置中断初始化的结构体。

typedef struct
uint32_t EXTI_Line;
EXTIMode_TypeDef EXTI_Mode;
EXTITrigger_TypeDef EXTI_Trigger;
Function alState EXTI_LineCmd;
}EXTI_
  1. EXTI_Line:中断线标号,取值范围为 EXTI_Line0~EXTI_Line15;
  2. EXTI_Mode:中断的模式,取值为中断请求 EXTI_Mode_Interrupt 和 事件请求 EXTI_Mode_Event;
  3. EXTI_Trigger:触发方式,取值为下降沿触发 EXTI_Trigger_Falling ,上升沿触发 EXTI_Trigger_ Rising ,或者任意电平(上升沿和下降沿触发)EXTI_Trigger_Rising_Falling;
  4. EXTI_LineCmd:中断是否使能能

针对中断线3配置下降沿触发的范例:

EXTI _InitTypeDef EXTI_InitStructure;
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);// 根据 EXTI_InitStructure 中指定的参数初始化外设 EXTI 寄存器

4)配置中断分组优先级

4.1 中断函数的介绍

STM32 的 IO 口外部中断函数只有 6 个,分别为:

EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler

中断线0~4的每个中断线对应一个中断函数,

中断线5~9 共用中断函数 EXTI9_5_IRQHandler ,

中断线10~15 共用中断函数 EXTI15_10_IRQHandler 。


4.2 配置中断优先级

用 NVIC_Init()函数实现中断优先级的设置

NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)

根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

NVIC_InitTypeDef定义于文件“misc.h”

typedef struct
{
u8 NVIC_IRQChannel;
u8 NVIC_IRQChannelPreemptionPriority;
u8 NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;
  1. NVIC_IRQChannel:定义初始化哪个中断
  2. NVIC_IRQChannelPreemptionPriority:定义中断的抢占优先级别
  3. NVIC_IRQChannelSubPriority:定义这个中断的子优先级别
  4. NVIC_IRQChannelCmd:该中断是否使能

针对 中断线3设置优先级的范例:

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_ IRQChannel = EXTI3_IRQn; //使能按键KEY1所在的外部中断通道3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVI C_InitStructure); //根据参数对中断优先级分组初始化

4.3 NVIC 的优先级组的解析

STM32用4位寄存器位的表示中断优先级,其的分组方式如下:

第0组:所有4位用于指定响应优先级

第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级,抢占级有2^1 =2 级;子优先级2^3=8级,共2*8=16级嵌套

第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级,抢占级有2^2 =4 级;子优先级2^2=4级,共4*4=16级嵌套

第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级,抢占级有2^3 =8 级;子优先级2^1=2级,共8*2=16级嵌套

第4组:所有4位用于指定抢占式优先级

中断响应的优先级由抢占优先级和响应优先级(子优先级)确定,若抢占优先级相同,则看响应优先级,数字越小优先级越高。

1.抢占相同,子优先级不同:按照子优先级顺序排序
2.抢占和子优先级都相同但有先后:此时无抢占剥夺,依照FIFO(先进先出),前一个执行完了再执行后者;
3.抢占和子优先级都相同且同时到达:按照中断向量表顺序排先后

5)编写中断服务函数

第一个函数是判断某个中断线上的中断是否发生,一般使用在中断服务函数的开头判断中断是否发生:

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)

第二个函数是中断发生后,清除某个中断线上的中断标志位,一般应用在中断服务函数结束之前:

void EXTI_ClearITPendingBit(uint32_t EXTI_Line)

常用的中断服务函数格式为:

void EXTI3_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生
	{
		中断逻辑……
	}
	EXTI_ClearITPendingBit(EXTI_Line3); // 清除 LINE 上的中断标志位
}

针对外部中断3 实现LED1亮灭变换的范例:

void EXTI3_IRQHandler(void)
{
	delay_ms(10);//消抖
	if(KEY1==0)	 //按键KEY1
	{				 
		LED1=!LED1;
	}		 
	EXTI_ClearITPendingBit(EXTI_Line2);  //清除LINE3上的中断标志位
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值