首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

跟我学单片机——第十八课 51单片机的中断系统

跟我学单片机——第十八课 51单片机的中断系统

有关中断的概念
   
什么是中断,我们从一个生活中的例子引入。你正在家中看书,突然电话铃响了,你放下书本,去接电话,和来电话的人交谈,然后放下电话,回来继续看你的书。这就是生活中的“中断”的现象,就是正常的工作过程被外部的事件打断了。


仔细研究一下生活中的中断,对于我们学习单片机的中断也很有好处。


第一、什么可以引起中断,生活中很多事件可以引起中断:有人按了门铃了,电话铃响了,你的闹钟闹响了,你烧的水开了….等等诸如此类的事件,我们把可以引起中断的称之为中断源,单片机中也有一些可以引起中断的事件,8031中一共有5个:两个外部中断,两个计数/定时器中断,一个串行口中断。


第二、中断的嵌套与优先级处理:设想一下,我们正在看书,电话铃响了,同时又有人按了门铃,你该先做那样呢?如果你正是在等一个很重要的电话,你一般不会去理会门铃的,而反之,你正在等一个重要的客人,则可能就不会去理会电话了。如果不是这两者(即不等电话,也不是等人上门),你可能会按你通常的习惯去处理。总之这里存在一个优先级的问题,单片机中也是如此,也有优先级的问题。优先级的问题不仅仅发生在两个中断同时产生的情况,也发生在一个中断已产生,又有一个中断产生的情况,比如你正接电话,有人按门铃的情况,或你正开门与人交谈,又有电话响了情况。考虑一下我们会怎么办吧。


第三、中断的响应过程:当有事件产生,进入中断之前我们必须先记住现在看书的第几页了,或拿一个书签放在当前页的位置,然后去处理不同的事情(因为处理完了,我们还要回来继续看书):电话铃响我们要到放电话的地方去,门铃响我们要到门那边去,也说是不同的中断,我们要在不同的地点处理,而这个地点通常还是固定的。计算机中也是采用的这种方法,五个中断源,每个中断产生后都到一个固定的地方去找处理这个中断的程序,当然在去之前首先要保存下面将执行的指令的地址,以便处理完中断后回到原来的地方继续往下执行程序。具体地说,中断响应可以分为以下几个步骤:


1、保护断点,即保存下一将要执行的指令的地址,就是把这个地址送入堆栈。


2、寻找中断入口,根据5个不同的中断源所产生的中断,查找5个不同的入口地址。以上工作是由计算机自动完成的,与编程者无关。在这5个入口地址处存放有中断处理程序(这是程序编写时放在那儿的,如果没把中断程序放在那儿,就错了,中断程序就不能被执行到)。


3、执行中断处理程序。


4、中断返回:执行完中断指令后,就从中断处返回到主程序,继续执行。


究竟单片机是怎么样找到中断程序所在位置,又怎么返回的呢?我们稍后再谈。


MCS-51中断系统的结构:


8031单片机的中断系统简单实用,其基本特点是:有5个固定的可屏蔽中断源,3个在片内,2个在片外,它们在程序存储器中各有固定的中断入口地址,由此进入中断服务程序;5个中断源有两级中断优先级,可形成中断嵌套;2个特殊功能寄存器用于中断控制和条件设置的编程。


中断系统的结构:
5个中断源的符号、名称及产生的条件如下。
INT0:外部中断0,由P3.2端口线引入,低电平或下跳沿引起。
INT1:外部中断1,由P3.3端口线引入,低电平或下跳沿引起。
T0:定时器/计数器0中断,由T0计满回零引起。
T1:定时器/计数器l中断,由T1计满回零引起。
TI/RI:串行I/O中断,串行端口完成一帧字符发送/接收后引起。整个中断系统的结构框图见下图一所示。



由图一可见,外部中断有下跳沿引起和低电平引起的选择;串行中断有发送(TI)相接收(R1)的区别;各个中断源打开与否,受中断自身的允许位和全局允许位的控制,并具有高优先级和低优先级的选择。

中断请求源:


(1)外部中断请求源:即外中断0和1,经由外部引脚引入的,在单片机上有两个引脚,名称为INT0、INT1,也就是P3.2、P3.3这两个引脚。在内部的TCON中有四位是与外中断有关的。


IT0:INT0触发方式控制位,可由软件进和置位和复位,IT0=0,INT0为低电平触发方式,IT0=1,INT0为负跳变触发方式。这两种方式的差异将在以后再谈。


IE0:INT0中断请求标志位。当有外部的中断请求时,这位就会置1(这由硬件来完成),在CPU响应中断后,由硬件将IE0清0。


IT1、IE1的用途和IT0、IE0相同。


(2)内部中断请求源


TF0:定时器T0的溢出中断标记,当T0计数产生溢出时,由硬件置位TF0。当CPU响应中断后,再由硬件将TF0清0。


TF1:与TF0类似。


TI、RI:串行口发送、接收中断,在串口中再讲解。


中断系统的控制寄存器:中断允许寄存器IE


在MCS-51中断系统中,中断的允许或禁止是由片内可进行位寻址的8位中断允许寄存器IE来控制的。见下表



其中EA是总开关,如果它等于0,则所有中断都不允许。


ES-串行口中断允许


ET1-定时器1中断允许


EX1-外中断1中断允许。


ET0-定时器0中断允许


