在单片机应用系统中,中断主要用于实时监测和控制。单片机如果没有中断系统,那就需要浪费大量的时间用于轮询是否有服务请求的定时查询上面。采用中断技术完全可以消除查询方式中的等待现象。
这里主要讲述AT89S51芯片的中断系统
1)系统有五个中断请求源简称为终端源,两个终端优先级,可以实现两级中断服务程序的嵌套。
2)每个中断源都可以使用软件独立地控制为允许中断或者中断关闭
3)中断的优先级由软件设置。
中断请求源-------5个中断源
1,INT0(上面的横线打不出来)—外部中断请求0,中断请求信号为负跳变或者低电平有效,中断请求标志位IE0。
2,INT1(上面的横线打不出来)—外部中断请求1,中断请求信号为负跳变或者低电平有效,中断请求标志位IE1。
3,T0----定时器/计算器,计数溢出时发出的中断信号,请求标志位TF0.
4,T1----定时器/计算器,计数溢出时发出的中断信号,请求标志位TF1.
5,串行口中断请求----中断请求标志为发送中断TI或接收终端RI
中断请求标志寄存器
1TCON《Timer Control Register》定时器/计数器的控制寄存器,字节地址为88H,可位寻址。
1)TF1—片内定时器/计数器T1的溢出中断请求标志。在启动之后T1会自动从初值开始加一,当最高位产生溢出的时候《超过65536》,由硬件电路开始置“1”,向CPU请求中断。当CPU开始中断的时候TF1由硬件电路置“0”,同事TF1也可以由软件置“0”。
2)TF0的功能和TF1类似
3)IE1–外部中断1的中断标志位
4)IE0–外部中断0的中断标志位
5)IT1–选择外部中断1的触发方式是跳沿触发还是电平触发。
当IT1=1的时候,是跳沿触发方式,加到外部中断1,INT1的外部中断1请求输入信号由高电平到低电平负跳变有效<正跳变是由低电平到高电平>并把IE1置“1”。转向中断服务程序的时候,则由硬件自动把IE1清“0”。
当IT1=0的时候,是电平触发方式,加到外部中断1,INT1的外部中断1请求输入信号低电平有效,并把IE1置“1”。转向中断服务程序的时候,则由硬件自动把IE1清“0”。
6)TR1–TR0:计算运行控制位
TR1或者TR0 =1,是启动定时器/计数器的必要条件。
TR1或者TR0 =0,停止定时器/计数器计数。
可以由软件进行置1“或者清0.
SCON寄存器 Serial Control Register)
字节地址为98H,可以位寻址。SCON的低二位锁存串行口的发送和接收的中断请求标志TI和RI。
1)TI–串行口的发送中断请求标志位。CPU将一个字节的数据写入串行口的发送缓冲器SBUF,就启动一帧串行数据的发送,没发完一帧数据后硬件自动将,硬件自动将其置一。
2)RI–串行口的接收中断请求标志位。
IE中断允许寄存器
IE的字节地址为A8H,可进行位寻址。IE对于中断实行两级控制。一个总开关EA,二级开关是五个中断源的控制为
EA:中断允许总开关控制位
EA= 1.所有的中断请求都被允许
EA= 0.所有的中断请求都被禁止
ES:串行口中断允许位
ES = 1 允许串行口中断
ES = 0 禁止串行口中断
ET1:定时器/计数器1的溢出中断允许位
ET1= 1 时允许T1溢出中断
ET1= 0 时禁止T1溢出中断
ET0:定时器/计数器0的溢出中断允许位
ET0= 1 时允许T0溢出中断
ET0= 0 时禁止T0溢出中断
EX1:外部中断1的中断允许位
EX1 = 1 允许外部中断1中断
EX1 = 0 禁止外部中断1中断
EX0:外部中断1的中断允许位
EX0 = 1 允许外部中断0中断
EX0 = 0 禁止外部中断0中断
在AT89S51复位后,IE被清”0“,所有的中断请求都被禁止。
中断优先级寄存器IP Interrupt Priority
PS–串行口中断优先级控制位。
PS=1,串行口中断定义为高优先级中断。
PS=0,串行口中断定义为低优先级中断。
PT1–定时器/计数器1中断优先级控制位。
PT1=1,定时器/计数器1中断定义为高优先级中断。
PT1=0,定时器/计数器1中断定义为低优先级中断。
PX1—外部中断1中断优先级控制位。
PX1=1,外部中断1定义为高优先级中断。
PX1=0,外部中断1定义为低优先级中断。
PT0–定时器/计数器0中断优先级控制位。
PT0=1,定时器/计数器0中断定义为高优先级中断。
PT0=0,定时器/计数器0中断定义为低优先级中断。
PX0–外部中断0中断优先级控制位。
PX0=1,外部中断0定义为高优先级中断。
PX0=0,外部中断0定义为低优先级中断
小结:响应中断请求的条件
总中断开关EA=1开启,
对应中断源的请求标志位1
该中断的中断允许位为1,即中断被允许
无同级中断和更高级的中断在执行
下面是一个demo
/*P1口接八个led,开关k1,k2分别接外部中断0 P3.2,和外部中断1 P3.3
程序执行的时候8是流水灯形式。
1)k1按下上下四个灯是交替闪烁10次
2)k2按下的是8个灯交替闪烁5次
3)设置优先级别
*/
#include<reg51.h>
#include<intrins.h> //循环移位的头文件
#define uint unsigned int
void delay(int z)
{
int i,j;
for(i=0;i<z;i++)
for(j=0;j<110;j++);
}
/* 中断函数的步骤
1)开启总中断EA
2) 开启对应的中断的允许位,外部中断0,对应EX0=1,外部中断1,对应EX1=1;
3)选择触发方式(跳沿触发=1,电平触发=0),外部中断0对应的是IT0=0,低电平有效。
外部中断1对应的是IT1=1,跳沿触发,高电平跳变成低电平有效
4)设置中断的优先级,如果不设置则按照系统默认的优先级别
*/
void main()
{
uint tmp;
EA = 1;//开启总中断
EX0 = 1;//外部中断0允许位,置一表示允许
IT0 = 0;//外部中断0,选择电平触发,低电平有效
EX1 = 1;//外部中断1的允许位
IT1 = 1;//外部中断1,选择跳沿触发,电平由高到低的负跳变有效
PX0 = 0;//外部中断0,优先级别为低
PX1 = 1;//外部中断1,优先级别为高
tmp = 0xfe;
while(1)
{
P1 = tmp;
tmp=_crol_(tmp,1);
delay(500);
}
}
//外部中断0
void exter0() interrupt 0
{
uint tmp1;
int mun;
IE0 = 0;//关闭外部中断0
tmp1 = 0xf0;
for(mun=0;mun<10;mun++)
{
P1=tmp1;
tmp1 =_crol_(tmp1,4);
delay(500);
}
IE0 = 1;//开启外部中断0
}
//外部中断1
void exter1() interrupt 2
{
int mun1;
EX1= 0;//关闭外部中断1
for(mun1=0;mun1<5;mun1++)
{
P1 = 0x00;
delay(500);
P1 = 0xff;
delay(500);//这个延时必须要有,不然肉眼无法辨别出led灯有亮
}
EX1 = 1;//开启外部中断1
}