STM32-07-STM32_外部中断

文章目录

  • [STM32 中断系统](#STM32 中断系统)
    • [1. 中断](#1. 中断)
    • [2. NVIC](#2. NVIC)
    • [3. EXTI](#3. EXTI)
    • [4. AFIO](#4. AFIO)
    • [5. 中断配置步骤](#5. 中断配置步骤)
    • [6. 外部中断代码](#6. 外部中断代码)

STM32 中断系统

1. 中断

  • 目的 :中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。
  • 中断过程 :当CPU正在处理某事件的时候外界发生了紧急事件请求 (中断发生) ,要求CPU暂停当前的工作,转而去处理这个紧急事件 (中断响应和中断服务) ,处理完以后,再回到原来被中断的地方,继续原来的工作 (中断返回)
  • 中断系统:实现中断功能的部件称为中断系统,请求CPU中断的请求源称为中断源。微型机的中断系统一般允许有多个中断源,当几个中断源同时向CPU请求中断,要求它服务的时候,这就存在CPU优先响应哪个中断源请求的问题。因此设置中断优先级,CPU总是先响应优先级别最高的中断请求。
  • 作用与意义
    1. 实时控制
    2. 故障处理
    3. 数据传输

2. NVIC

  • 什么是NVIC?

    Nested vectored interrupt controller 即嵌套向量中断控制器,属于内核。

    支持256个中断,其中包含了16个系统中断和240个外部中断,并且具有256级的可编程中断设置。

    对于STM32F103ZET6的系统中断10个,外部中断60个,16中断优先级

    特性:

    • 68个可屏蔽中断通道
    • 16个可编程的优先等级
    • 低延时的异常和中断处理
    • 电源管理的控制
    • 系统控制寄存器的实现
  • NVIC相关寄存器介绍

    NVIC相关寄存器 位数 寄存器个数 备注
    中断使能寄存器(ISER) 32 8 每个位控制一个中断
    中断失能寄存器(ICER) 32 8 每个位控制一个中断
    应用程序中断及复位控制寄存器(AIRCR) 32 1 位[10:8]控制优先级分组
    中断优先级寄存器(IPR) 8 240 8个位对应一个中断,而STM32只使用高4位
  • 工作原理

    内核中断是不可屏蔽中断,直接由SHPR决定优先级,外部中断过来以后,会首先经过ISERICER寄存器进行使能或者失能,之后由IPR寄存器确定优先级,然后去抢占CPU执行中断。

  • 中断优先级

    • 抢占优先级:高抢占优先级可以打断正在执行的低抢占优先级中断
    • 响应优先级:当抢占优先级相同时,响应优先级高的先执行,但是不能互相打断
    • 自然优先级:中断向量表的优先级
    • 抢占和响应优先级相同时,自然优先级高的先执行,数值越小,表示优先级越高
  • 优先级分组

    优先级分组 AIRCR[10:8] IPRx bit[7:4]分配 分配结果
    0 111 None :[7:4] 0位抢占优先级,4位响应优先级
    1 110 [7] :[6:4] 1位抢占优先级,3位响应优先级
    2 101 [7:6] :[5:4] 2位抢占优先级,2位响应优先级
    3 100 [7:5] :[4] 3位抢占优先级,1位响应优先级
    4 011 [7:4] :None 4位抢占优先级,0位响应优先级
  • NVIC的使用

    1. 设置中断分组 SCB_AIRCR
    2. 设置中断优先级 NVIC_IPRx
    3. 使能中断 NVIC_ISER

3. EXTI

  • 什么是EXTI?

    External interrupt/event Controller 即外部中断/事件控制器,由20个产生事件/中断请求的边沿检测器组成,非互联型产品有19个边沿检测器。每个输入线可以独立地配置输入类型和对应的触发事件。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。

  • 特性:

    • 每个中断/事件都有独立地触发和屏蔽
    • 每个中断线都有专用的状态位
    • 支持多达20个软件的中断/事件请求
    • 检测脉冲宽度低于APB2时钟宽度的外部信号
  • 框图

    功能框图包含两条主线:一是由输入线到NVIC中断控制器,二是由输入线到脉冲发生器。这就是EXTI的两大功能,产生中断与产生事件,两者从硬件上就存在不同。

    输入线是线路的信息输入端,它可以通过配置寄存器设置为任何一个GPIO口,或者是一些外设的事件。输入线一般都存在电平变化的信号。

    ①:边缘检测上升沿触发选择寄存器 (EXTI_RTSR)和下降沿触发选择寄存器 (EXTI_FTSR)。边沿检测电路以输入线作为信号输入端,如果检测到边缘跳变,就输出有效信号1,有效信号1会传输到②电路。

    ②:软件触发,两个信号输入端分别为软件中断事件寄存器(EXTI_SWIER)和边沿检测电路的输入信号。或门电路只要输入有效信号1,就会把有效信号输入到③和④电路。通过对软件中断事件寄存器的读写操作就可以启动中断/事件线。

    ③:中断屏蔽/清除 ,两个信号输入端分别为中断屏蔽寄存器 (EXTI_IMR)和②电路,与门电路要求输入都为'1'才输出'1',这样子的情况下,如果中断屏蔽寄存器EXTI_IMR)设置为0时,不管从标号②电路输出的信号特性如何,最终标号③电路输出的信号都是0;假如中断屏蔽寄存器(EXTI_IMR)设置为1时,最终标号③电路输出的信号才由标号②电路输出信号决定,这样子就可以简单控制EXTI_IMR来实现中断的目的。标号④电路输出'1'就会把请求挂起寄存器(EXTI_PR)对应位置1。

    ④:事件屏蔽请求挂起寄存器 (EXTI_PR)的内容就输出到 NVIC 内,实现系统中断事件的控制。

4. AFIO

  • Alternate Function IO,即复用功能IO,主要用于重映射和外部中断映射配置

    寄存器AFIO_EXTICR1~4,配置EXTI中断线0~15具体对应哪个IO口

  • EXTI与IO对应关系

5. 中断配置步骤

  • EXTI配置步骤:

    1. 使能GPIO时钟

    2. 设置GPIO工作模式

    3. 使能AFIO

    4. 设置EXTI和IO对应关系

    5. 设置EXTI屏蔽,上下沿

    6. 设置NVIC

    7. 设计中断服务函数

  • HAL库配置步骤:

    1. 使能GPIO时钟

      c 复制代码
      __HAL_RCC_GPIOx_CLK_ENABLE();
    2. GPIO/AFIO/EXTI配置

      c 复制代码
      HAL_GPIO_Init();
    3. 设置中断分组

      c 复制代码
      HAL_NVIC_SetPriorityGrouping();
    4. 设置中断优先级

      c 复制代码
      HAL_NVIC_SetPriority();
    5. 使能中断

      c 复制代码
      HAL_NVIC_EnableIRQ();
    6. 设计中断服务函数

      c 复制代码
      EXTIx_IRQHandler();
    7. 编写中断处理回调函数

      c 复制代码
      HAL_GPIO_EXTI_Callback();
  • 中断回调处理机制

6. 外部中断代码

Exti.h

c 复制代码
#ifndef _EXTI_H
#define _EXTI_H


#include "./SYSTEM/sys/sys.h"

void exti_init(void);

#endif

EXTI.c

c 复制代码
#include "./BSP/EXTI/exti.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"


//外部中断初始化
void exti_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    //1.打开GPIO的时钟
    __HAL_RCC_GPIOE_CLK_ENABLE();
    
    //2.配置GPIO
    gpio_init_struct.Pin = GPIO_PIN_4;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);
    
    gpio_init_struct.Pin = GPIO_PIN_3;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);
    
    gpio_init_struct.Pin = GPIO_PIN_2;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);
    
    gpio_init_struct.Pin = GPIO_PIN_0;
    gpio_init_struct.Mode = GPIO_MODE_IT_RISING;
    gpio_init_struct.Pull = GPIO_PULLDOWN;
    HAL_GPIO_Init(GPIOA, &gpio_init_struct);
    
    //4.设置中断优先级
    HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0);
    HAL_NVIC_SetPriority(EXTI3_IRQn, 3, 0);
    HAL_NVIC_SetPriority(EXTI2_IRQn, 4, 0);
    HAL_NVIC_SetPriority(EXTI0_IRQn, 5, 0);
    
    //5.使能中断
    HAL_NVIC_EnableIRQ(EXTI4_IRQn);
    HAL_NVIC_EnableIRQ(EXTI3_IRQn);
    HAL_NVIC_EnableIRQ(EXTI2_IRQn);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}


void EXTI4_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
    __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_4);
}

