STM32外部中断(实现按键控制LED)

引言

“中断” 这个概念,指的是在单片机运行过程中,在指定条件发生时,停下当前所有工作,去执行中断处理函数内的内容。就像我们在教室上课时,突然地震了,不出意外的话我们都需要停下手中学习任务,去进行一系列的避险动作。

这一节我们通过中断的方式,完成通过按键控制LED亮灭的操作。




准备环节

中断相关知识

STM32的中断控制器支持19个外部中断/事件请求。这十九个外部中断为:

  • 线0~15:对应外部IO口的输入中断。
  • 线16:连接到PVD输出。
  • 线17:连接到连接到RTC时钟事件。
  • 线18:连接到USB唤醒事件。

配置使用时,需要先将IO口与相应中断线的映射关系建立,再对其进行使用。那映射关系是怎样的呢?

GPIOx.0 ~ GPIOx.15(x = A,B,C,D,E,F,G)分别对应中断线0 ~ 15

配置GPIO与中断线关系的函数是 void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)

eg:GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);

把GPIO作为EXTI外部中断时,需要打开AFIO时钟。

APIO时钟何时需要打开,具体可以参考这篇文章:

STM32的AFIO时钟什么时候需要开启

嵌套向量中断控制器(NVIC)

初始化完线上中断和中断条件等内容,还需要配置中断分组。配置中断分组之前,我们需要先确定如何进行分组。这里就需要用到NVIC。

关于NVIC的具体内容可查看这篇博文:嵌套向量中断控制器(NVIC)详解




编码环节

步骤

  • 初始化IO口输入
  • 开启AFIO时钟
  • 设置IO口与中断线的映射关系
  • 初始化线上中断、设置触发条件等
  • 配置中断分组,并使能中断
  • 编写中断服务函数

main.c(以下内容均省略头文件)

int main(void){
	delay_init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置NVIC终端分组2
	LED_Init();
	KEY_Init();
	EXTIX_Init();	//外部中断初始化
	LED1 = 0;
}

exti.h

#ifndef __EXTI_H
#define __EXIT_H	 
#include "sys.h"

void EXTIX_Init(void);	//外部中断初始化

#endif

exti.c

void EXTIX_Init(void)
{

	EXTI_InitTypeDef EXTI_InitStructure;	//外部中断结构体初始化
	NVIC_InitTypeDef NVIC_InitStructure;	//中断分组结构体初始化

	KEY_Init();

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);	//开启AFIO时钟

	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);	//映射IO口与中断线
	
    //以下为配置中断线初始化
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;		//中断模式
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;				//使能中断线
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;				//中断线标号
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;	//触发方式

	EXTI_Init(&EXTI_InitStructure);

	//以下为中断优先级的配置
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;		//声明使用的中断是哪一个
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;	//设置抢占优先级为2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;	//设置子优先级为3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//使能中断

	NVIC_Init(&NVIC_InitStructure);
}

void EXTI0_IRQHandler(void)		//中断服务函数
{
	delay_ms(10);			//软件去抖
	if(WK_UP==1)
	{				 
		LED0 = !LED0;
		LED1 = !LED1;
	}
	EXTI_ClearITPendingBit(EXTI_Line0);		//清除中断位
}




补充

中断服务函数

中断服务函数的名称是固定的,写错会导致无法中断。

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

  • EXTI0_IRQHandler
  • EXTI1_IRQHandler
  • EXTI2_IRQHandler
  • EXTI3_IRQHandler
  • EXTI4_IRQHandler
  • EXTI9_5_IRQHandler
  • EXTI15_10_IRQHandler

中断线0 ~ 4各对应一个中断服务函数,中断线5 ~ 9共用 EXTI9_5_IRQHandler,中断线10 ~ 15共用 EXTI15_10_IRQHandler

中断服务函数常规格式

void EXTI3_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line3)!=RESET)		//判断中断线上的中断是否发生
	{
		//这里写需要执行的服务
		EXTI_ClearITPendingBit(EXTI_Line3);		//清除中断标志位
	}
}

posted @ 2020-09-02 12:35  Rane  阅读(6659)  评论(0编辑  收藏  举报