STM32 EXTI(外部中断)

中断是什么?

例:在公司上班打代码,然后经理打电话过去谈话,谈话到一半,老婆打电话要去医院,然后回来医院继续谈话,然后继续工作打代码。

打断原来做的事情 -> 打断工作
保留现场 -> 保留工作进度
处理中断 -> 谈话
回到现场 -> 继续工作

如何配置中断

1.初始化原来中断的GPIO口

2.初始化EXTI(什么是EXTI?)
边沿检测电路 -> 上升沿/下降沿触发中断

3.配置NVIC(中断优先级)
配置中断的优先级,中断嵌套

4.编写中断服务函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

EXTI 初始化结构体
 typedef struct {
 uint32_t EXTI_Line; // 中断/事件线
 EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
 EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
 FunctionalState EXTI_LineCmd; // EXTI 使能
 } EXTI_InitTypeDef;
  1. EXTI_Line:EXTI中断/事件线选择,可选 EXTI0 至 EXTI19
  2. EXTI_Mode:EXTI 模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
  3. EXTI_Trigger:EXTI 边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发 (EXTI_Trigger_Falling) 或者上升沿和下降沿都触发
  4. ( EXTI_Trigger_Rising_Falling)。 EXTI_LineCmd:控制是否使能 EXTI 线,可选使能 EXTI线(ENABLE)或禁用 (DISABLE)。
    在这里插入图片描述
NVIC 初始化结构体
typedef struct
{
  uint8_t NVIC_IRQChannel;                   //设置中断通道
  uint8_t NVIC_IRQChannelPreemptionPriority; //设置抢占优先级
  uint8_t NVIC_IRQChannelSubPriority;		 //设置响应优先级
  FunctionalState NVIC_IRQChannelCmd;		 //设置是否使能或禁用
} NVIC_InitTypeDef;

在这里插入图片描述
本文章是学习笔记,部分内容转载自https://blog.csdn.net/zxh1592000/article/details/80280715
此文章讲的非常详细。

震动感应灯

上篇文章做了感应灯,现在来用中断做震动感应灯。

按照如何上面如何配置中断的四个步骤来编写。

1.初始化原来中断的GPIO口

GPIO口配置我直接复制了shake.c(震动传感器)内容

2.初始化EXTI

EXTI_Line

因为震动传感器为PA1,所以exti_init.EXTI_Line = EXTI_Line1;

GPIO1的中断挂在line1上了,硬件决定的,没法改

EXTI_Mode_Interrupt

EXTIMode有两种,一种是Interrupt(中断模式),另一种是Event(事件模式)

如果想深入了解这两种模式有什么区别可以参考下面文章
http://blog.sina.com.cn/s/blog_4d1854230101dcui.html

EXTI_Trigger_Falling

震动传感器
未发生震动 - - 高电平
发生震动 - - - -低电平

在这里插入图片描述
所以我们需要在下降沿的时候中断
exti_init.EXTI_Trigger = EXTI_Trigger_Falling;

3.配置NVIC(中断优先级)

NVIC_IRQChannel

可以去stm32f10x.h中找到,因为EXTI_Line是1

所以nvic_init.NVIC_IRQChannel=EXTI1_IRQn;
在这里插入图片描述

NVIC_IRQChannelPreemptionPriority(抢占优先级)

说到优先级,可以去misc.h中找到图下代码
在这里插入图片描述
我们需要配置一个优先级组,因为我们就一个中断,所以随便选择,我写的是第三种
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

根据组的不同抢占优先级和子优先级的范围就不同,这就随便写了。
nvic_init.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_IRQChannelSubPriority(子优先级)

nvic_init.NVIC_IRQChannelSubPriority = 1;

配置完NVIC我们需要配置中断时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

还需要将GPIO1设置为外部中断源
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);

4.编写中断服务函数

在main.c中编写中断函数
中断函数在启动文件中
在这里插入图片描述
我们需要判断中断是否发生
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);

这个函数中有个标识位RESET也就是0的意思
在这里插入图片描述
发生了中断开灯就完了

我们还需要写一个清除中断标志,要不中断创建了一个标志不清除,那么这个标志一直存在,就像一直申请内存,用完不释放,一直被占用导致内存泄漏一样,所以需要清除一下。
void EXTI_ClearFlag(uint32_t EXTI_Line);

提示:发生中断时中断函数会自动执行

代码

exti.h

#include "stm32f10x.h"
void exti_init(void);

exti.c

#include "stm32f10x.h"
#include "exti.h"

void exti_init(void)
{
	//1.ÅäÖÃGPIO
	GPIO_InitTypeDef shake_init;
	EXTI_InitTypeDef exti_init;
	NVIC_InitTypeDef nvic_init;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	shake_init.GPIO_Mode = GPIO_Mode_IPD;
	shake_init.GPIO_Pin = GPIO_Pin_1;
	shake_init.GPIO_Speed	= GPIO_Speed_10MHz;
	
	GPIO_Init(GPIOA, &shake_init);
	
	//2.ÅäÖÃEXTIÍⲿÖжÏ
	exti_init.EXTI_Line 	 = EXTI_Line1;
	exti_init.EXTI_Mode 	 = EXTI_Mode_Interrupt;
	exti_init.EXTI_Trigger = EXTI_Trigger_Falling;
	exti_init.EXTI_LineCmd = ENABLE;
	
	EXTI_Init(&exti_init);
	
	//3.ÅäÖÃNVICÖжϿØÖÆÆ÷
	nvic_init.NVIC_IRQChannel 									= EXTI1_IRQn;
	nvic_init.NVIC_IRQChannelPreemptionPriority = 1;
	nvic_init.NVIC_IRQChannelSubPriority 				= 1;
	nvic_init.NVIC_IRQChannelCmd 								= ENABLE;

  NVIC_Init(&nvic_init);
}

main.c

#include "stm32f10x.h"
#include "led.h"
#include "relay.h"
#include "shake.h"
#include "exti.h"

void delay(uint16_t time)
{
	uint16_t i =0;
	while(time--){
		i=12000;
		while(i--);
	}
}

int main()
{
	Led_init();
	Relay_Init();
	Shake_init();
	exti_init();
	
	GPIO_SetBits(GPIOA, GPIO_Pin_3);
	GPIO_SetBits(GPIOC, GPIO_Pin_13);
	
	while(1)
	{
		
	}

}

void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus( EXTI_Line1 ) != RESET){// ÅжÏÊÇ·ñ·¢ÉúÖжÏ
		GPIO_ResetBits(GPIOA, GPIO_Pin_3);
		delay(1000);
		GPIO_SetBits(GPIOA, GPIO_Pin_3);
	}

	EXTI_ClearFlag(EXTI_Line1);
	
}

  • 9
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一只小阿大:)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值