STM32中断概述

异常类型

1.中断简介
程序从下到上执行,当发生中断时,程序转而执行中断程序,执行完毕后,继续执行主函数。中断中可以接中断嵌套。中断同时发生时,优先执行优先级高的。中断优先级越小,优先级越高。

2.中断类型
系统异常:体现在内核水平
外部中断:体现在外设水平

3.NVIC(嵌套向量中断控制器)
属于内核外设,管理着包括内核和片上所有外设的中断相关的功能。
主要在两个库文件上:core_cm3.h和misc.h
CM3内核一共支持256个中断。

4.NVIC寄存器简介
中断使能寄存器-------------ISER
8个32位寄存器来控制,每个位控制一个中断。对于STM32F103的可屏蔽中断最多只有60个。所以只需要ISER[0]和ISER[1]就可以全部表示。ISER[0]的bit0~31分别对应中断0 ~ 31,ISER[1]的0 ~ 27对应32 ~ 59.
中断清除寄存器-------------ICER
用来清除中断使能的,写1有效。其余和ISER等效。
中断使能悬起寄存器 ----- ISPR
可以将正在执行的中断挂起,而去执行同级或者更高级别的中断
中断清除悬起寄存器 - ----ICPR
与ISPR相反,解除中断挂起的状态
中断有效位寄存器 ---------IABR
一个只读寄存器,用来判断目前是哪个中断正在被执行
中断优先级寄存器----------IP
IP寄存器是由240个八位寄存器组成,每个可屏蔽中断占八位,这样就可以表示240可屏蔽中断,IP[59]~IP[0]分别对应中断59 ~0.每个可屏蔽中断占用的8bit并没有全部使用,而是只用了高四位。这四位有分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。这两个优先级的占位由SCB->AIRCR中的中断分组设置来决定。子优先级又叫响应优先级。
正在执行的优先级由抢占优先级-相应优先级-自然优先级的方式来决定正在执行中断。

优先级分组AIRCR[10:8]bit[7: 4]分配情况分配结果
01110:40 位抢占优先级, 4 位响应优先级
11101:31 位抢占优先级, 3 位响应优先级
21012:22 位抢占优先级, 2 位响应优先级
31003:13 位抢占优先级, 1 位响应优先级
40114:04 位抢占优先级, 4 位响应优先级

中断优先级设定NVIC->IPRx

寄存器高四位用来表达优先级,低四位未使用,读回为0。

优先级分组:SCB->AIRCR:PRIGROUP[10:8]

在这里插入图片描述
判断优先级:分组>主优先级>子优先级.如果都相同,则看硬件中断编号(中断向量表)。

中断编程顺序

1——使能中断请求

使能中断请求一共需要使能两个。外设和NVIC中断使能寄存器。

2——配置中断优先级分组

配置SCB->AIRCR的8到10位确定优先级分组
固件库函数为

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);//设置中断优先级的分组
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority,uint32_t SubPriority);//设置中断优先级

一共有0到4五个组。

3——配置NVIC寄存器,初始化NVIC_InitTypeDef;

(1)指定中断源

uint8_t NVIC_IRQChannel; //中断源为中断向量表中的中断

(2)设置抢占优先级,分组不同,抢占优先级的位数不同。

 uint8_t NVIC_IRQChannelPreemptionPriority;

(3)设置子优先级

  uint8_t NVIC_IRQChannelSubPriority; 

(4)使能或者失能

  FunctionalState NVIC_IRQChannelCmd;  

4——编写中断服务函数

(1)中断服务函数名
中断服务函数在启动文件里面有弱定义(stm32f10x.h中的62行),当我们写相应的中断服务函数时,要保持与启动文件的中断服务函数名一致,若命名错误,则程序会执行启动文件中的中断服务函数。
(2)中断服务函数位置
为了编程方便管理,一般把中断服务函数放在stm32f10x_it.c中。

GPIO中断示例

EXTI(外部中断/事件控制器)简介

EXTI(External interrupt/event controller)—外部中断/事件控制器,管理了控制器的 20 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
在这里插入图片描述

EXTI控制器简介

EXTI 控制器有 20 个中断/事件输入线,编号为EXTI0到EXTI19,EXTI0到EXTI15的每条线控制GPIO的组数(即GPIOA到GPIOI),线的编号(0—15)对应着GPIO的16个端口。所以可以输入任意GPIO口。16线为PVD输出,17线为RTC闹钟事件,18线为USB唤醒事件,19线为互联网唤醒事件(只适用于互联型,即105或107)

AFIO_EXTICR——外部中断配置寄存器