EX0-外中断0中断允许。


如果我们要设置允许外中断1,定时器1中断允许,其它不允许,则IE可以是



即8CH,当然,我们也可以用位操作指令


SETB    EA
SETB    ET1


SETB    EX1


来实现它。

中断优先级寄存器IP


在MCS-中断优先级中由中断优先级寄存器IP来高置的,IP中某位设为1,相应的中断就是高优先级,否则就是低优先级。



IP优先级别寄存器各位介绍如下:


PS串行口中断优先级控制位。PS=1设定串行口为高优先级中断;PS=0为低优先级中断。


PT1T1中断优先级控制位。PT1=1设定定时器T1为高优先级中断;PT1=0为低优先级中断。


PX1外部中断1优先级控制位。PX1=1设定定时器外部中断1为高优先级中断;PX1=0为低优先级中断。


PT0T0中断优先级控制位。PT0=1设定定时器T0为高优先级中断;PT0=0为低优先级中断。


PX0外部中断0优先级控制位。PX0=1设定定时器外部中断0为高优先级中断;PX0=0为低优先级中断。


例:设有如下要求,将T0、外中断1设为高优先级,其它为低优先级,求IP的值。


IP的首3位没用,可任意取值,设为000,后面根据要求写就可以了



因此,最终,IP的值就是06H。


例:在上例中,如果5个中断请求同时发生,求中断响应的次序。


响应次序为:定时器0->外中断1->外中断0->实时器1->串行中断。

五个中断源的自然优先级与中断服务入口地址


外中断0:0003H


定时器0:000BH


外中断1:0013H


定时器1:001BH


串口 :0023H


它们的自然优先级由高到低排列。写到这里,大家应当明白,为什么前面有一些程序一始我们这样写:


ORG 0000H


LJMP START


ORG 0030H


START


这样写的目的,就是为了让出中断源所占用的向量地址。当然,在程序中没用中断时,直接从0000H开始写程序,在原理上并没有错,但在实际工作中最好不这样做。


优先级:单片机采用了自然优先级和人工设置高、低优先级的策略,即可以由程序员设定那些中断是高优先级、哪些中断是低优先级,由于只有两级,必有一些中断处于同一级别,处于同一级别的,就由自然优先级确定。


开机时,每个中断都处于低优先级,我们可以用指令对优先级进行设置。

MCS-51的中断响应过程:


中断响应的条件:讲到这儿,我们依然对于计算机响应中断感到神奇,我们人可以响应外界的事件,是因为我们有多种“传感器“――眼、耳可以接受不同的信息,计算机是如何做到这点的呢?其实说穿了,一点都不希奇,MCS51工作时,在每个机器周期中都会去查询一下各个中断标记,看他们是否是“1“,如果是1,就说明有中断请求了,所以所谓中断,其实也是查询,不过是每个周期都查一下而已。这要换成人来说,就相当于你在看书的时候,每一秒钟都会抬起头来看一看,查问一下,是不是有人按门铃,是否有电话。。。。很蠢,不是吗?可计算机本来就是这样,它根本没人聪明。


    了解了上述中断的过程,就不难解中断响应的条件了。在下列三种情况之一时,CPU将封锁对中断的响应:


1、CPU正在处理一个同级或更高级别的中断请求。


2、现行的机器周期不是当前正执行指令的最后一个周期。我们知道,单片机有单周期、双周期、三周期指令,当前执行指令是单字节没有关系,如果是双字节或四字节的,就要等整条指令都执行完了,才能响应中断(因为中断查询是在每个机器周期都可能查到的)。


3、当前正执行的指令是返回批令(RETI)或访问IP、IE寄存器的指令,则CPU至少再执行一条指令才应中断。这些都是与中断有关的,如果正访问IP、IE则可能会开、关中断或改变中断的优先级,而中断返回指令则说明本次中断还没有处理完,所以都要等本指令处理结束,再执行一条指令才可以响应中断。


中断响应过程


CPU响应中断时,首先把当前指令的下一条指令(就是中断返回后将要执行的指令)的地址送入堆栈,然后根据中断标记,将相应的中断入口地址送入PC,PC是程序指针,CPU取指令就根据PC中的值,PC中是什么值,就会到什么地方去取指令,所以程序就会转到中断入口处继续执行。这些工作都是由硬件来完成的,不必我们去考虑。这里还有个问题,大家是否注意到,每个中断向量地址只间隔了8个单元,如0003-000B,在如此少的空间中如何完成中断程序呢?很简单,你在中断处安排一个LJMP指令,不就可以把中断程序跳转到任何地方了吗?


一个完整的主程序看起来应该是这样的:


ORG 0000H


LJMP START


ORG 0003H


LJMP INT0    ;转外中断0


ORG 000BH


RETI    ;没有用定时器0中断,在此放一条RETI,万一 “不小心“产生了中断,也不会有太大的后果。


中断程序完成后,一定要执行一条RETI指令,执行这条指令后,CPU将会把堆栈中保存着的地址取出,送回PC,那么程序就会从主程序的中断处继续往下执行了。注意:CPU所做的保护工作是很有限的,只保护了一个地址,而其它的所有东西都不保护,所以如果你在主程序中用到了如A、PSW等,在中断程序中又要用它们,还要保证回到主程序后这里面的数据还是没执行中断以前的数据,就得自己保护起来。

返回列表