中断基础知识
异常就是中断,中断就是异常。但是习惯上称系统产生的为异常,外部产生的为中断,即系统异常和外部中断。
谈到中断,必须知道NVIC。NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设
NVIC 结构体定义
typedef struct {
__IO uint32_t ISER[8]; // 中断使能寄存器
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; // 中断清除寄存器
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; // 中断使能悬起寄存器
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; // 中断清除悬起寄存器
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; // 中断有效位寄存器
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; // 中断优先级寄存器(8Bit wide)
uint32_t RESERVED5[644];
__O uint32_t STIR; // 软件触发中断寄存器
} NVIC_Type;
优先级定义
在NVIC 有一个专门的寄存器:中断优先级寄存器NVIC_IPRx,用来配置外部中断的优先级。
用于表达优先级的这4bit,又被分组成抢占优先级和子优先级。如果有多个中断同时响应,抢占优先级高的就会 抢占 抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。
其中抢占优先级即主优先级
中断优先级分组库函数 void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
/**
* 配置中断优先级分组:抢占优先级和子优先级
* 形参如下:
* @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
* 4 bits for subpriority
* @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
* 3 bits for subpriority
* @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
* 2 bits for subpriority
* @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
* 1 bits for subpriority
* @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
* 0 bits for subpriority
* @注意 如果优先级分组为0,则抢占优先级就不存在,优先级就全部由子优先级控制
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
/* 设置优先级分组 */
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
中断编程
1、使能外设某个中断,这个具体由每个外设的相关中断使能位控制。
2、初始化NVIC_InitTypeDef 结构体,配置中断优先级分组,设置抢占优先级和子优先级,使能中断请求。
/* NVIC 初始化结构体 */
typedef struct {
uint8_t NVIC_IRQChannel; // 中断源 成员配置可参考stm32f10x.h 头文件里面的IRQn_Type 结构体定义
uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级(主优先级)
uint8_t NVIC_IRQChannelSubPriority; // 子优先级
FunctionalState NVIC_IRQChannelCmd; // 中断使能(ENABLE)或者失能(DISABLE)
} NVIC_InitTypeDef;
3、编写中断服务函数。
在启动文件中已经定义了中断服务函数,为的只是初始化中断向量表。中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限循环,实现不了中断。
EXTI—外部中断/事件控制器
EXTI 是在APB2 总线上的
STM32之中断与事件—中断与事件的区别
总的来说,产生中断线路目的是把输入信号输入到NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。
中断/事件线
EXTI 有20 个中断/事件线,每个GPIO 都可以被设置为输入线(如下面框图中的标号为 1 的输入线),占用EXTI0 至EXTI15,还有另外4根用于特定的外设事件。
EXTIx 可以通过AFIO 的外部中断配置寄存器(AFIO_EXTICR1、AFIO_EXTICR2、AFIO_EXTICR3、AFIO_EXTICR4)的EXTIx[3:0]位选择配置为PAx、PBx、PCx、PDx、PEx、PFx、PGx、PHx或者PIx。
以EXTI0为例,设置寄存器AFIO_EXTICR1的EXTI1[3:0]位选择配置PA0、PB0、PC0、PD0、PE0、PF0、PG0、PH0 或者PI0。涉及到的寄存器见下图:

