野火F1开发板STM32案例-外部中断(按键)使用

    科技2022-07-10  92

    野火F1开发板STM32案例-外部中断(按键)使用

    硬件平台

    野火STM32F103ZET6 霸道V2开发板正点原子F1系列开发板

    软件平台

    Keil MDK 5.31串口调试助手

    工程下载https://download.csdn.net/download/weixin_43599390/12910397

    Gitee st-demo.

    中断相关概念

    中断配置寄存器 # 配置中断时,使用ISER、 ICER 和 IP 寄存器, ## ISER 是中断使能寄存器 ## ICER 是中断清除寄存器 ## IP 是中断优先级寄存器 中断优先级 1. 数值越小,优先级越高 2. STM32F103 中只使用4位,高4位有效。 3. 用于表达优先级的高 4 位又被分组成抢占式优先级和响应优先级,称为“亚优先级”或“副优先级” 4. 每个中断源都需要被指定这两种优先级。 中断配置步骤 1.使能外设中断 6. 设置中断优先级分组 初始化 NVIC_InitTypeDef 结构体,设置抢占优先级和响应优先级,使能中断请求。 typedef struct { uint8_t NVIC_IRQChannel; //中断源 uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级 uint8_t NVIC_IRQChannelSubPriority; //响应优先级 FunctionalState NVIC_IRQChannelCmd; //中断使能或失能 } NVIC_InitTypeDef; NVIC_IRQChannel 中断源:中断源的设置,不同的外设中断,中断源不一样 NVIC_IRQChannelPreemptionPriority //抢占优先级 NVIC_IRQChannelSubPriority //响应优先级 NVIC_IRQChannelCmd //中断使能或失能:使能配置为 ENABLE,失能配置为 DISABLE。 NVIC_IRQChannel //中断源 /****** Cortex-M3 Processor Exceptions Numbers ***************************************************/ NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */ BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */ UsageFault_IRQn = -10, /*!< 6 Cortex-M3 Usage Fault Interrupt */ SVCall_IRQn = -5, /*!< 11 Cortex-M3 SV Call Interrupt */ DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 Debug Monitor Interrupt */ PendSV_IRQn = -2, /*!< 14 Cortex-M3 Pend SV Interrupt */ SysTick_IRQn = -1, /*!< 15 Cortex-M3 System Tick Interrupt */ /****** STM32 specific Interrupt Numbers *********************************************************/ WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */ TAMPER_IRQn = 2, /*!< Tamper Interrupt */ RTC_IRQn = 3, /*!< RTC global Interrupt */ FLASH_IRQn = 4, /*!< FLASH global Interrupt */ RCC_IRQn = 5, /*!< RCC global Interrupt */ EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */ DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */ DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */ DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */ DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */ DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */

    STM32F103 中断向量表

    EXTI外部中断

    1. STM32F10x 外部中断/事件控制器(EXTI)包含多达 20 个用于产生事件/中断请求的边沿检测器。 2. EXTI 的每根输入线都可单独进行配置,以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发) 还可独立地被屏蔽。 3. EXIT功能:产生中断;产生事件.

    STM32 EXIT框架图

    EXTI外部中断步骤

    使能I0口时钟,配置I0口模式为输入开启AFIO时钟,设置I0口与中断线的映射关系配置中断分组(NVIC),使能中断初始化EXTI,选择触发方式编写EXTI中断服务函数

    GPIO引脚配置(本文中和外部中断bsp_exit.h一起进行初始化,可以分开进行配置相关函数)

    (一般配置过程类似,无论使用什么外设,UART,IIC,SPI,ADC 一般情况都要GPIO初始化)

    //定义GPIO初始化结构体 //使能 GPIO时钟 (时钟分频) //设置相关外部设备的对应引脚 //设置GPIO端口模式(GPIO输入 GPIO输出) //设置生效(GPIO端口启动生效) # GPIO输入模式 void initKey(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIO时钟 (时钟分频) GPIO_InitStructure.GPIO_Pin = KEY_UP_PIN|KEY_DOWN_PIN;//设置相关外部设备的对应引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置上拉输入 //设置GPIO端口模式 GPIO_Init(GPIOA, &GPIO_InitStructure); //设置生效(GPIO端口启动生效) } # GPIO输出模式 void initLED(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIO时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //设置对应引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //工作速度50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //设置生效 GPIO_ResetBits(GPIOB, GPIO_Pin_5); //默认低电平,LED不 }

    配置嵌套向量中断控制器NVIC步骤

    定义NVIC结构体 NVIC_InitTypeDef 结构体 typedef struct { uint8_t NVIC_IRQChannel; //中断源 uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级 uint8_t NVIC_IRQChannelSubPriority; //响应优先级 FunctionalState NVIC_IRQChannelCmd; //中断使能或失能 } NVIC_InitTypeDef; 配置NVIC为优先级组 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 配置中断源 NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ; // #define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA // #define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0 // #define KEY1_INT_EXTI_LINE EXTI_Line0 // #define KEY1_INT_EXTI_IRQ EXTI0_IRQn 配置抢占优先级 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 配置子优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 使能中断通道 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 初始化NVIC NVIC_Init(&NVIC_InitStructure);

    配置 EXTI中断口,并设置中断优先级步骤流程

    1. 定义GPIO_InitTypeDef EXTI_InitTypeDef 结构体 GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; typedef struct { uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins. This parameter can be a value of @ref GPIOSpeed_TypeDef */ GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins. This parameter can be a value of @ref GPIOMode_TypeDef */ }GPIO_InitTypeDef; typedef struct { uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled. This parameter can be any combination of @ref EXTI_Lines */ EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines. This parameter can be a value of @ref EXTIMode_TypeDef */ EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines. This parameter can be a value of @ref EXTIMode_TypeDef */ FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines. This parameter can be set either to ENABLE or DISABLE */ }EXTI_InitTypeDef;

    /*开启按键GPIO口的时钟*/ RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE); /* 配置 NVIC 中断*/ NVIC_Configuration();
    GPIO引脚配置
    /*--------------------------KEY1配置-------------------------*/ /* 选择按键用到的GPIO */ GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN; /* 配置为浮空输入 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure); /*------------------------KEY2配置-----------------------------*/ /* 选择按键用到的GPIO */ GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN; /* 配置为浮空输入 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
    中断配置
    中断信号源EXIT模式外部中断触发类型使能中断EXIT中断初始化 /* 选择EXTI的信号源 */ GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE; /* EXTI为中断模式 */ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; /* 上升沿中断 */ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; /* 使能中断 */ EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);

    BSP_EXIT.H

    //引脚定义 #define KEY1_INT_GPIO_PORT GPIOA #define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO) #define KEY1_INT_GPIO_PIN GPIO_Pin_0 #define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA #define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0 #define KEY1_INT_EXTI_LINE EXTI_Line0 #define KEY1_INT_EXTI_IRQ EXTI0_IRQn #define KEY1_IRQHandler EXTI0_IRQHandler #define KEY2_INT_GPIO_PORT GPIOC #define KEY2_INT_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO) #define KEY2_INT_GPIO_PIN GPIO_Pin_13 #define KEY2_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOC #define KEY2_INT_EXTI_PINSOURCE GPIO_PinSource13 #define KEY2_INT_EXTI_LINE EXTI_Line13 #define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn #define KEY2_IRQHandler EXTI15_10_IRQHandler

    BSP_EXIT.C

    配置嵌套向量中断控制器NVIC

    #include “bsp_exit.h” /** * @brief 配置嵌套向量中断控制器NVIC * @param 无 * @retval 无 */ static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 配置NVIC为优先级组1 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* 配置中断源:按键1 */ NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ; /* 配置抢占优先级 */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 配置子优先级 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断通道 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* 配置中断源:按键2,其他使用上面相关配置 */ NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ; NVIC_Init(&NVIC_InitStructure); }

    配置 IO为EXTI中断口,并设置中断优先级

    void EXTI_Key_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; /*开启按键GPIO口的时钟*/ RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE); /* 配置 NVIC 中断*/ NVIC_Configuration(); /*--------------------------KEY1配置-----------------------------*/ /* 选择按键用到的GPIO */ GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN; /* 配置为浮空输入 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure); /* 选择EXTI的信号源 */ GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE; /* EXTI为中断模式 */ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; /* 上升沿中断 */ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; /* 使能中断 */ EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); /*--------------------------KEY2配置-----------------------------*/ /* 选择按键用到的GPIO */ GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN; /* 配置为浮空输入 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure); /* 选择EXTI的信号源 */ GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE; /* EXTI为中断模式 */ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; /* 下降沿中断 */ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; /* 使能中断 */ EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }

    中断服务函数

    #include "stm32f10x_it.h" #include "bsp_test.h" /** ****************************************************************************** * @file stm32 用户自定义外部中断 * @author dele * @version V1.0 * @date 2020-10-03 * @brief 按键测试(中断模式/EXTI模式) * 实验平台:野火 F103-霸道 STM32 开发板 ****************************************************************************** */ void KEY1_IRQHandler(void) { //确保是否产生了EXTI Line中断 if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) { // LED1 取反 LED1_TOGGLE; BSP_KEY1_EXIT_LCDTEST(); USART_SendString(USART1,"KEY1 EXIT www.delehub.top"); USART_SendLine(USART1); //清除中断标志位 EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE); } } void KEY2_IRQHandler(void) { //确保是否产生了EXTI Line中断 if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) { // LED2 取反 LED2_TOGGLE BSP_KEY2_EXIT_LCDTEST(); USART_SendString(USART1,"KEY2 EXIT 2020-10-03 14:50"); USART_SendLine(USART1); //清除中断标志位 EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE); } }

    按键外部中断测试函数

    void BSP_KEY1_EXIT_LCDTEST(void) { LCD_SetFont(&Font8x16); LCD_SetColors(RED,WHITE); ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,显示全黑 */ ILI9341_DispStringLine_EN(LINE(0),"2020-10-03 14:30 BSP_EXIT_TEST"); ILI9341_DispStringLine_EN(LINE(1),"KEY1 EXIT TEST"); LCD_SetTextColor(RED); ILI9341_DrawCircle(100,200,20,1); } void BSP_KEY2_EXIT_LCDTEST(void) { LCD_SetFont(&Font8x16); LCD_SetColors(RED,WHITE); ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,显示全黑 */ ILI9341_DispStringLine_EN(LINE(3),"2020-10-03 14:30 DELEHUB"); ILI9341_DispStringLine_EN(LINE(4),"KEY2 EXIT TEST"); LCD_SetTextColor(GREEN); ILI9341_DrawCircle(100,200,40,0); }

    MAIN.C

    /**************************************************************** * @file main.c * 实验平台:野火 F103-霸道 STM32 开发板 ***************************************************************** 第三方库文件导入 START THE FILE ***************************************************************/ #include "stm32f10x.h" #include "bsp_led.h" #include "bsp_key.h" #include "bsp_beep.h" #include "bsp_exit.h" #include "timer.h" #include "bsp_ili9341_lcd.h" #include "bsp_SysTick.h" #include "bsp_usart.h" #include <stdio.h> #include "bsp_test.h" #include "STM32F103xxxx_USART.H" /****************************************************************************** END THE FILE * 第三方库文件导入*********************************************************/ void HardWare_Iint(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); EXTI_Key_Config(); LED_Iint(); Key_Iint(); Beep_Init(); //TIM4_Int_Init(9999,7199); ILI9341_Init(); USART_Configure(); } /** * @brief 主函数 * @param 无 * @retval 无 */ int main(void) { /* 硬件端口初始化 */ HardWare_Iint(); while(1) { } }

    串口打印效果

    TFT显示效果

    博客地址https://delehub.vercel.app/

    Processed: 0.013, SQL: 8