void EXTI3_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
    __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_3);
}

void EXTI2_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
    __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_2);
}

void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
    __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{ 
    delay_ms(20);
    
    switch(GPIO_Pin)
    {
        case GPIO_PIN_0: 
            if(KEY_UP == 1)
                LED0(0); 
            break;
        case GPIO_PIN_2:
            if(KEY2 == 0)            
                LED0(1); 
            break;
        case GPIO_PIN_3: 
            if(KEY1 == 0)
                LED1(0); 
            break;
        case GPIO_PIN_4: 
            if(KEY0 == 0)
                LED1(1); 
            break;
        default : 
            break;
    }
}

main.c

c 复制代码
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/BEEP/beep.h"
#include "./BSP/EXTI/exti.h"


int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    led_init();                         /* LED初始化 */
    key_init();     //按键初始化
    beep_init();    //蜂鸣器初始化
    exti_init();    //外部中断初始化
    
    while(1)
    {     

    }
}

声明 :资料来源(战舰STM32F103ZET6开发板资源包)

  1. Cortex-M3权威指南(中文).pdf
  2. STM32F10xxx参考手册_V10(中文版).pdf
  3. STM32F103 战舰开发指南V1.3.pdf
  4. STM32F103ZET6(中文版).pdf
  5. 战舰V4 硬件参考手册_V1.0.pdf
相关推荐
cjy_Somnr2 小时前
keil5报错显示stm32的SWDIO未连接不能烧录
stm32·单片机·嵌入式硬件
Lay_鑫辰3 小时前
西门子诊断-状态和错误位(“轴”工艺对象 V1...3)
服务器·网络·单片机·嵌入式硬件·自动化
无垠的广袤5 小时前
【工业树莓派 CM0 NANO 单板计算机】本地部署 EMQX
linux·python·嵌入式硬件·物联网·树莓派·emqx·工业物联网
雲烟7 小时前
嵌入式设备EMC安规检测参考
网络·单片机·嵌入式硬件
泽虞7 小时前
《STM32单片机开发》p7
笔记·stm32·单片机·嵌入式硬件
田甲7 小时前
【STM32】 数码管驱动
stm32·单片机·嵌入式硬件
up向上up8 小时前
基于51单片机垃圾箱自动分类加料机快递物流分拣器系统设计
单片机·嵌入式硬件·51单片机
纳祥科技17 小时前
Switch快充方案,内置GaN,集成了多个独立芯片
单片机
单片机日志18 小时前
【单片机毕业设计】【mcugc-mcu826】基于单片机的智能风扇系统设计
stm32·单片机·嵌入式硬件·毕业设计·智能家居·课程设计·电子信息
松涛和鸣19 小时前
从零开始理解 C 语言函数指针与回调机制
linux·c语言·开发语言·嵌入式硬件·排序算法