51单片机中断优先级讲解以及示例说明

51单片机中断优先级讲解以及示例说明


  • Proteus仿真演示
    在这里插入图片描述

51单片机中断的优先级有两个:查询优先级和执行优先级

查询优先级

查询优先级是指当51单片机的多个中断源同时引起中断时,CPU逐个查询中断标志位的次序,高优先级的中断标志位将被优先查询到,但并不代表查询优先级高的中断一定可以打断正在执行中断处理的低优先级中断。查询优先级是由单片机硬件决定,不可更改。

  • 单片机内部自然优先级顺序(由高到低)为:
    在这里插入图片描述
1
2
外部中断0→定时器0中断→外部中断l→定时器1中断→串行口中断

在这里插入图片描述

  • 如果使用C语言编程,中断查询次序号就是中断号,例如:
1
2
3
4
5
6
7
8
9
void Int0\_Routine(void) interrupt 0
void Timer0\_Rountine(void) interrupt 1
void Int1\_Routine(void) interrupt 2
void Timer1\_Rountine(void) interrupt 3
void UART\_Routine(void) interrupt 4
void Timer2\_Routine(void) interrupt 5
void Int2\_Routine(void) interrupt 6
void Int3\_Routine(void) interrupt 7

  • 查询优先级说明:
  1. 当定时器中断0和外部中断1同时引起时(没有设置中断优先级控制寄存器),则会首先执行定时器中断0的请求;
  2. 当定时器中断0和外部中断1同时引起且外部中断1正在执行请求时(没有设置中断优先级控制寄存器),外部中断1不能被任何中断(包括定时器中断0)所打断。

执行优先级

执行优先级由中断优先级控制寄存器IP来控制。

中断优先级控制寄存器

在这里插入图片描述

  • PT2:定时器中断2优先级控制位
  • PS:串口中断优先级控制位
  • PT1:定时器中断1优先级控制位
  • PX1:外部中断1优先级控制位
  • PT0:定时器中断0优先级控制位
  • PX0:外部中断0优先级控制位
中断触发条件

在这里插入图片描述

如果只设置IP寄存器,执行优先级则只有两级:高优先级(IP中的相应位置1)和低优先级(IP中的相应位置0)。若寄存器IP没有设置(即寄存器IP所有位全为0),则只按照查询优先级进行。

中断的优先级总结:
  1. CPU同时接收到几个中断时,首先响应优先级最高的中断请求;
  2. 正在进行的中断过程不能被新的同级或低行优优先级的中断请求所中断;
  3. 正在进行的低行优优先级中断服务,能被高行优优先级中断请求中断;

当IP中的PX1位和PT0位置1,其余位置0时,中断的响应次序依次为:

1
2
定时器中断0 → 外部中断1 → 外部中断0 → 定时器中断1 → 串口中断 → 定时器中断2

中断嵌套

中断嵌套,是当一个中断正在执行的时候,如果事先设置了中断优先级寄存器IP,那么当一个更高优先级的中断到来的时候会发生中断嵌套,如果没有设置则不会发生任何嵌套;如果有同一个优先级的中断触发,它并不是在“不断的申请”,而是将它相应的中断标志位置即IE寄存器的某位置位,当CPU执行完当前中断之后,按照查询优先级重新去查询各个中断标志位,进入相应中断。

产生中断嵌套,关键字using的使用说明

没有设置IP时,单片机会按照查询优先级来排队进入不同中断服务。如果要想让某个中断优先响应, 则要设置IP,更改执行优先级,当设置了IP寄存器后,当低执行优先级中断正在执行期间,有高执行优先级的中断产生,则会嵌套调用进入高执行优先级的中断。如果是用C语言写的程序,并在中断服务时,using 寄存组,要注意:两个不同执行优先级的中断服务程序不要使用相同的 using 寄存器。

  • 当产生中断嵌套时,C语言编程相当于手动去给cpu分配了寄存器进栈和出栈的寄存器组,用来保护和恢复现场。
  • 如果是使用汇编编程,在写代码时就需要手动添加工作寄存器r1-r7。
51单片机中using使用在C语言编程中,用来在中断函数中指定工作寄存器区,工作寄存器共有4个区,分别代表R0~R7地址是:
1
2
3
4
5
第0工作区:00H~07H
第1工作区:08H~0FH
第2工作区:10H~17H
第3工作区:18H~1FH

using n,那么n就是第几区,使用方法如下:
void exterint0() interrupt 0 using 1
这表示外部中断0使用第1工作区地址。

示例代码

这里演示的外部中断1的执行优先级最高,其次是外部中断0,最低优先级定时器0.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include"reg52.h"
#include"intrins.h"
#define uchar unsigned char //定义字符类型
#define uint unsigned int
#define FOSC 12000000uL
#define T50MS (65536-FOSC\*50/12/1000) //50ms timer calculation method in 12T mode

sbit led=P2^0; //定义IO口P2.0为led
sbit led1=P2^1;
static volatile uchar flag=0; //定义flag类型

void delay(){ //延时程序5s
unsigned char i, j, k;
\_nop\_();
i = 38;
j = 0;
k = 118;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void init()//初始化,即打开各中断开关
{
TMOD=0x01;
TH0= T50MS >> 8;; //定时器0装初值
TL0 = T50MS;
// TH0=(65536-50000)/256; //定时器0装初值
// TL0=(65536-50000)%256; //同上
IT0=1;//外部中断0为跳变沿触发方式
IT1=1;//外部中断1为跳变沿触发方式
EA=1;//开总中断
EX0=1;//打开外部中断0
EX1=1;//打开外部中断1
ET0=1;//打开定时器0中断开关
TR0=1;//打开定时器0运行开关
// IP=0x01;//设置int0优先级为高,与PX0=1;等效
PX1=1;//外部中断1优先级最高,

}
/\*按键1\*/
void int0() interrupt 0 using 0//外部中断0的执行程序。
{ //interrupt 0指外部中断0 using 0指第0组寄存器
led=1; //熄灭LED灯
led1=1;
delay();//延时5s
}
void t0() interrupt 1 using 1 //定时器
{
TH0= T50MS >> 8;; //定时器0装初值
TL0 = T50MS;
// TH0=(65536-50000)/256; //定时器0装初值
// TL0=(65536-50000)%256; //同上
flag++; //记录定时器经过的时间
if(flag==8){ //定时2秒后执行,flag=40时约两秒
led1=led=~led; //点亮LED灯
// led1= ~led1;
flag=0; //重置定时,达到每两秒点亮一次的目的
}
}
/\*按键2\*/
void int1() interrupt 2 using 2//外部中断1的执行程序。
{
led=1;
led1=0;
delay();
}
void main()//主函数
{
init(); //初始化
led=1; //指定LED灯开始的时候是熄灭状态
led1=1;
while(1);
}


程序源码和仿真资源

本示例仿真基于Proteus8.12平台。

1
2
3
链接:https://pan.baidu.com/s/1gWoBxcz-Lwev3Dnu6JCyLA 
提取码:0jg1 //温馨提示:在填写提取码时,建议使用复制粘贴命令,以免出错。


竹石 清朝·郑板桥
咬定青山不放松,立根原在破岩中。
千磨万击还坚劲,任尔东西南北风。