STM32学习笔记一一外部中断

前言:

为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。

在这里插入图片描述


githubmy github


注:博客所涉及的关于 stm32 的代码,均在仓库【stm32f013_study】下,包括底层驱动和应用测试代码。
本文设计的文件包含:
(1)源文件:
drvexti.c:外部中断驱动实现
(2)头文件:
drvexti.h : 外部中断驱动头文件


1. STM32 外部中断简介

STM32 的每个 IO 都可以作为外部中断的中断输入口。 STM32F103 的中断控制器支持 19 个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。代码主要分布在固件库的 stm32f10x_exti.h 和 stm32f10x_exti.c 文件。

STM32F103的 19 个外部中断为:

IO对应中断
线 0~15对应外部 IO 口的输入中断
线 16连接到 PVD 输出
线 17连接到 RTC 闹钟事件
线 18连接到 USB 唤醒事件
线 19连接到 以太网 唤醒事件

触发方式:STM32 的外部中断是通过边沿来触发的,不支持电平触发。

2. 外部中断分组

STM32 的每一个 GPIO 都能配置成一个外部中断触发源,STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组。

比如:PA0,PB0,PC0,PD0,PE0,PF0,PG0 为第一组。

依此类推,我们能得出一共有16 组,STM32 规定,每一组中同时只能有一个中断触发源工作,那么,最多工作的也就是16个外部中断。

在这里插入图片描述

3. 使用 IO 口外部中断的配置步骤

3.1 初始化 IO 口为输入

设置作为外部中断输入的 IO 口的状态,可以设置为上拉 / 下拉输入 / 浮空输入,但浮空的时候外部一定要带上拉,或者下拉电阻。否则可能导致中断不停的触发。在干扰较大的地方,就算使用了内部上拉/下拉,也建议使用外部上拉/下拉电阻,这样可以一定程度防止外部干扰带来的影响。

3.2 开启 IO 口复用时钟,设置 IO 口与中断线的映射关系

STM32 的 IO 口与中断线的对应关系需要配置外部中断配置寄存器 EXTICR,这样我们要先开启复用时钟,然后配置 IO 口与中断线的对应关系。才能把外部中断与中断线连接起来。

3.3 开启与该IO口相对的线上中断/事件,设置触发条件

配置中断产生的条件,STM32 可以配置成上升沿触发,下降沿触发,或者任意电平变化触发,但是不能配置成高电平触发和低电平触发。同时要开启中断线上的中断。

注意: 如果使用外部中断,并设置该中断的 EMR 位的话,会引起软件仿真不能跳到中断,而硬件上是可以的。而不设置 EMR,软件仿真就可以进入中断服务函数,并且硬件上也是可以的。建议不要配置 EMR 位。

3.4 配置中断分组NVIC

配置中断的分组,以及使能,对 STM32 的中断来说,只有配置了 NVIC 的设置,并开启才能被执行,否则是不会执行到中断服务函数里面去的。

3.5 编写中断服务函数

这是中断设置的最后一步,中断服务函数,是必不可少的,如果在代码里面开启了中断,但是没编写中断服务函数,就可能引起硬件错误,从而导致程序崩溃!所以在开启了某个中断后,一定要记得为该中断编写服务函数。在中断服务函数里面编写你要执行的中断后的操作。

4. 例程分析

4.1 配置外部中断对应IO

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 数 名: exti_gpio_config
//	功能说明: 外部中断GPIO参数配置
//	形    参: 无
//	返 回 值: 无
//	日    期: 2020-04-25
//  备    注: 
//	作    者: by 霁风AI
//---------------------------------------------------------------------------------------------------------------------------------------------
static void exti_gpio_config(void)
{
	GPIO_InitTypeDef gpio_init_config;

 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PORTA时钟
	
	gpio_init_config.GPIO_Pin  		= GPIO_Pin_0;//PA0
	gpio_init_config.GPIO_Mode 		= GPIO_Mode_IPD; //PA0设置成输入,默认下拉	  
	GPIO_Init(GPIOA, &gpio_init_config);//初始化GPIOA.0
}