外部中断/事件控制器框图
1、输入线 EXTI 有20 个中断/事件线,每个GPIO 都可以被设置为输入线
2、边沿检测电路 它会根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)对应位的设置来控制信号触发。
3、或门 它一个输入来自编号2 电路,另外一个输入来自软件中断事件寄存器(EXTI_SWIER)。EXTI_SWIER 允许我们通过程序控制就可以启动中断/事件线,相当于一个小开关。
4、与门 它一个输入是编号3 电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR)。
5、 是将EXTI_PR 寄存器内容输出到NVIC 内,从而实现系统中断事件控制
6、与门 它一个输入来自编号3 电路,另外一个输入来自事件屏蔽寄存器(EXTI_EMR)
7、脉冲发生器电路 当它的输入端,即编号6 电路的输出端,是一个有效信号1 时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。
8、一个脉冲信号 就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器TIM、模拟数字转换器ADC 等等,这样的脉冲信号一般用来触发TIM或者ADC 开始转换。
软件中断事件寄存器(EXTI_SWIER): SWIERx: 线x上的软件中断,当该位为’0’时,写’1’将设置EXTI_PR中相应的挂起位。如果在EXTI_IMR和EXTI_EMR中允许产生该中断,则此时将产生一个中断。通过清除EXTI_PR的对应位(写入’1’),可以清除该位为’0’。
挂起寄存器(EXTI_PR): PRx: 挂起位 (Pending bit),0表示没有发生触发请求,1表示发生了选择的触发请求,当在外部中断线上发生了选择的边沿事件,该位被置’1’。在该位中写入’1’可以清除它,也可以通过改变边沿检测的极性清除。
中断屏蔽寄存器(EXTI_IMR): MRx: 线x上的中断屏蔽,0表示屏蔽来自线x上的中断请求,1表示开放来自线x上的中断请求。
事件屏蔽寄存器(EXTI_EMR): MRx: 线x上的事件屏蔽,0表示屏蔽来自线x上的事件请求,1表示开放来自线x上的事件请求。
注:以上四个寄存器加上边沿检测电路中用到的上升沿触发选择寄存器和下降沿触发选择寄存器中的位19只适用于互联型产品,对于其它产品为保留位。
EXTI 初始化结构体
typedef struct {
uint32_t EXTI_Line; // 中断/事件线
EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
FunctionalState EXTI_LineCmd; // EXTI 使能
} EXTI_InitTypeDef
中断/事件线选择,可选EXTI0 至EXTI19。对以下寄存器的位选控制:
如:EXTI_Line0对EXTI_IMR的第0位操作
- EXTI_Mode:EXTI 模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。中断屏蔽寄存器(EXTI_IMR)和事件屏蔽寄存器(EXTI_EMR)。
- EXTI_Trigger:EXTI 边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发(EXTI_Trigger_Falling) 或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)。操作寄存器上升沿触发选择寄存器(EXTI_RTSR) 和下降沿触发选择寄存器(EXTI_FTSR)。
- EXTI_LineCmd:控制是否使能EXTI线,可选使能EXTI线(ENABLE)或禁用EXTI线(DISABLE)
中断基础知识
异常就是中断,中断就是异常。但是习惯上称系统产生的为异常,外部产生的为中断,即系统异常和外部中断。
谈到中断,必须知道NVIC。NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设
NVIC 结构体定义
typedef struct {
__IO uint32_t ISER[8]; // 中断使能寄存器
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; // 中断清除寄存器
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; // 中断使能悬起寄存器
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; // 中断清除悬起寄存器
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; // 中断有效位寄存器
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; // 中断优先级寄存器(8Bit wide)
uint32_t RESERVED5[644];
__O uint32_t STIR; // 软件触发中断寄存器
} NVIC_Type;
优先级定义
在NVIC 有一个专门的寄存器:中断优先级寄存器NVIC_IPRx,用来配置外部中断的优先级。
用于表达优先级的这4bit,又被分组成抢占优先级和子优先级。如果有多个中断同时响应,抢占优先级高的就会 抢占 抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。
其中抢占优先级即主优先级
中断优先级分组库函数 void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
/**
* 配置中断优先级分组:抢占优先级和子优先级
* 形参如下:
* @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
* 4 bits for subpriority
* @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
* 3 bits for subpriority
* @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
* 2 bits for subpriority
* @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
* 1 bits for subpriority
* @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
* 0 bits for subpriority
* @注意 如果优先级分组为0,则抢占优先级就不存在,优先级就全部由子优先级控制
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
/* 设置优先级分组 */
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
中断编程
1、使能外设某个中断,这个具体由每个外设的相关中断使能位控制。
2、初始化NVIC_InitTypeDef 结构体,配置中断优先级分组,设置抢占优先级和子优先级,使能中断请求。
/* NVIC 初始化结构体 */
typedef struct {
uint8_t NVIC_IRQChannel; // 中断源 成员配置可参考stm32f10x.h 头文件里面的IRQn_Type 结构体定义
uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级(主优先级)
uint8_t NVIC_IRQChannelSubPriority; // 子优先级
FunctionalState NVIC_IRQChannelCmd; // 中断使能(ENABLE)或者失能(DISABLE)
} NVIC_InitTypeDef;
3、编写中断服务函数。
在启动文件中已经定义了中断服务函数,为的只是初始化中断向量表。中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限循环,实现不了中断。
EXTI—外部中断/事件控制器
EXTI 是在APB2 总线上的
STM32之中断与事件—中断与事件的区别
总的来说,产生中断线路目的是把输入信号输入到NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。
中断/事件线
EXTI 有20 个中断/事件线,每个GPIO 都可以被设置为输入线(如下面框图中的标号为 1 的输入线),占用EXTI0 至EXTI15,还有另外4根用于特定的外设事件。
EXTIx 可以通过AFIO 的外部中断配置寄存器(AFIO_EXTICR1、AFIO_EXTICR2、AFIO_EXTICR3、AFIO_EXTICR4)的EXTIx[3:0]位选择配置为PAx、PBx、PCx、PDx、PEx、PFx、PGx、PHx或者PIx。
以EXTI0为例,设置寄存器AFIO_EXTICR1的EXTI1[3:0]位选择配置PA0、PB0、PC0、PD0、PE0、PF0、PG0、PH0 或者PI0。涉及到的寄存器见下图:

外部中断/事件控制器框图
1、输入线 EXTI 有20 个中断/事件线,每个GPIO 都可以被设置为输入线
2、边沿检测电路 它会根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)对应位的设置来控制信号触发。
3、或门 它一个输入来自编号2 电路,另外一个输入来自软件中断事件寄存器(EXTI_SWIER)。EXTI_SWIER 允许我们通过程序控制就可以启动中断/事件线,相当于一个小开关。
4、与门 它一个输入是编号3 电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR)。
5、 是将EXTI_PR 寄存器内容输出到NVIC 内,从而实现系统中断事件控制
6、与门 它一个输入来自编号3 电路,另外一个输入来自事件屏蔽寄存器(EXTI_EMR)
7、脉冲发生器电路 当它的输入端,即编号6 电路的输出端,是一个有效信号1 时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。
8、一个脉冲信号 就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器TIM、模拟数字转换器ADC 等等,这样的脉冲信号一般用来触发TIM或者ADC 开始转换。
软件中断事件寄存器(EXTI_SWIER): SWIERx: 线x上的软件中断,当该位为’0’时,写’1’将设置EXTI_PR中相应的挂起位。如果在EXTI_IMR和EXTI_EMR中允许产生该中断,则此时将产生一个中断。通过清除EXTI_PR的对应位(写入’1’),可以清除该位为’0’。
挂起寄存器(EXTI_PR): PRx: 挂起位 (Pending bit),0表示没有发生触发请求,1表示发生了选择的触发请求,当在外部中断线上发生了选择的边沿事件,该位被置’1’。在该位中写入’1’可以清除它,也可以通过改变边沿检测的极性清除。
中断屏蔽寄存器(EXTI_IMR): MRx: 线x上的中断屏蔽,0表示屏蔽来自线x上的中断请求,1表示开放来自线x上的中断请求。
事件屏蔽寄存器(EXTI_EMR): MRx: 线x上的事件屏蔽,0表示屏蔽来自线x上的事件请求,1表示开放来自线x上的事件请求。
注:以上四个寄存器加上边沿检测电路中用到的上升沿触发选择寄存器和下降沿触发选择寄存器中的位19只适用于互联型产品,对于其它产品为保留位。
EXTI 初始化结构体
typedef struct {
uint32_t EXTI_Line; // 中断/事件线
EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
FunctionalState EXTI_LineCmd; // EXTI 使能
} EXTI_InitTypeDef
中断/事件线选择,可选EXTI0 至EXTI19。对以下寄存器的位选控制:
如:EXTI_Line0对EXTI_IMR的第0位操作
- EXTI_Mode:EXTI 模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。中断屏蔽寄存器(EXTI_IMR)和事件屏蔽寄存器(EXTI_EMR)。
- EXTI_Trigger:EXTI 边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发(EXTI_Trigger_Falling) 或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)。操作寄存器上升沿触发选择寄存器(EXTI_RTSR) 和下降沿触发选择寄存器(EXTI_FTSR)。
- EXTI_LineCmd:控制是否使能EXTI线,可选使能EXTI线(ENABLE)或禁用EXTI线(DISABLE)
举报