AFIO_EXTICR外部中断配置寄存器共四组,高16位保留,低十六位有效。每4bit决定一个GPIO和中断线的映射关系。
在这里插入图片描述

EXYI_RTSP——上升沿触发选择寄存器

0—19位有效,x位为1时,允许输入线x上的上升沿触发(中断和事件),为0时禁止上升沿触发。

EXIT_SWIER 软件中断事件寄存器

0—19位有效,x位为1时,允许输入线x上的上升沿触发(中断和事件),为0时禁止上升沿触发。

EXIT_PR——挂起寄存器

0—19位有效,为1表示接受到了中断请求。挂起是指接收到了中断请求,但是响不响应需要下一步判断

EXIT_IMR——中断屏蔽寄存器

0—19位有效,为1表示开放来自线x上的中断请求,

EXIT_EMR——事件屏蔽寄存器

初始化结构体函数EXTI_InitTypeDef;

uint32_t EXTI_Line;//选择中断/事件线,控制的是EXIT_IMR——中断屏蔽寄存器,置一为开放相应线的中断请求
EXTIMode_TypeDef EXTI_Mode;//选择是中断还是事件两种模式
EXTITrigger_TypeDef EXTI_Trigger;//选择触发方式(上升沿、下降沿、上升沿和下降沿)
FunctionalState EXTI_LineCmd; //对应EXIT_IMR——中断屏蔽寄存器或者EXIT_EMR——事件屏蔽寄存器,

EXTI外部中断的配置步骤

1.使能对应的GPIO时钟
2.设置GPIO的工作模式,触发条件,开启AFIO时钟,设置IO口与中断线的映射关系。
3.配置好中断优先级(NVIC),并使能中断
4.编写中断服务函数
5.编写中断处理回调函数HAL_GPIO_EXTI_Callback

在main函数中

int main(void)
{
    HAL_Init();                            /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);    /* 设置时钟, 72Mhz */
    delay_init(72);                        /* 延时初始化 */
    usart_init(115200);                    /* 串口初始化为115200 */
    led_init();                            /* 初始化LED */
    beep_init();                           /* 初始化蜂鸣器 */
    extix_init();                          /* 初始化外部中断输入 */
    LED0(0);                               /* 先点亮红灯 */

    while (1)
    {
        printf("OK\r\n");
        delay_ms(1000);
    }
}

exti.c

/**
 ****************************************************************************************************
 * @file        exti.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2020-04-19
 * @brief       外部中断 驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 STM32F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 * 修改说明
 * V1.0 20200420
 * 第一次发布
 *
 ****************************************************************************************************
 */

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/BEEP/beep.h"
#include "./BSP/KEY/key.h"
#include "./BSP/EXTI/exti.h"


/**
 * @brief       KEY0 外部中断服务程序
 * @param       无
 * @retval      无
 */
void KEY0_INT_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY0_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

/**
 * @brief       KEY1 外部中断服务程序
 * @param       无
 * @retval      无
 */
void KEY1_INT_IRQHandler(void)
{ 
    HAL_GPIO_EXTI_IRQHandler(KEY1_INT_GPIO_PIN);         /* 调用中断处理公用函数 清除KEY1所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY1_INT_GPIO_PIN);         /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}


/**
 * @brief       WK_UP 外部中断服务程序
 * @param       无
 * @retval      无
 */
void WKUP_INT_IRQHandler(void)
{ 
    HAL_GPIO_EXTI_IRQHandler(WKUP_INT_GPIO_PIN);        /* 调用中断处理公用函数 清除KEY_UP所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    __HAL_GPIO_EXTI_CLEAR_IT(WKUP_INT_GPIO_PIN);        /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

/**
 * @brief       中断服务程序中需要做的事情
                在HAL库中所有的外部中断服务函数都会调用此函数
 * @param       GPIO_Pin:中断引脚号
 * @retval      无
 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(20);      /* 消抖 */
    switch(GPIO_Pin)
    {
        case KEY0_INT_GPIO_PIN:
            if (KEY0 == 0)
            {
                LED0_TOGGLE();  /* LED0 状态取反 */ 
                LED1_TOGGLE();  /* LED1 状态取反 */ 
            }
            break;
        case KEY1_INT_GPIO_PIN:
            if (KEY1 == 0)
            {
                LED0_TOGGLE();  /* LED0 状态取反 */ 
            }
            break;
        case WKUP_INT_GPIO_PIN:
            if (WK_UP == 1)
            {
                BEEP_TOGGLE();  /* 蜂鸣器状态取反 */ 
            }
            break;
    }
}

/**
 * @brief       外部中断初始化程序
 * @param       无
 * @retval      无
 */
void extix_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;

    KEY0_GPIO_CLK_ENABLE();                                  /* KEY0时钟使能 */
    KEY1_GPIO_CLK_ENABLE();                                  /* KEY1时钟使能 */
    WKUP_GPIO_CLK_ENABLE();                                  /* WKUP时钟使能 */

    gpio_init_struct.Pin = KEY0_INT_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下升沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY0_INT_GPIO_PORT, &gpio_init_struct);    /* KEY0配置为下降沿触发中断 */

    gpio_init_struct.Pin = KEY1_INT_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;            /* 下升沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY1_INT_GPIO_PORT, &gpio_init_struct);    /* KEY1配置为下降沿触发中断 */
    
    gpio_init_struct.Pin = WKUP_INT_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_IT_RISING;             /* 上升沿触发 */
    gpio_init_struct.Pull = GPIO_PULLDOWN;
    HAL_GPIO_Init(WKUP_GPIO_PORT, &gpio_init_struct);        /* WKUP配置为下降沿触发中断 */

    HAL_NVIC_SetPriority(KEY0_INT_IRQn, 0, 2);               /* 抢占0,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY0_INT_IRQn);                       /* 使能中断线4 */

    HAL_NVIC_SetPriority(KEY1_INT_IRQn, 1, 2);               /* 抢占1,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY1_INT_IRQn);                       /* 使能中断线3 */

    HAL_NVIC_SetPriority(WKUP_INT_IRQn, 2, 2);               /* 抢占2,子优先级2 */
    HAL_NVIC_EnableIRQ(WKUP_INT_IRQn);                       /* 使能中断线0 */
}

