前言

上一节我们学习了单片机独立按键操作,实际上我们采用的是查询的方法,MCU实时检测有无按键按下比较占用MCU资源,本节我们将使用中断的方法实现按键操作。

一、基础知识

1. STM32物联网套件简介

STM32物联网套件目前有两个版本:基础版和高级版,后续会增加应用版本和语音版,核心板均采用STM32F103C8T6核心板,基础版主要元器件如下所示:
在这里插入图片描述
高级版版主要元器件如下所示:
在这里插入图片描述
STM32物联网套件致力于带领大家入门物联网,不仅学习STM32,也了解转微信小程序开发、物联网服务器后台开发,真正做到了解一个物联网项目的方方面面,基于此,我们定制了一套通用的WIFI通讯协议(可以理解为类似AT指令,不过集成度更高,几条指令就可以直连接云平台),如三条指令连接腾讯云实例

后续我们会继续增加涂鸦智能、电信云、移动Onenet、阿里云等主流云平台的支持,力争做到,一套STM32代码,通过定制的WIFI模块可以连接到不同的云平台,也欢迎有产品开发需求的朋友私聊我们咨询、定制物联网方案!

本套物联网套件可以支持大学生参加物联网相关比赛、申请学校大创项目、完成毕业设计等,我们的定位是做一家开源智能硬件服务商,和大家一起探索物联网,我们的使命是推动更多物联网产品的落地和普及,让技术不再是阻碍!

2.中断简介

中断是指CPU在执行A事件的时候,突然收到B事件发出的(中断)请求,CPU停止手中的事情,转而去执行B事件,B事件执行完毕后,又回到原来A事件被打断的地方,继续执行程序的过程,示意图如下所示:
在这里插入图片描述

STM32单片机使用NVIC(嵌套向量中断控制器)来管理中断,主要有三部分:中断使能、抢占优先级设置、响应优先级设置,注意:优先级数值越小,优先级别越高;

其中中断使能控制中断是否打开,抢占优先级用来判断中断是否可以相互打断,高抢占优先级可以打断低抢占优先级(低抢占优先级任务正在执行时候来了高抢占优先级中断,系统会暂停执行当前任务,转去执行高抢占优先级任务,执行完毕后继续返回执行低抢占优先级任务)。

当两个中断抢占优先级相同时候,系统会根据相应优先级的高低选择执行任务,

3.中断优先级分组

问题来了,已经说到STM32单片机可以使用NVIC管理诸多中断,那么STM32一共有多少个中断呢? 我们打开startup_stm32f103xb.s启动文件中中断向量表分配,如下:

__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
                DCD     MemManage_Handler          ; MPU Fault Handler
                DCD     BusFault_Handler           ; Bus Fault Handler
                DCD     UsageFault_Handler         ; Usage Fault Handler
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     SVC_Handler                ; SVCall Handler
                DCD     DebugMon_Handler           ; Debug Monitor Handler
                DCD     0                          ; Reserved
                DCD     PendSV_Handler             ; PendSV Handler
                DCD     SysTick_Handler            ; SysTick Handler

                ; External Interrupts
                DCD     WWDG_IRQHandler            ; Window Watchdog
                DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
                DCD     TAMPER_IRQHandler          ; Tamper
                DCD     RTC_IRQHandler             ; RTC
                DCD     FLASH_IRQHandler           ; Flash
                DCD     RCC_IRQHandler             ; RCC
                DCD     EXTI0_IRQHandler           ; EXTI Line 0
                DCD     EXTI1_IRQHandler           ; EXTI Line 1
                DCD     EXTI2_IRQHandler           ; EXTI Line 2
                DCD     EXTI3_IRQHandler           ; EXTI Line 3
                DCD     EXTI4_IRQHandler           ; EXTI Line 4
                DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
                DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
                DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
                DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
                DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
                DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
                DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
                DCD     ADC1_2_IRQHandler          ; ADC1_2
                DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
                DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
                DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
                DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
                DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
                DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
                DCD     TIM1_UP_IRQHandler         ; TIM1 Update
                DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
                DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare
                DCD     TIM2_IRQHandler            ; TIM2
                DCD     TIM3_IRQHandler            ; TIM3
                DCD     TIM4_IRQHandler            ; TIM4
                DCD     I2C1_EV_IRQHandler         ; I2C1 Event
                DCD     I2C1_ER_IRQHandler         ; I2C1 Error
                DCD     I2C2_EV_IRQHandler         ; I2C2 Event
                DCD     I2C2_ER_IRQHandler         ; I2C2 Error
                DCD     SPI1_IRQHandler            ; SPI1
                DCD     SPI2_IRQHandler            ; SPI2
                DCD     USART1_IRQHandler          ; USART1
                DCD     USART2_IRQHandler          ; USART2
                DCD     USART3_IRQHandler          ; USART3
                DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
                DCD     RTC_Alarm_IRQHandler        ; RTC Alarm through EXTI Line
                DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
__Vectors_End

