1. 什么是中断
在处理器中,中断是一个过程,即CPU在正常执行程序的过程中,遇到外部/内部的紧急事件需要处理,暂时中止当前程序的执行,转而去为处理紧急的事件,待处理完毕后再返回被打断的程序处继续往下执行。
在发送中断时。要打断CPU正在做的事情。要保护现场,接着根据中断向量跳转到中断服务函数执行。执行完要恢复现场。CPU继续从打断时的状态运行。
举个列子:当前正在看书(CPU执行),突然客厅的电话响了(中断请求)。打断看书(保存现场,当前看到第几页)。去处理打电话(中断服务函数)。打完电话后继续看书(恢复 现场)从打断的页继续看。
2. 什么是中断嵌套以及中断优先级
1. 中断优先级
比如CPU正在运行有两个中断请求。这时总有一个先后。这时就看这两个中断的优先级(程序来设置)。
2. 中断嵌套
当前正在看书(CPU执行),突然客厅的电话响了(中断请求)。打断看书(保存现场,当前看到第几页)。去处理打电话(中断服务函数)。这时水壶开了(水壶比打电话优先级高)。
这时打断电话去处理水壶开。这就是中断嵌套。当然在处理这前也会有保存现场(打电话)。去处理水壶请求。水壶处理完在处理打电话。打完电话后继续看书(恢复 现场)从打断的页继续看。
3. 抢占优先级与子响应优先级
1.抢占式优先级
望文知义,就是优先级高的可以抢占优先级的中断。
具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套在低抢占式优先级的中断中。
2. 子优先级(响应式优先级)
望文知义,就是当两个抢占式优先级同时来时,先处理响应式优先级高的(谁优先级高先响应谁)。
当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。
总结下便是:抢占式优先级>响应优先级>中断表中的排位顺序
如下函数设置中断分组:
void nvic_priority_group_set(uint32_t nvic_prigroup)
3. 什么是异常
内核里的中断就叫异常(滴答定时器)。外部发送的就叫中断(定时器溢出中断,串口接收数据中断)
4. 什么是事件
5. 帮助CPU专门处理中断的助手NVIC(在内核里)
它可以屏蔽中断,判断中断优先级,处理中断向量。
6. 查找手册可以看到底有多少内部中断与外部中断。
内部中断:如下图:有16个。优先级一次往下。一般不允许改。
外部中断:(查当前芯片有68个)下面只是其中一部分。
7. 外部中断(EXIT)
上图:中断流程如下:
8.程序设计
1. 触摸按键的原理介绍。
原理:触摸按键接在TTP223-BA6的输入I引脚,Q是输出接在OUT_4上。芯片引脚PA3上。
当手触摸按键时会有感应电容与C41并联(电容变大)Q输出0,
当手松开触摸按键时会没有感应电容。只有C41(电容变小)Q输出1。
程序设计:当一按触摸按键就会产生一个下降沿。把PA3设置为外部中断3。并且下降沿触发。来翻转LED1。
9. 程序代码实现
EXTI.h
#ifndef _EXTI_H
#define _EXTI_H
#include "gd32f10x.h"
#include <stdio.h>
void EXTI_Init(void);
void EXTI3_IRQHandler(void);
#endif
EXTI.c
#include "EXTI.h"
#include "LED.h"
// 外部中断的初始化函数
void EXTI_Init(void){
/* 使能复用时钟 */
rcu_periph_clock_enable(RCU_AF);
/* 使能中断,并设置中断优先级 */
/* 参数1:中断类型 参数2:抢占优先级 参数3:子优先级 */
nvic_irq_enable(EXTI3_IRQn, 2U, 2U);
// 初始化EXTI线,并设置中断触发方式
/* 参数1:中断线 参数2:中断模式 参数3:中断类型 */
exti_init(EXTI_3, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
/* 清除中断发生的标志 */
exti_interrupt_flag_clear(EXTI_3);
/* 选择中断源 */
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOA, GPIO_PIN_SOURCE_3);
}
// EXTI3(按键D)过来的中断的服务函数
void EXTI3_IRQHandler(void){
LED2_Toggle();
exti_interrupt_flag_clear(EXTI_3); /* 清除中断发生的标志 */
}
main.c
#include "LED.h"
#include "EXTI.h"
int main(){
LED_Init();
EXTI_Init();
while(1){
}
}