1.中断概念
CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生);
CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);
待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断。
2.中断系统结构
引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。CPU暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统。
89C51/52的中断系统有5个中断源 ,2个优先级,可实现二级中断嵌套 。
- (P3.2)可由IT0(TCON.0)选择其为低电平有效还是下降沿有效。当CPU检测到P3.2引脚上出现有效的中断信号时,中断标志IE0(TCON.1)置1,向CPU申请中断。
- (P3.3)可由IT1(TCON.2)选择其为低电平有效还是下降沿有效。当CPU检测到P3.3引脚上出现有效的中断信号时,中断标志IE1(TCON.3)置1,向CPU申请中断。
- TF0(TCON.5),片内定时/计数器T0溢出中断请求标志。当定时/计数器T0发生溢出时,置位TF0,并向CPU申请中断。
- TF1(TCON.7),片内定时/计数器T1溢出中断请求标志。当定时/计数器T1发生溢出时,置位TF1,并向CPU申请中断。
- RI(SCON.0)或TI(SCON.1),串行口中断请求标志。当串行口接收完一帧串行数据时置位RI或当串行口发送完一帧串行数据时置位TI,向CPU申请中断。
3.中断允许控制寄存器---IE
CPU对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE控制的
- EX0(IE.0),外部中断0允许位;
- ET0(IE.1),定时/计数器T0中断允许位;
- EX1(IE.2),外部中断0允许位;
- ET1(IE.3),定时/计数器T1中断允许位;
- ES(IE.4),串行口中断允许位;
- EA (IE.7), CPU中断允许(总允许)位。
4.定时器控制寄存器---TCON
TCON的中断标志:中断标志位就是提供给用户查询的事件及区分中断事件。
- 51串口中断接受与发送时同一个中断入口,需要串口中断标记位RI与TI区分时发送中断还是接收中断。
- 当中断不开启,而使用查询方式,这就可以使用中断标记位进行判断是否有相关事件发生。
- 当开启中断时,每执行一条汇编指令系统会根据这个标志位进行是否进入中断处理。
通俗的讲:中断标志置1的话,cpu会记录这个中断标志位,然后进入中断处理
- TR0(TR1)——定时器运行控制位
当TR0(TR1)=0 停止定时器/计数器工作
当TR0(TR1)=1 启动定时器/计数器工作
- IE0(IE1)——外中断请求标志位
当CPU采样到P3.2(P3.3)出现有效中断请求时,此位由硬件置1。在中断响应完成后转向中断服务时,再由硬件自动清0。
- IT0(IT1)——外中断请求信号方式控制位
当IT0(IT1)=1 脉冲方式(后沿负跳有效)
当IT0(IT1)=0 电平方式(低电平有效)此位由软件置1或清0。
- TF0(TF1)——计数溢出标志位
当计数器产生计数溢出时,此位由硬件置1。当转向中断服务时,再有硬件自动清0。计数溢出的标志位的使用有两种情况:采用中断方式时,作中断请求标志位 来使用;采用查询方式时,作查询状态位来使用。
5.中断优先级寄存器--IP
IP 这个寄存器的每一位,表示对应中断的抢占优先级,每一位的复位值都是 0,当把某一位设置为 1 的时候,这一位的优先级就比其它位的优先级高了。
- 抢占优先级
比如设置了 PT0位为 1 后,当单片机在主循环或者任何其它中断程序中执行时,一旦定时器 T0 发生中断,作为更高的优先级,程序马上就会跑到 T0 的中断程序中来执行。
反过来,当单片机正在 T0中断程序中执行时,如果有其它中断发生了,还是会继续执行 T0 中断程序,直到把 T0 中的中断程序执行完毕以后,才会去执行其它中断程序。
当进入低优先级中断中执行时,如又发生了高优先级的中断,则立刻进入高优先级中断执行,处理完高优先级级中断后,再返回处理低优先级中断,这个过程就叫做中断嵌套,也称为抢占。
所以抢占优先级的概念就是,优先级高的中断可以打断优先级低的中断的执行,从而形成嵌套。当然反过来,优先级低的中断是不能打断优先级高的中断的。
- 固有优先级
那么既然有抢占优先级,自然就也有非抢占优先级了,也称为固有优先级。在下图的最后一列给出的就是固有优先级,请注意,在中断优先级的编号中,一般都是数字越小优先级越高。
从表中可以看到一共有 1~6 共 6 级的优先级,这里的优先级与抢占优先级的一个不同点就是,它不具有抢占的特性,也就是说即使在低优先级中断执行过程中又发生了高优先级的中断,那么这个高优先级的中断也只能等到低优先级中断执行完后才能得到响应。既然不能抢占,那么这个优先级有什么用呢?
答案是多个中断同时存在时的仲裁。比如说有多个中断同时发生了,当然实际上发生这种情况的概率很低,但另外一种情况就常见的多了,那就是出于某种原因我们暂时关闭了总中断,即 EA=0。执行完一段代码后又重新使能了总中断,即 EA=1。那么在这段时间里就很可能有多个中断都发生了,但因为总中断是关闭的,所以它们当时都得不到响应,而当总中断再次使能后,它们就会在同时请求响应了,很明显,这时也必需有个先后顺序才行,这就是非抢占优先级的作用了——如表中,谁优先级最高先响应谁,然后按编号排队,依次得到响应。
6.定时器模式寄存器---TMOD
工作方式寄存器TMOD用于设置定时/计数器的工作方式,低四位用于T0,高四位用于T1。
- GATE是门控位
GATE=0时,用于控制定时器的启动是否受外部中断源信号的影响。只要用软件使TCON中的TR0或TR1为1,就可以启动定时/计数器工作;
GATA=1时,要用软件使TR0或TR1为1,同时外部中断引脚INT0/1也为高电平时,才能启动定时/计数器工作。
- C/T :定时/计数模式选择位
C/T =0为定时模式;
C/T =1为计数模式。
- M1M0:工作方式设置位
定时/计数器有四种工作方式
7.中断源
记住区分中断号
7.中断响应条件
- 中断源有中断请求;
- 此中断源的中断允许位为1;
- CPU开中断(即EA=1)。
8.举例说明(外部中断0):
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit k3=P3^2; //定义按键K3
sbit led=P2^0; //定义P20口是led
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函 数 名 : Int1Init()
* 函数功能 : 设置外部中断1
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int0Init()
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)---中断请求
EX0=1;//打开INT0的中断允许。 ---外部中断允许
EA=1;//打开总中断 ----总中断
}
void main()
{
Int0Init(); // 设置外部中断0
while(1);
}
/*******************************************************************************
* 函 数 名 : Int0() interrupt 0
* 函数功能 : 外部中断0的中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int0() interrupt 0 //外部中断0的中断函数 ;0为外部中断0的中断号
{
delay(1000); //延时消抖
if(k3==0)
{
led=~led;
}
}
9.举例说明(定时器1实验 )
**************************************************************************************
* 定时器1实验 *
实现现象:下载程序后数码管最后一位间隔一秒循环显示0-F。使用单片机内部定时器可以实现准确延时。
注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
u8 n=0;
/*******************************************************************************
* 函 数 名 : Timer1Init
* 函数功能 : 定时器1初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer1Init()
{
TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。
//0x10=0001 0000,所以是T1模式,工作方式1
TH1=0XFC; //给定时器赋初值,定时1ms (65536-1000=64536)
TL1=0X18;
ET1=1;//打开定时器1中断允许
EA=1;//打开总中断
TR1=1;//打开定时器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
LSA=0;
LSB=0;
LSC=0;
Timer1Init(); //定时器1初始化
while(1);
}
/*******************************************************************************
* 函 数 名 : void Timer1() interrupt 3
* 函数功能 : 定时器0中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer1() interrupt 3
{
static u16 i;
TH1=0XFC; //给定时器赋初值,定时1ms
TL1=0X18;
i++;
if(i==1000)
{
i=0;
P0=smgduan[n++];
if(n==16)n=0;
}
}