其中从Reset_Handler开始,一直到SysTick_Handler,总计10个, 为不可屏蔽中断,属于内核中断,其余中断为外部中断,而NVIC就是管理外部中断的,接下来我们看下中断优先级分组
在这里插入图片描述
举个例子:

设置分组1,中断3(RTC)的抢占优先级为1,响应优先级为0,中断7(外部中断1)的抢占优先级为1,响应优先级为2,中断8(外部中断2)的抢占优先级为0,响应优先级为2,则三个中断优先级为:中断8 > 中断3 > 中断7。

4.按键检测原理

简单的独立按键连接电路原理图如下所示
在这里插入图片描述

独立按键电路中,按键一边接GND,另一边接到单片机IO口上,当按键按下时候,按键两边1和2导通,单片机P2.5引脚直接连接GND,电平为低电平,所以只需要让单片机不断的检测P2.5引脚的I/O口是否为低电平,一旦程序检测到I/O口引脚变为低电平说明按键按下了。

4. 硬件设计

本次按键实验按键部分原理图如下,按键一端引脚均接地,另一端接到单片机PB4,当按键按下时候PB4为低电平。
在这里插入图片描述
实物图如下所示:
在这里插入图片描述
其中,PB12引脚输出低电平可以点亮LED灯,当按键按下时候,单片机检测到下降沿中断,PB4引脚为低电平,点亮LED灯。

二、实例

1. 新建工程

使用STM32CubeMX创建一个新的工程,参考环境搭建章节配置方式,设置RCC和PB12引脚输出,PB4为GPIO_EXIT4
在这里插入图片描述
设置中断触发方式为下降沿
在这里插入图片描述
使能NVIC配置中断优先级分组4,并使能EXIT line4中断,GPIO设置抢占优先级为2
在这里插入图片描述
进入Clock configuration页面,选择HSE时钟源,倍频后主时钟为72MHz
在这里插入图片描述
切换到Project Manager栏目,设置工程名字、工程保存目录、工具链等信息,具参数如下图所示
在这里插入图片描述
点击左边栏目Code Generator,然后勾选Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral,勾选此选项,外设将单独保存在一个文件中,而不是全部都在main.c中。
在这里插入图片描述

2.函数说明

(1) 首先查看下gpio.c中MX_GPIO_Init()函数

void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);

  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pin : PB12 */
  GPIO_InitStruct.Pin = GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PB4 */
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(EXTI4_IRQn);

}

在GPIO初始化函数中,首先使能GPIOB时钟,然后初始化PB12 PB13为输出模式,PB4为输入模式,中断操作NVIC配置中断优先级,并使能EXTI4_IRQn中断;EXTI是外部中断/事件控制器,一共管理20个中断/事件线,每个中断/事件线都对应一个边沿检测器,可单独配置为中断或者事件,中断/事件线具体对应关系如下:
在这里插入图片描述
(2) 中断处理函数
当中断来临时候,会进入上文中断向量表对应的void EXTI4_IRQHandler(void)函数,函数在stm32f1xx_it.c中

/**
  * @brief This function handles EXTI line4 interrupt.
  */
void EXTI4_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI4_IRQn 0 */
  /* USER CODE END EXTI4_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
  /* USER CODE BEGIN EXTI4_IRQn 1 */
  /* USER CODE END EXTI4_IRQn 1 */
}

打开stm32f1xx_hal_gpio.c,HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)定义如下:

/**
  * @brief  This function handles EXTI interrupt request.
  * @param  GPIO_Pin: Specifies the pins connected EXTI line
  * @retval None
  */
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

/**
  * @brief  EXTI line detection callbacks.
  * @param  GPIO_Pin: Specifies the pins connected EXTI line
  * @retval None
  */
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */
}

当确认外部中断线4发生中断时候,系统会调用HAL_GPIO_EXIT_Callback(uint16_t GPIO_Pin)函数,该函数为一个__weak函数,用户可以在应用层重写该函数,如果用户忘记定义了,系统也不会报错,会进入这个__weak函数,但是什么也不执行

3. 修改程序

在gpio.c中重定义 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)函数

volatile int key_flag= 0;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  // 按键按下
  key_flag = 1;
}

在main.c中根据中断处理函数标志位,做进一步处理,当按键按下时候按键标志清零,翻转LED灯

/* USER CODE BEGIN 0 */
extern volatile int key_flag;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
    if ( key_flag )
    {
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_12);
        
        key_flag = 0;
    }
    HAL_Delay(10); 
  }
  /* USER CODE END 3 */
}

三、下载运行

按照环境搭建章节方式给核心板下载程序,可以看到每次按下按键,红色LED灯点亮或者熄灭。
在这里插入图片描述

四、小结

如您在使用过程中有任何问题,请加QQ群进一步交流。

QQ交流群:906015840 (备注:物联网项目交流)

源码获取:关注公众号,回复xiaoyi_stm32kits获取资料

硬件获取:某宝搜索小驿物联

小驿物联出品:宁愿做过了后悔,也不要后悔没去做!
在这里插入图片描述

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