中断,顾名思义就是停止现在正在做的事情,去做其他的事情。就像你在上班,这时来了个电话,你就要停下手中的活,去接电话。而要我们暂时停下手中的活的电话就叫做中断源。可以说是中断让单片机的工作变得丰富且更有条理,就像生活中这个电话可能是约会奥。
一、简介
51的中断系统如下图所示:
从图中可以看出:51有5个中断源,INT0(外部中断0),IF0(定时器0),INT(外部中断1),IF1(定时器1),TI/RI(串行中断)。
每个中断源都有一个控制开关。开关打开,即使中断来了也不去响应,就像我们可以不去理开始说的那个电话。所有的中断源又由一个总开关统一控制,就像公司有很多部电话,但是交换机电源关掉了,所有的电话就都不会响了。
所有的中断源又按重要程度分了优先级(执行的先后顺序),还是讨厌的电话,两部摆在面前,一个是客户的,一个是哥们的。当然了,先接客户的。
另外中断又可以分为可屏蔽中断和不可屏蔽中断,很容易理解,就像51的所有中断,都带有控制是否接通的开关,这就是可以屏蔽的,叫做可屏蔽中断。当然还有开关没有办法控制的中断源,这个叫做不可屏蔽中断。
二、中断的作用或者特征
中断到底能有什么作用呢?众所周之,我们只有一个脑袋,两只手,不会分身术,所以同一个时刻只能做一件事情,当然孙悟空和哪吒除外。单片机的CPU也一样,程序在正常情况下只能顺序执行,但是有些事情你不会预知它什么时候会发生,比如我按了下按键,单片机当然可以一直都在查看你是否按下了按键,然后做相应的处理,但是如果CPU一直都在查看按键的状态,但是你半天都不按一个按键,那好了,它大部分的时间都在做无用功,这样做事可以,但是效率很低,还有一个很难处理的问题就是,如果我们的程序很庞大(或者中间有较长时间的延时),那么程序每循环一圈的时间就会很长,有个情况就是你按下了按键,但是CPU那时没有在查询按键状态,那么这就没办法相应了。就像我们不可能派个人去客户那里一直呆着,有问题了,他就回来报告下,然后在去那里“蹲点”。
有个中断就不一样了,安个电话嘛!有事call me。万事OK。更近一点说,一个公司会有很多客户,不同方面的(供应商,代理商,直接客户==),相应的就会有不同的电话(技术支持,代理咨询==)。而这些不同的客户的电话的接听也是可以有先后顺序的,供应商的电话当然可以放在代理商的后面,毕竟他们是卖产品给我们的,我们赚钱还是靠卖产品滴。这就道出了一个优先级处理的问题。
中断还有一个很重要的特征就是嵌套,这个需要单独说明。
由此可以得出一个结论:中断的存在解决了一个资源共享的问题,就是很多的事件不论什么时候发生,都可以得到响应。很多事情同时发生的时候,可以按照重要性分别对待。
三、中断到底做了什么?
还是那个电话的例子,如果你正在整理资料,电话响了,你会在正整理的资料上做个记号,然后去接电话,电话接完了,你会找到之前做到记号,然后再接着整理。CPU执行中断操作的过程就像这个一样:
单片机CPU检测中断发生的时候,会保存断点(此时CPU执行的所有的寄存器的值)也叫现场保护,然后在跳转到中断服务程序,执行完了之后。会取出保存的断点,继续执行原来的程序。如果在书写汇编程序的时候,需要手动编写断点保存和恢复的程序,(push和pop指令);而如果使用C编写程序,则需要在中断服务程序上加特殊的关键字,编译器在编译的时候就会自动的做断点保存和恢复的操作。(比如keil里使用interrupt 关键字)。
MCS-51CPU在每一个机器周期顺序检查每一个中断源,在机器周期的S6按优先级处理所有被激活的中断请求,此时,如果CPU没有正在处理更高或相同优先级的中断,或者现在的机器周期不是所执行指令的最后一个机器周期,或者CPU不是正在执行RETI指令或访问IE和IP的指令(因为按MCS-51中断系统的特性规定,在执行完这些指令之后,还要在继续执行一条指令,才会响应中断),CPU在下一个机器周期响应激活了的最高级中断请求。
中断响应的主要内容就是由硬件自动生成一条长调用LCALL addr16指令,这里的addr16就是程序存储器中相应的中断区入口地址,这些中断源的服务程序入口地址如下:
表5 | |||||||||
中断源 | 入口地址 | ||||||||
外中断0 | 0003H | ||||||||
定时/计数器0 | 000BH | ||||||||
外中断1 | 0013H | ||||||||
定时/计数器0 | 001BH | ||||||||
串行口中断 | 0023H |
生成LCALL指令后,CPU紧跟着便执行之.首先将PC(程序计数器)的内容压入堆栈保护断点,然后把中断入口地址赋予PC,CPU便按新的PC地址(即中断服务程序入口地址)执行程序。 值得一提的是,各中断区只有8个单元,一般情况下(除非中断程序非常简单),都不可能安装下一个完整的中断服务程序。因此,通常是在这些入口地址区放置一条无条件转移指令,使程序按转移的实际地址去执行真正的中断服务程序。 |
四、中断嵌套
51有两级中断,就是说中断是有优先级,如果两个中断同时到达,那么一定要先响应优先级比较高的那个中断,你再郁闷也不行。当然更郁闷的是如果中断在执行过程中,如果有高优先级的中断来了,也要去响应高优先级的中断。这就是中断的嵌套
中断嵌套和中断优先级有关,简单的说就是中断服务程序执行的时候又来了中断,它中断了之前正在执行的中断。很拗口的话,画个图说明下吧:
五、中断有关寄存器:
1.TCON
TCON 寄存器的每一位都控制一个中断源,它们的对应关系如下:
TF0 ,TF1:定时器中断的控制位。
IE1:外部边沿触发中断1请求标志,其功能和操作类似于TF0。
IT1:外部中断1类型控制位,通过软件设置或清楚,用于控制外中断的触发信号类型。IT1=1,边沿触发。IT=0是电平触发。
IT1:外部中断1类型控制位,通过软件设置或清楚,用于控制外中断的触发信号类型。IT1=1,边沿触发。IT=0是电平触发。
IT1:外部中断1类型控制位,通过软件设置或清楚,用于控制外中断的触发信号类型。IT1=1,边沿触发。IT=0是电平触发。
2.SCON
SCON是串行口中断控制器,只有低2位是有意义的,其他位保留:
TI:MCS-51串行口的发送中断标志,在串行口以方式0发送时,每当发送完8位数据,由硬件置位。如果以方式1、方式2或方式3发送时,在发送停止位的开始时TI被置1,TI=1表示串行发送器正向CPU发出中断请求,向串行口的数据缓冲器SBUF写入一个数据后就立即启动发送器继续发送。但是CPU响应中断请求后,转向执行中断服务程序时,并不清零TI,TI必须由用户的中断服务程序清“0”,即中断服务程序必须有TI=0;(“CLR TI”或“ANL SCON, #0FDH”等指令)来清零TI。
RI:串行口接收中断标志.若串行口接收器允许接收,并以方式0工作,每当接收到8位数据时,RI被置1,若以方式1、2、3方式工作,当接收到半个停止位时,TI被置1,当串行口一方式2或3方式工作,且当SM2=1时,仅当接收到第9位数据RB8为1后,同时还要在接收到半个停止位时,RI被置1。RI为1表示串行口接收器正向CPU申请中断。同样RI标志必须由用户的软件清“0”。
3.IE
IE叫做中断控制寄存器,51所有中断的开启屏蔽都是由它来控制,它的各位的情况如下:
EA:中断总控制位,也就是中断的总开关,在第一个图中可以很明确的看到。EA=1,CPU开放中断。EA=0,CPU禁止所有中断。
ES:串行口中断控制位,ES=1允许串行口中断,ES=0,屏蔽串行口中断。
ETx:定时/计数器Tx中断控制位。ETx=1,允许Tx中断,ETx=0,禁止Tx中断。(其中x=0.1)
EXx:外中断1中断控制位,EXx=1,允许外中断x中断,EXx=0,禁止外中断x中断。(其中x=0.1)
4.IP
表4 | |||||||||
IP | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
- | - | - | PS | PT1 | PX1 | PT0 | PX0 | ||
位地址 | | | | BCH | BBH | BAH | B9H | B8H |
IP叫做中断优先级控制寄存器,其中的D0到D4的5位对应于5个优先级,对应次序如下:
PS:串行口中断口优先级控制位,PS=1,串行口中断声明为高优先级中断,PS=0,串行口定义为低优先级中断。
PTx:定时器1优先级控制位。PTx=1,声明定时器x为高优先级中断,PTx=0定义定时器x为低优先级中断。(其中x=0,1)
PXx:外中断1优先级控制位。PTx=1,声明外中断x为高优先级中断,PXx=0定义外中断x为低优先级中断。(其中x=0,1)
六、中断实例: