STM32基础知识:中断系统

描述

中断系统

1 数据传输方式

  • 无条件传输 :处理器不必了解外部设备状态,直接进行数据传输,用于指示灯和按键等简单设备.。
  • 查询方式 :传输前,一方先查询另一方的状态,若已经准备好就传输,否则就继续查询。
  • 中断方式 :一方通过申请中断的方式与另一方进行数据传输,收发双方可以并行工作。
  • 直接存储器访问 :处理器内部建立片内外设和内存之间的数据传输通道,传输过程不需要处理器参与。

2 中断系统的基本概念

2.1 中断全过程

  • 中断发生: 当CPU在处理某一事件A时,发生了另一事件B,请求CPU迅速去处理。
  • 中断处理: CPU暂停当前的工作,转去处理事件B。
  • 中断返回: 当CPU将事件B处理完毕后,再回到事件A中被暂停的地方继续处理事件A。

STM32

2.2 中断的作用

  • 速度匹配: 可以解决快速的CPU与慢速的外部设备之间传送数据的矛盾。
  • 分时操作: CPU可以分时为多个外部设备服务,提高计算机的利用率。
  • 实时响应: CPU能够及时处理应用系统的随机事件,增强系统的实时性。
  • 可靠性高: CPU可以处理设备故障及掉电等突发事件,提高系统可靠性。

2.3 中断优先级

处理器根据不同中断的重要程序设置不同的优先等级。

不同优先级中断的处理原则是: 高级中断可以打断低级中断;低级中断不能打断高级中断

STM32

2.4 中断向量

  • 中断服务程序: 在响应一个特定中断的时候,处理器会执行一个函数,该函数一般称为中断处理程序或者中断服务程序。
  • 中断向量: 中断服务程序在内存中的入口地址称为中断向量。
  • 中断向量表: 把系统中所有的中断向量集中起来放到存储器的某一区。
  • 查找中断向量:
    • 编号:计算机系统对每一个中断源进行编号,这个号码称为中断类型号。
    • 查表:根据中断类型号,到中断向量表中找到对应的表项。
    • 执行:取出表项内容,即该中断源对应的中断服务程序地址,进入该程序执行相应操作。

2.5 中断响应过程

  1. 中断源发出中断请求。
  2. 判断处理器是否允许中断,以及该中断源是否被屏蔽。
  3. 中断优先级排队。
  4. 处理器暂停当前程序,保护断点地址和处理器的当前状态,根据中断类型号,查找中断向量表,转到对应的中断服务程序。
  5. 执行中断服务程序。
  6. 恢复被保护的状态,执行中断返回指令,回到被中断的程序。

3 STM32微控制器中断系统

3.1 基本概念

  • 中断: 中断是由内核外部产生的,一般由硬件引起,比如外设中断和外部中断等。
  • 异常: 异常通常是内核自身产生的,大多是软件引起的,比如除法出错异常、预取值失败等。

3.2 NVIC嵌套向量中断控制器

NVIC属于Cortex-M内核的组件,管理所有的中断和异常,为中断源分配中断通道

STM32

STM32

中断向量表

__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

3.3 中断通道

微控制器片内集成了很多外设,对于单个外设而言,它通常具备若干个可以引起中断的中断源,而该外设的所有中断源只能通过指定的中断通道向内核申请中断。

以STM32F103芯片为例,它支持43个可屏蔽中断通道(不包括16个Cortex-M3的中断线),已经固定分配给相应的片内外设。由于中断源数量较多,而中断通道有限,会出现多个中断源共享同一个中断通道的情况。

3.4 中断优先级

  • NVIC中有一个8位中断优先级寄存器NVIC_IPR,理论上可以配置0~255共256级中断。
  • STM32只使用了其中的高4位,并分成抢占优先级子优先级两组。

中断嵌套:

多个中断同时提出中断申请时

  • 先比较抢占优先级,抢占优先级高的中断先执行。
  • 如果抢占优先级相同,则比较子优先级。
  • 二者都相同时,比较中断编号。编号越小,优先级越高。中断编号位于芯片头文件中。

STM32中断优先级分组

STM32

HAL库初始化函数HAL_Init将优先级分组设置为第4组,即有0~15,共16级抢占优先级,没有子优先级。编号越小的优先级越高:0号为最高,15号为最低。

3.5 EXIT外部中断控制器

STM32

GPIO引脚的外部中断

触发方式:

  • 上升沿触发
  • 下降沿触发
  • 双边沿触发

引脚分组:

  • 尾号相同的引脚一组,接入1个外部中断线。
  • 同组引脚只能有一个设置为外部中断功能。

中断通道:

  • EXTI0~EXIT4分别具有独立的中断通道
  • EXTI5~EXIT9共享同一个中断通道
  • EXTI5~EXIT9共享同一个中断通道

STM32

4 HAL库中断处理流程

4.1 编程步骤

在STM32CubeMX中完成

  1. 设置中断触发条件
  2. 设置中断优先等级
  3. 设能外设中断

HAL库的接口函数完成

  1. 清除中断标志
  2. 编写中断服务程序

4.2 HAL库对中断的封装处理

  • 统一规定处理各个外设的中断服务程序HAL_PPP_IRQHandler
  • 在中断服务程序HAL_PPP_IRQHandler完成了中断标志的判断和清除。
  • 将中断中需要执行的操作以回调函数的形式提供给用户。

启动文件startup_stm32fxxx.s

  • 该文件存放在MDK-ARM组中。在该文件中,预先为每个中断编写了一个中断服务程序,只是这些中断服务程序都是死循环,目的只是 初始化中断向量表
  • 中断服务程序的属性定义为“weak”。weak属性的函数表示:如果该函数没有在其他文件中定义,则使用该函数;如果用户在其他地方定义了该函数,则使用用户定义的函数。

中断服务程序文件:stm32fxxx_it.c

  • 该文件存放在User组中,用于 存放各个中断的中断服务程序

  • 在使用CubeMX软件进行初始化配置时,如果使能了某一个外设的中断功能,那么在生成代码时,相对应的外设中断服务程序HAL_PPP_IRQHandler就会自动添加到该文件中,用户只需要在该函数中添加相应的中断处理代码即可。
    外部中断所对应的中断服务程序

    外部中断线中断服务程序的函数名称
    外部中断线0(EXTI Line 0)EXTI0_IRQHandler
    外部中断线1(EXTI Line 1)EXTI1_IRQHandler
    外部中断线2(EXTI Line 2)EXTI2_IRQHandler
    外部中断线3(EXTI Line 3)EXTI3_IRQHandler
    外部中断线4(EXTI Line 4)EXTI4_IRQHandler
    外部中断线5~9(EXTI Line[9:5])EXTI9_5_IRQHandler
    外部中断线10~15(EXTI Line[15:10])EXTI15_10_IRQHandler

    例如

    /**
      * @brief This function handles EXTI line0 interrupt.
      */
    void EXTI0_IRQHandler(void)
    {
      /* USER CODE BEGIN EXTI0_IRQn 0 */
    
      /* USER CODE END EXTI0_IRQn 0 */
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
      /* USER CODE BEGIN EXTI0_IRQn 1 */
    
      /* USER CODE END EXTI0_IRQn 1 */
    }
    

4.3 外部中断处理流程

假设微控制器芯片为STM32F103,设置引脚PA0为外部中断功能。当引脚PA0出现脉冲边沿时,将触发外部中断。

由于外部中断主要是利用GPIO引脚实现,因此外部中断数据类型的定义放在stm32f1xx_hal_gpio.h文件中,外部中断接口函数的实现放在stm32f1xx_hal_gpio.c文件中。

  1. 引脚初始化
    STM32
    成员变量Mode的取值范围

    • GPIO_MODE_IT_RISING 上升沿触发
    • GPIO_MODE_IT_FALLING 下降沿触发
    • GPIO_MODE_IT_RISING_FALLING 双边沿触发
  2. 外部中断通用处理函数HAL_GPIO_EXTI_IRQHandler

    /**
      * @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);
      }
    }
    
    函数原型void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
    功能描述作为所有外部中断发生后的通用处理函数
    入口参数GPIO_Pin:连接到对应外部中断线的引脚,范围是 GPIO_PIN_0~GPIO_PIN_15
    返回值
    注意事项1. 所有外部中断服务程序均调用该函数完成中断处理2. 函数内部根据GPIO_Pin的取值判断中断源,并清除对应外部中断线的中断标志3. 函数内部调用外部中断回调函数HAL_GPIO_EXTI_Callback完成实际的处理任务4. 该函数由CubeMX自动生成
  3. 外部中断回调函数HAL_GPIO_EXTI_Callback

    /**
      * @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
       */
    }
    
    函数原型void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    功能描述外部中断回调函数,用于处理具体的中断任务
    入口参数GPIO_Pin:连接到对应外部中断线的引脚,范围是 GPIO_PIN_0~GPIO_PIN_15
    返回值
    注意事项1. 该函数由外部中断通用处理函数HAL_GPIO_EXTI_IRQHandler调用,完成所有外部中断的任务处理2. 函数内部先根据GPIO_Pin的取值来判断中断源,然后执行对应的中断任务3. 该函数由用户根据实际需求编写

任务实践

基于STM32F103C8T6,开发板原理图

STM32

利用按键KEY1改变指示灯LED1的闪烁频率,闪烁频率设置为3档:

  • 初始状态时,LED1按照1Hz的频率闪烁;
  • 第一次按键后,LED1按照5Hz的频率闪烁;
  • 第二次按键后,LED1按照20Hz的频率闪烁,并重复上述过程。

注:本任务例程使用的开发板,LED1与STM32的PA1相连接,KEY1与PA0相连接。KEY1原理图如下:

STM32

使用按键时,需要设置PA0为输入上拉模式,这样在KEY1没有按下时,PA0可以读取到高电平,KEY1按下时PA0可以读取到低电平。

  1. 配置PA0为GPIO_EXIT0,PA1为GPIO_Output
    STM32
  2. PA1保持默认GPIO输出模式即可
    STM32
  3. PA0配置为下降沿触发,上拉模式
    STM32
  4. 使能外部中断线
    STM32
  5. 配置中断优先级分组为第四组16级抢占优先级,没有子优先级
    STM32

以上步骤生成如下代码:

  • stm32f1xx_hal_gpio.c中生成GPIO引脚配置代码,并在main.c中调用

    void MX_GPIO_Init(void)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct = {0};
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_GPIOB_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    
      /*Configure GPIO pin : PA0 */
      GPIO_InitStruct.Pin = GPIO_PIN_0;
      GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /*Configure GPIO pin : PA1 */
      GPIO_InitStruct.Pin = GPIO_PIN_1;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
      /* EXTI interrupt init*/
      HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
      HAL_NVIC_EnableIRQ(EXTI0_IRQn);
    
    }
    
    • 开启外设时钟RCC
    • 配置PA0,PA1两个引脚结构体
    • 设置EXTI0中断优先级为0,并使能这个中断
  • stm32fxxx_it.c中生成外设中断服务程序

    /**
      * @brief This function handles EXTI line0 interrupt.
      */
    void EXTI0_IRQHandler(void)
    {
      /* USER CODE BEGIN EXTI0_IRQn 0 */
    
      /* USER CODE END EXTI0_IRQn 0 */
      HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
      /* USER CODE BEGIN EXTI0_IRQn 1 */
    
      /* USER CODE END EXTI0_IRQn 1 */
    }
    
  1. 编写程序
    main.c中定义指示灯闪烁频率,0代表1Hz,1代表5Hz,2代表20Hz

    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    volatile uint8_t Speed = 0;
    /* USER CODE END PV */
    

    main.c中编写应用代码

    /* USER CODE BEGIN 3 */
        if (Speed == 0)
        {
          HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
          HAL_Delay(1000);
        }
        else if (Speed == 1)
        {
          HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
          HAL_Delay(200);
        }
        else
        {
          HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
          HAL_Delay(50);
        }
      }
      /* USER CODE END 3 */
    

    main.c中外部中断回调函数HAL_GPIO_EXTI_Callback

    /* USER CODE BEGIN 4 */
     void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
     {
       if(GPIO_Pin == GPIO_PIN_0)
       {
         Speed++;
         if (Speed == 3)
         {
           Speed = 0;
         }
       }
     }
     /* USER CODE END 4 */
    
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分