4.2 配置外部中断参数

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 数 名: exti_config
//	功能说明: 外部中断参数配置
//	形    参: 无
//	返 回 值: 无
//	日    期: 2020-04-25
//  备    注: 
//	作    者: by 霁风AI
//---------------------------------------------------------------------------------------------------------------------------------------------
static void exti_config(void)
{
	EXTI_InitTypeDef exti_init_config;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	//外部中断,需要使能AFIO时钟
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);	//PA0设置为外部中断
	
	exti_init_config.EXTI_Line		= EXTI_Line0;
  	exti_init_config.EXTI_Mode 		= EXTI_Mode_Interrupt;	
  	exti_init_config.EXTI_Trigger 	= EXTI_Trigger_Rising;//上升沿触发
  	exti_init_config.EXTI_LineCmd 	= ENABLE;
  	
	EXTI_Init(&exti_init_config);	 	//根据EXTI_InitTypeDef中指定的参数初始化外设EXTI寄存器
}

4.3 配置中断向量

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 数 名: exit_nvic_config
//	功能说明: 中断向量参数配置
//	形    参: 无
//	返 回 值: 无
//	日    期: 2020-04-25
//  备    注: 
//	作    者: by 霁风AI
//---------------------------------------------------------------------------------------------------------------------------------------------
static void exti_nvic_config(void)
{
	NVIC_InitTypeDef nvic_init_config;
	
	nvic_init_config.NVIC_IRQChannel 					= EXTI0_IRQn;//使能按键所在的外部中断通道
	nvic_init_config.NVIC_IRQChannelPreemptionPriority 	= 0x02;//抢占优先级2
	nvic_init_config.NVIC_IRQChannelSubPriority 		= 0x02;//子优先级1
	nvic_init_config.NVIC_IRQChannelCmd 				= ENABLE;
	
	NVIC_Init(&nvic_init_config);
}

4.4 统一外部中断调用接口

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 数 名: exti_init
//	功能说明: 外部中断初始化
//	形    参: 	exti_no:中断号
//	返 回 值: 无
//	日    期: 2020-04-25
//  备    注: 外部调用此函数,实现EXTI的初始化配置
//	作    者: by 霁风AI
//---------------------------------------------------------------------------------------------------------------------------------------------
void exti_init(uint8_t exti_no)
{
	if (exti_no == 0)
	{
		exti_gpio_config();
		exti_config();
		exti_nvic_config();
	}
}

4.5 编写中断服务函数

//---------------------------------------------------------------------------------------------------------------------------------------------
//	函 数 名: EXTI0_IRQHandler
//	功能说明: 外部中断0服务函数
//	形    参: 无
//	返 回 值: 无
//	日    期: 2020-04-25
//  备    注: 
//	作    者: by 霁风AI
//---------------------------------------------------------------------------------------------------------------------------------------------
void EXTI0_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line0) != RESET)  
	{
		g_exti_cnt++;
		
		if (g_exti_cnt % 2)
		{
			Bsp_LedOn(0);	//点亮OLED0
		}
		else 
		{
			Bsp_LedOff(0);	//熄灭OLED0
		}
		
		if (g_exti_cnt > 200)
		{
			g_exti_cnt = 0;
		}
		
		EXTI_ClearITPendingBit(EXTI_Line0);	//清除EXTI0线路挂起
	}
}

补充:

在编写中断服务函数的时候会经常使用到两个函数。

(1)第一个函数是判断某个中断线上的中断是否发生(标志位是否置位):

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)

这个函数一般使用在中断服务函数的开头判断中断是否发生。

(2)第二个是清除某个中断线上的中断标志位:

void EXTI_ClearITPendingBit(uint32_t EXTI_Line)

这个函数一般应用在中断服务函数结束之前,清除中断标志位。


参考:

  1. STM32-外部中断实验
  2. STM32-外部中断学习笔记
  3. STM32之EXTI——外部中断
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值