STM32外部中断标准库函数详解(三)

前言

上一篇文章已经介绍了如何用按键点灯,使用的是按键扫描的方式,实现了点灯的第二步。这一篇则介绍如何用外部中断的方式实现按键点灯的过程。

一、实验原理

1.外部中断的定义

中断想必大家都知道,通俗来说也就是你现在在做事情1,被打扰了先去做了事情2,事情2做完了回去继续做事情1。

而STM32的外部中断也是如此,只是它做的事情跟你做的不太一样罢了,而且对处理事情有更为严格的优先级关系。举个通俗的例子,它在做事情1,但是被事情2和事情3同时打扰了,事情2的优先级大于事情3,那么它会先去做事情2再去做事情3,都做完了才回归主线事情1。所以有利于提高cpu的利用率。

2.外部中断的介绍

嵌入式要学好必然要把图看好,那么先上个外部中断的流程框图:

2.1 STM32的外部中断线

每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。

 STM32的中断控制器支持19个外部中断/事件请求:

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

    每个IO口都可以对应作为中断,几个IO口为一组映射到一个中断线上,如GPIOx.0映射到EXTI0,GPIOx.1映射到EXTI1,…,GPIOx.15映射到EXTI15.

    外部中断通用I/O映像

    2.3外部中断所需寄存器

    STM32外部中断需要用到以下几个寄存器:

    1.  中断屏蔽寄存器(EXTI_IMR)
    2. 事件屏蔽寄存器(EXTI_EMR)
    3. 上升沿触发选择寄存器(EXTI_RTSR)
    4. 下降沿触发选择寄存器(EXTI_FTSR)
    5. 软件中断事件寄存器(EXTI_SWIER)
    6. 挂起寄存器(EXTI_PR) 

    2.4外部中断与中断服务函数

    IO口外部中断只有7个中断服务函数

  • EXTI0~EXTI4 分别对应一个中断服务函数
  • EXTI5~EXTI9 对应一个中断服务函数 
  • EXTI10~EXTI15 对应一个中断服务函数
  • ps:这边值得注意的是EXTI5~EXTI9与EXTI10~EXTI15对应的都只有一个中断服务函数,所以要是出现在这范围出现多个线程的中断会有点问题,但在后面对这问题进行了解决。而且还有多个IO口出现同一线程该如何区分开的问题,也对其进行解决。

    二、实验步骤

    1.NVIC配置

    1. 对NVIC初始化,用到 NVIC_InitTypeDef 结构体,其中四个成员:  

  • NVIC_IRQChannel参数来选择将要配置的中断向量;
  • NVIC_IRQChannelCmd参数来进行使能(ENABLE)或关闭(DISABLE)该中断;
  • NVIC_IRQChannelPreemptionPriority成员要配置中断向量的抢占优先级;
  • NVIC_IRQChannelSubPriority需要配置中断向量的子优先级(响应优先级);
  • 2. NVIC只可配置16种中断向量的优先级:编号越小,优先级别越高;

    3. 抢占优先级:是指打断其它中断,会出现嵌套中断;

    4. 子优先级(响应优先级):先处理响应优先级高的中断; 

    /* 选择中断优先级配置组为4个抢占式优先级和4个子优先级,可以参考misc.h文件了解相关设置 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    /* 使能KEY1所在的外部中断通道 */
    NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQCHANNEL;
    /* 设置抢占式优先级为2 */
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; 
    /* 设置子优先级为3 */
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
    /* 使能外部中断通道 */
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	
    /* 初始化配置嵌套向量中断控制器 */
    NVIC_Init(&NVIC_InitStructure); 

    2.EXTI配置

    EXTI的配置步骤如下所示:

     ①使能EXTIx线的IO时钟和复用时钟(AFIO)

     ②配置EXTI中断线与I/O的映射关系

     ③EXTI的I/O口线引脚和工作模式的配置

     ④配置EXTIx线的中断优先级

     ⑤EXTI 中断线工作模式配置

    /* 为启用IO引脚中断功能需要使能复用功能时钟 */
    KEY1_RCC_CLOCKCMD(KEY1_RCC_CLOCKGPIO | KEY1_RCC_CLOCKAFIO,ENABLE);
    /* 选择PE7作为中断输入源 */
    GPIO_EXTILineConfig(KEY1_GPIO_PORTSOURCE,KEY1_GPIO_PINSOURCE);
    /* KEY1对应的断线 */
    EXTI_InitStructure.EXTI_Line=KEY1_EXITLINE;
    /* 外部中断模式 */
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
    /* 上升沿触发方式 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    /* 使能中断 */
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    /* 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 */
    EXTI_Init(&EXTI_InitStructure);

    其中AFIO的作用是信号传输媒介或者说是信号搬运工,EXTI的时钟是由AFIO提供的,所以需要开启。而AFIO时钟在APB2总线上的原因是端口重映射之后,映射的新引脚都是GPIO的引脚,GPIOx又是APB2的外设,使用APB2给其提供时钟非常合适。

    参考:AFIO时钟误区及其用法解析-CSDN博客

    3.中断函数

    /* 中断服务函数,用于产生中断动作 */
    EXTIx_IRQHandler();
    /* 中断判断函数,用于判断中断动作 */
    EXTI_GetITStatus()
    /* 中断清除函数,用于清除中断动作	*/
    EXTI_ClearITPendingBit()

    上面说过由于EXTI5~EXTI9与EXTI10~EXTI15分别对于中断服务函数EXTI9_5_IRQHandler和EXTI15_10_IRQHandler,所以要是出现在这范围出现多个线程的中断,可能会出现问题,则需要进行对线程判断的处理,以及对IO口判断的处理。

    void KEY_IRQHANDLER(void)
    {
    	/* 处理Line7的中断 */
        if(EXTI_GetITStatus(EXTI_Line7) != RESET)
        {
            /* 处理GPIOA的PIN7的中断,若没有多个IO占用Line7可以注释 */
            if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) == Bit_SET) // 检查引脚状态
            {
                //事件
            }
            
            /* 处理EXTI_Line7的中断 */
            EXTI_ClearITPendingBit(EXTI_Line7); 
        }
    
        // 重复上述逻辑,检查其他线(如EXTI_Line5, EXTI_Line6,...)
    }

    三、实操代码

    程序分为3个文件:bsp_key.c、bsp_key.h、main.c

    1.bsp_key.c

    这边值得注意的是KEY的引脚线序,对下方代码进行选取,我都为大家列好情况了,看下注释即可。

    /* 包含头文件 ----------------------------------------------------------------*/
    #include "bsp/key/bsp_key.h"
    
    
    /**
      * 函数功能: 配置KEY作为中断引脚并使能中断
      * 输入参数:无
      * 返 回 值: 无
      * 说    明:配置KEY为上升沿中断,当按下按键时就有一个从低电平变为高
      *           电平过程。
      */
    void KEY1_EXIT_Config(void)
    {
      /* 定义IO硬件初始化结构体变量 */
      GPIO_InitTypeDef GPIO_InitStructure;
      /* 定义外部中断线初始化结构体变量 */
      EXTI_InitTypeDef EXTI_InitStructure;
      /* 定义嵌套向量中断控制器初始化结构体变量 */
      NVIC_InitTypeDef NVIC_InitStructure;
      
      /* 为启用IO引脚中断功能需要使能复用功能时钟 */
      KEY1_RCC_CLOCKCMD(KEY1_RCC_CLOCKGPIO | KEY1_RCC_CLOCKAFIO,ENABLE);
      
      /* 设定KEY1对应引脚IO编号 */
      GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN;  
      /* 设定KEY1对应引脚IO最大操作速度 :GPIO_Speed_50MHz */
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
      /* 设定KEY1对应引脚IO为浮空输入模式 */
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
      /* 初始化KEY1对应引脚IO */
      GPIO_Init(KEY1_GPIO, &GPIO_InitStructure);
    
      /* 选择PE7作为中断输入源 */
      GPIO_EXTILineConfig(KEY1_GPIO_PORTSOURCE,KEY1_GPIO_PINSOURCE);
      
      /* KEY1对应的断线 */
      EXTI_InitStructure.EXTI_Line=KEY1_EXITLINE;
      /* 外部中断模式 */
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
      /* 上升沿触发方式 */
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
      /* 使能中断 */
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      /* 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 */
      EXTI_Init(&EXTI_InitStructure);
      
      /* 选择中断优先级配置组为4个抢占式优先级和4个子优先级,可以参考misc.h文件了解相关设置 */
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      
      /* 使能KEY1所在的外部中断通道 */
      NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQCHANNEL;
      /* 设置抢占式优先级为2 */
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; 
      /* 设置子优先级为3 */
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
      /* 使能外部中断通道 */
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	
      /* 初始化配置嵌套向量中断控制器 */
      NVIC_Init(&NVIC_InitStructure); 
    }
    
    void KEY2_EXIT_Config(void)
    {
      /* 定义IO硬件初始化结构体变量 */
      GPIO_InitTypeDef GPIO_InitStructure;
      /* 定义外部中断线初始化结构体变量 */
      EXTI_InitTypeDef EXTI_InitStructure;
      /* 定义嵌套向量中断控制器初始化结构体变量 */
      NVIC_InitTypeDef NVIC_InitStructure;
      
      /* 为启用IO引脚中断功能需要使能复用功能时钟 */
      KEY1_RCC_CLOCKCMD(KEY2_RCC_CLOCKGPIO | KEY2_RCC_CLOCKAFIO,ENABLE);
      
      /* 设定KEY2对应引脚IO编号 */
      GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN;  
      /* 设定KEY2对应引脚IO最大操作速度 :GPIO_Speed_50MHz */
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
      /* 设定KEY2对应引脚IO为浮空输入模式 */
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
      /* 初始化KEY2对应引脚IO */
      GPIO_Init(KEY2_GPIO, &GPIO_InitStructure);
    
      /* 选择PE8作为中断输入源 */
      GPIO_EXTILineConfig(KEY2_GPIO_PORTSOURCE,KEY2_GPIO_PINSOURCE);
      
      /* KEY2对应的断线 */
      EXTI_InitStructure.EXTI_Line=KEY2_EXITLINE;
      /* 外部中断模式 */
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
      /* 上升沿触发方式 */
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
      /* 使能中断 */
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      /* 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 */
      EXTI_Init(&EXTI_InitStructure);
      
      /* 选择中断优先级配置组为4个抢占式优先级和4个子优先级,可以参考misc.h文件了解相关设置 */
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      
      /* 使能KEY2所在的外部中断通道 */
      NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQCHANNEL;
      /* 设置抢占式优先级为0 */
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; 
      /* 设置子优先级为0 */
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
      /* 使能外部中断通道 */
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	
      /* 初始化配置嵌套向量中断控制器 */
      NVIC_Init(&NVIC_InitStructure); 
    }
    
    void KEY3_EXIT_Config(void)
    {
      /* 定义IO硬件初始化结构体变量 */
      GPIO_InitTypeDef GPIO_InitStructure;
      /* 定义外部中断线初始化结构体变量 */
      EXTI_InitTypeDef EXTI_InitStructure;
      /* 定义嵌套向量中断控制器初始化结构体变量 */
      NVIC_InitTypeDef NVIC_InitStructure;
      
      /* 为启用IO引脚中断功能需要使能复用功能时钟 */
      KEY1_RCC_CLOCKCMD(KEY3_RCC_CLOCKGPIO | KEY3_RCC_CLOCKAFIO,ENABLE);
      
      /* 设定KEY3对应引脚IO编号 */
      GPIO_InitStructure.GPIO_Pin = KEY3_GPIO_PIN;  
      /* 设定KEY3对应引脚IO最大操作速度 :GPIO_Speed_50MHz */
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
      /* 设定KEY3对应引脚IO为浮空输入模式 */
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
      /* 初始化KEY3对应引脚IO */
      GPIO_Init(KEY1_GPIO, &GPIO_InitStructure);
    
      /* 选择PE9作为中断输入源 */
      GPIO_EXTILineConfig(KEY3_GPIO_PORTSOURCE,KEY3_GPIO_PINSOURCE);
      
      /* KEY3对应的断线 */
      EXTI_InitStructure.EXTI_Line=KEY3_EXITLINE;
      /* 外部中断模式 */
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
      /* 上升沿触发方式 */
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
      /* 使能中断 */
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      /* 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 */
      EXTI_Init(&EXTI_InitStructure);
      
      /* 选择中断优先级配置组为4个抢占式优先级和4个子优先级,可以参考misc.h文件了解相关设置 */
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      
      /* 使能KEY3所在的外部中断通道 */
      NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQCHANNEL;
      /* 设置抢占式优先级为1 */
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; 
      /* 设置子优先级为1 */
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
      /* 使能外部中断通道 */
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	
      /* 初始化配置嵌套向量中断控制器 */
      NVIC_Init(&NVIC_InitStructure); 
    }
    
    /**
      * 函数功能: 针对KEY多根线序为5-9的中断服务函数
      * 输入参数:无
      * 返 回 值: 无
      * 说    明:在stm32f103检测到上升沿信号后会自动进入对应的中断服务函数,我们可以在
      *           服务函数内实现一些处理。
      *			  多根线序为5-9的线
      */
    void KEY_IRQHANDLER(void)
    {
    
    	if(EXTI_GetITStatus(EXTI_Line7) != RESET)
        {
    		/* 延时一小段时间,消除抖动 */
    	    Delay(10); 
            LED1_TOGGLE; 
    		/* 处理EXTI_Line7的中断 */
            EXTI_ClearITPendingBit(EXTI_Line7); 
        }
    
        if(EXTI_GetITStatus(EXTI_Line8) != RESET)
        {
    		Delay(10); 
            LED2_TOGGLE; 
    		/* 处理EXTI_Line8的中断 */
            EXTI_ClearITPendingBit(EXTI_Line8); 
        }
    	 if(EXTI_GetITStatus(EXTI_Line9) != RESET)
        {
    		 Delay(10); 
    		 LED3_TOGGLE; 
    		/* 处理EXTI_Line9的中断 */
            EXTI_ClearITPendingBit(EXTI_Line9); 
    	 }
        // 重复上述逻辑,检查其他线(如EXTI_Line5, EXTI_Line6)
    }
    
    /**
      * 函数功能: 针对KEY线序单独分开的中断服务函数
      * 输入参数:无
      * 返 回 值: 无
      * 说    明:在stm32f103检测到上升沿信号后会自动进入对应的中断服务函数,我们可以在
      *           服务函数内实现一些处理。
      *			  线序单独分开的线
      */
    //void KEY1_IRQHANDLER(void)
    //{
    //  /* 确保是否产生了EXTI Line中断 */
    //	if(EXTI_GetITStatus(KEY1_EXITLINE) != RESET)
    //	{
    //      Delay(10); 
    //		/* LED1灯翻转	*/	
    //		LED1_TOGGLE;
    //     /* 清除中断标志位	*/
    //	    EXTI_ClearITPendingBit(KEY1_EXITLINE);     
    //	}
    //}
    
    //void KEY2_IRQHANDLER(void)
    //{
    //	if(EXTI_GetITStatus(KEY2_EXITLINE) != RESET)
    //	{
    //      Delay(10); 
    //		LED2_TOGGLE;
    //		EXTI_ClearITPendingBit(KEY2_EXITLINE);     
    //	}
    //}
    
    //void KEY3_IRQHANDLER(void)
    //{
    //	if(EXTI_GetITStatus(KEY3_EXITLINE) != RESET)
    //	{
    //      Delay(10); 
    //		LED3_TOGGLE;
    //		EXTI_ClearITPendingBit(KEY3_EXITLINE);     
    //	}
    //}

    2.bsp_key.h

    这边值得注意的是KEY的引脚线序,对下方代码进行选取,我都为大家列好情况了,看下注释即可。

    #ifndef __BSP_KEY_H__
    #define __BSP_KEY_H__
    
    /* 包含头文件 ----------------------------------------------------------------*/
    #include <stm32f10x.h>
    #include "bsp/delay/delay.h"
    #include "bsp/led/bsp_led.h"
    
    /* 类型定义 --------------------------------------------------------------*/
    typedef enum
    {
      KEY_UP   = 0,
      KEY_DOWN = 1,
      KEY_DOWN_LONG   = 2,
    }KEYState_TypeDef;
    
    /* 宏定义 --------------------------------------------------------------------*/
    #define KEY1                          (uint8_t)0x01
    #define KEY2                          (uint8_t)0x02
    #define KEY3                          (uint8_t)0x04
    #define IS_KEY_TYPEDEF(KEY)           (((KEY) == KEY1) || ((KEY) == KEY2) || ((KEY) == KEY3))
    
    /* 宏定义 --------------------------------------------------------------------*/
    #define KEY1_RCC_CLOCKCMD             RCC_APB2PeriphClockCmd
    #define KEY1_RCC_CLOCKGPIO            RCC_APB2Periph_GPIOE
    #define KEY1_GPIO_PIN                 GPIO_Pin_7
    #define KEY1_GPIO                     GPIOE
    #define KEY1_DOWN_LEVEL               0  /* 根据原理图设计,KEY1按下时引脚为低电平,所以这里设置为0 */
    #define KEY1_RCC_CLOCKAFIO            RCC_APB2Periph_AFIO
    #define KEY1_GPIO_PORTSOURCE          GPIO_PortSourceGPIOE
    #define KEY1_GPIO_PINSOURCE           GPIO_PinSource7
    #define KEY1_EXITLINE                 EXTI_Line7
    
    /* 根据线序来,需要用到则取消注释并修改*/
    //#define KEY1_IRQCHANNEL               EXTI1_IRQn     
    //#define KEY1_IRQHANDLER               EXTI1_IRQHandler
    
    #define KEY2_RCC_CLOCKCMD             RCC_APB2PeriphClockCmd
    #define KEY2_RCC_CLOCKGPIO            RCC_APB2Periph_GPIOE
    #define KEY2_GPIO_PIN                 GPIO_Pin_8
    #define KEY2_GPIO                     GPIOE
    #define KEY2_DOWN_LEVEL               0  /* 根据原理图设计,KEY2按下时引脚为低电平,所以这里设置为0 */
    #define KEY2_RCC_CLOCKAFIO            RCC_APB2Periph_AFIO
    #define KEY2_GPIO_PORTSOURCE          GPIO_PortSourceGPIOE
    #define KEY2_GPIO_PINSOURCE           GPIO_PinSource8
    #define KEY2_EXITLINE                 EXTI_Line8
    
    /* 根据线序来,需要用到则取消注释并修改*/
    //#define KEY2_IRQCHANNEL               EXTI2_IRQn      
    //#define KEY2_IRQHANDLER               EXTI2_IRQHandler
    
    #define KEY3_RCC_CLOCKCMD             RCC_APB2PeriphClockCmd
    #define KEY3_RCC_CLOCKGPIO            RCC_APB2Periph_GPIOE
    #define KEY3_GPIO_PIN                 GPIO_Pin_9
    #define KEY3_GPIO                     GPIOE
    #define KEY3_DOWN_LEVEL               0  /* 根据原理图设计,KEY3按下时引脚为低电平,所以这里设置为0 */
    #define KEY3_RCC_CLOCKAFIO            RCC_APB2Periph_AFIO
    #define KEY3_GPIO_PORTSOURCE          GPIO_PortSourceGPIOE
    #define KEY3_GPIO_PINSOURCE           GPIO_PinSource9
    #define KEY3_EXITLINE                 EXTI_Line9
    
    /* 根据线序来,需要用到则取消注释并修改*/
    //#define KEY3_IRQCHANNEL               EXTI3_IRQn      
    //#define KEY3_IRQHANDLER               EXTI3_IRQHandler
    
    /* KEY多根线序为5-9,不用则注释 */
    #define KEY_IRQCHANNEL               EXTI9_5_IRQn 
    #define KEY_IRQHANDLER               EXTI9_5_IRQHandler
    
    
    #define IRQ_DISABLE                   __set_PRIMASK(1)		/* 关闭总中断 */  
    #define IRQ_ENABLE                    __set_PRIMASK(0)		/* 开放总中断 */ 
    
    /* 扩展变量 ------------------------------------------------------------------*/
    /* 函数声明 ------------------------------------------------------------------*/
    void KEY_GPIO_Init(void);
    KEYState_TypeDef KEYx_StateSet(GPIO_TypeDef* KEYx_GPIO, uint16_t KEYx_GPIO_PIN, uint8_t KEYx_DOWN_LEVEL);
    KEYState_TypeDef KEYx_Choice(int KEYIndex);
    void KEY_LED(void);
    
    void KEY1_EXIT_Config(void);
    void KEY2_EXIT_Config(void);
    void KEY3_EXIT_Config(void);
    #endif  // __BSP_KEY_H__
    
    

    3.main.c

    这边值得注意的while函数里面什么都不用加,较为简单,运行就完事儿了!

    
    /* 包含头文件 ----------------------------------------------------------------*/
    #include "stm32f10x.h"
    #include "bsp/led/bsp_led.h"
    #include "bsp/key/bsp_key.h"
    #include "bsp/delay/delay.h"
    
    
    /* 函数体 --------------------------------------------------------------------*/
    
    /**
      * 函数功能: 主函数.
      * 输入参数: 无
      * 返 回 值: 无
      * 说    明: 无
      */
    int main(void)
    {
    	LED_GPIO_Init();
    	KEY1_EXIT_Config();
    	KEY2_EXIT_Config();
    	KEY3_EXIT_Config();
    
      while (1)
      {
        //什么都不加
      }
    }
    
    

    四、实验效果

    外部中断-点灯

    结束语

    本文以STM32VET6为例讲解了用外部中断控制按键点灯的实现方法,并解决了几个可能会在实际中遇到的问题,并在代码中也给出相应注释。希望对大家有所帮助!如果还有什么问题,欢迎评论区留言,谢谢!

    作者:是覆盖对于变化

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32外部中断标准库函数详解(三)

    发表评论