• 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);		//清除中断标志位
    	}
    }
    
    
    我是这耀眼的瞬间,是划过天边的刹那火焰。
  • 相关阅读:
    前端利用vueelementadmin搭建流程总结
    redis持久化机制
    Java常用阻塞队列
    垃圾回收之并发情况下如何确定对象可达
    手写LRU算法
    SynchronousQueue详解
    (mysql)存储引擎、索引及优化、事务与锁
    (多线程)synchronized同步对象不能是Integer等类型
    (@Validated)参数合法性校验框架 的常用注解
    (Sql Server)分页
  • 原文地址:https://www.cnblogs.com/Rane/p/13601097.html
Copyright © 2020-2023  润新知