exti.h

/**
 ****************************************************************************************************
 * @file        exti.h
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2020-04-20
 * @brief       外部中断 驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 STM32F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 * 修改说明
 * V1.0 20200419
 * 第一次发布
 *
 ****************************************************************************************************
 */

#ifndef __EXTI_H
#define __EXTI_H

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

/******************************************************************************************/
/* 引脚 和 中断编号 & 中断服务函数 定义 */ 

#define KEY0_INT_GPIO_PORT              GPIOE
#define KEY0_INT_GPIO_PIN               GPIO_PIN_4
#define KEY0_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
#define KEY0_INT_IRQn                   EXTI4_IRQn
#define KEY0_INT_IRQHandler             EXTI4_IRQHandler

#define KEY1_INT_GPIO_PORT              GPIOE
#define KEY1_INT_GPIO_PIN               GPIO_PIN_3
#define KEY1_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
#define KEY1_INT_IRQn                   EXTI3_IRQn
#define KEY1_INT_IRQHandler             EXTI3_IRQHandler

#define WKUP_INT_GPIO_PORT              GPIOA
#define WKUP_INT_GPIO_PIN               GPIO_PIN_0
#define WKUP_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PA口时钟使能 */
#define WKUP_INT_IRQn                   EXTI0_IRQn
#define WKUP_INT_IRQHandler             EXTI0_IRQHandler

/******************************************************************************************/


void extix_init(void);  /* 外部中断初始化 */

#endif

EXTI外部中断函数的执行过程

当中断发生时执行对应的EXTIX_IRQHandler函数,该函数为弱函数,可重写。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32F103 微控制器中,中断处理过程主要涉及以下几个步骤: 1. 中断触发:当一个特定的事件(如外部引脚状态变化、定时器溢出等)发生时,会触发相应的中断请求。 2. 中断向量表:中断触发后,处理器会根据中断向量表(Interrupt Vector Table)找到相应的中断处理函数的地址。 3. 中断嵌套和优先级:STM32F103 支持多级嵌套中断,并且每个中断有不同的优先级。如果当前正在处理一个中断,而另一个优先级更高的中断请求发生,处理器会先处理更高优先级的中断。 4. 中断服务函数:一旦找到中断处理函数的地址,处理器会跳转到该地址执行中断服务函数。在该函数中,可以进行一些特定的操作,如保存寄存器状态、处理中断事件、更新相关标志位等。 5. 中断清除:在中断服务函数执行完毕后,需要清除中断标志位,以允许再次触发相同的中断事件。 6. 中断返回:中断服务函数执行完毕后,处理器会从堆栈中恢复之前保存的寄存器状态,并跳转回到中断触发时的执行点继续执行。 需要注意的是,具体的中断处理过程可能会根据所使用的开发环境、编译器和中断控制器配置等因素有所不同。以上是一个常见的中断处理过程的概述,具体实现可能会有所差异。建议参考相关的 STM32F103 参考手册和开发工具的文档来了解更详细的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值