目录
中断定义
中断系统是计算机的重要组成部分。实时控制、故障自动处理、计算机与外围设备间的数据传送往往采用中断系统。中断系统的应用大大提高了计算机效率。
中断就是CPU原本执行着程序,进来了一个更加紧急的程序需要优先执行,CPU跳到需要优先执行的地方先执行,再回到原来的程序里。引用Bilibili江科大自化协的例子:医院的医生给病人看病,这时候突然来了一个更加紧急的病人,那么他可以优先看病,这就是中断。被中断后,如果又来了更加紧急,再次中断去给更加紧急的病人看病,这就是中断嵌套。给紧急的病人看完病之后再回到原来的病人。
单片机的中断是由单片机片内的中断系统来实现的。当中断请求源(简称中断源)发出中断请求时,如果中断请求被允许的话,单片机暂时中止当前正在执行的主程序,转到中断服务程序处理中断服务请求,处理完中断服务请求后,再回到原来被中止的程序之处(断点),继续执行被中断的主程序。
中断常见使用情景
1.外部中断EXTI
如果使用按键扫描的模式去读入引脚的高低电平,在主程序while循环里一遍又一遍读入引脚状态,这会占用大量的CPU资源,并且如果主程序执行代码较多,很可能检测不到按键。如果使用外部中断,那么就可以设置引脚在下降沿或上升沿触发中断,再到中断函数里处理,这就可以节约资源。
2.外设中断
同样的,像串口、IIC、SPI、ADC、TIM等外设,如果一直在主程序里去判断状态就会消耗大量资源,串口可以使能接收中断,那么只有在接收到数据之后才会响应中断,就不需要主程序去判断接收状态。
优先级
中断优先级分为响应优先级和抢占优先级,在多个中断同时产生时,就需要比较这两个优先级的大小,从而判断哪个中断优先处理。
具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。
1.优先级的规则:
1.如果抢占优先级相同,两个中断没有嵌套关系,先来的中断优先处理
2.如果中断同时到达,则根据响应优先级高低来决定先处理哪一个
3.如果抢占优先级和响应优先级相同,则根据中断号排位顺序决定优先
2.中断向量表:
NVIC
NVIC:Nested vectoredinterrupt controller,嵌套向量中断控制器。
需要在NVIC里配置中断的优先级和分组。
假定设置组2,则抢占优先级只能设置为0-3,响应优先级也只能设置为0-3。因为抢占优先级和响应优先级总共占了4位的寄存器,分组只是在划分这两个优先级各占几位。不能理解就直接配置就行,表中没有的就无法配置。
NVIC的作用就是处理多个中断谁先谁后,把队排好,因为CPU在某一刻只能处理一件事,NVIC把中断排好队让CPU一个个处理。
1.NVIC框图
引用江科大自化协的图片:
2.配置NVIC代码
这里引用了正点原子sys.h里的函数
//设置NVIC分组
//NVIC_Group:NVIC分组 0~4 总共5组
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)
{
u32 temp,temp1;
temp1=(~NVIC_Group)&0x07;//取后三位
temp1<<=8;
temp=SCB->AIRCR; //读取先前的设置
temp&=0X0000F8FF; //清空先前分组
temp|=0X05FA0000; //写入钥匙
temp|=temp1;
SCB->AIRCR=temp; //设置分组
}
//设置NVIC
//NVIC_PreemptionPriority:抢占优先级
//NVIC_SubPriority :响应优先级
//NVIC_Channel :中断编号
//NVIC_Group :中断分组 0~4
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组0:0位抢占优先级,4位响应优先级
//组1:1位抢占优先级,3位响应优先级
//组2:2位抢占优先级,2位响应优先级
//组3:3位抢占优先级,1位响应优先级
//组4:4位抢占优先级,0位响应优先级
//NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)
{
u32 temp;
MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf; //取低四位
NVIC->ISER[NVIC_Channel/32]|=(1<<NVIC_Channel%32);//使能中断位(要清除的话,相反操作就OK)
NVIC->IP[NVIC_Channel]|=temp<<4; //设置响应优先级和抢断优先级
}
NVIC的函数直接用了,在《stm32f103中文教程及手册》中没有关于NVIC的学习,需要参考《STM32F10xxx Cortex-M3编程手册》
在库函数代码中,NVIC的配置可以是这样:
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级和balabala优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);