8098单片机原理介绍(续)

🏠 首页 《无线电》杂志 1992年 🔗 第9期 🔗 第24页 分类:无线电技术自学经验交流 🔗 陈尚品 🔗, 梁建国 🔗, 朱小华 🔗

四、中断系统

1.中断源:8098具有21个中断源,它们可分成9类,图12是8098中断系统的示意图。在8098之中,每一个中断源都有与之对应的中断向量单元,中断向量单元之中直接存放中断服务程序的入口,而不是转跳到中断服务程序的指令。8051这类芯片则是规定了各种中断入口,然后再在中断入口之中填入转跳到中断服务程序的指令。当8098响应了中断之后,程序就会自动跳到由中断向量规定的中断服务程序的入口,各中断与中断向量的对应关系如表1所示。

图2
图2 🔍原图 (758×592)

在9类中断中,TRAP这个软件中断是专为开发装置使用的,在一般情况下,使用者不要使用这个中断。但有些8098开发装置是允许使用软件中断的。

图3
图3 🔍原图 (747×946)

由图13可看出,对于一个中断向量单元地址可能对应了多个中断源,当中断发生时,如果要详细了解究竟是哪一个中断源发出的中断请求,可由软件来检测状态寄存器 (IOS0和IOS1)中的有关位来判别。8098中的一些中断源由哪些部件来使用,还可用状态控制器(IOC0和IOC1)来选择。

例:(1)EXTINT(外部中断)和ACH7(A/D转换通道7)合用一个中断向量单元,至于这个中断向量单元由哪一个中断源来使用,可由IOC1.1来选择。当IOC1.1为1时,由ACH7使用;当IOC1.1为0时,则由EXTINT使用。

(2)当发生串行口中断时,可通过检测串行发送中断标志寄存器中的RI(接收)和TI(发送)标志位,来判别是串行发送中断,还是串行接收中断。

(3)HSO命令寄存器中的第4位,可用来选择是否允许软件定时器中断,当该位为1时,就允许软件定时器中断,否则就禁止软件定时器中断。

2.在8098工作过程中,一个中断源发出的中断请求信号必须满足如下条件才能被响应:

(1)PSW9位必须置1,即已使用指令EI开放了中断;

(2)中断屏蔽寄存器(INT-MASK)对应中断的位应置1,即已允许某一个中断源中断;

(3)中断悬挂寄存器(INT-PENDING)对应的位应为1,悬挂寄存器中的位可由硬件置1或由软件设定为1;

(4)当前产生的中断优先级别高于其它中断的优先级。

CPU响应中断后,把中断悬挂寄存器相应的位清零,把PC值压入堆栈保护,并根据中断向量单元之中的内容,自动转到中断服务程序之中。这些工作不需要操作者干预,由CPU自动完成。

CPU响应一个中断后至少要执行一条指令,才可能响应另一个优先级更高的中断请求。通常在中断服务程序中的第一条指令是DI或PUSH,指令DI的作用是屏蔽所有的中断,PUSH的作用是将PSW(程序状态字)压入难栈,并将PSW清零,从而也禁止了中断。这样就能保证中断服务程序在正常执行中不被打断,当然如果希望在执行中断服务程序时,CPU能响应其他中断源发出的中断请求信号,可将屏蔽寄存器中相应的位置1后再执行一条EI指令(即开放了中断)。在中断服务程序的最后两条指令,通常是POPF和RET,POPF的作用是恢复PSW中的原内容,RET则是使中断时PC(程序计数器)的值送回到PC之中,也就是让程序返回到被打断之处继续执行。

3.中断悬挂寄存器(INT-PENDING)

当8098检测到某一中断源发中断请求信号时,就把中断悬挂寄存器中相应的位置1,当对应的中断信号被响应时,又立即将中断悬挂寄存器中相应的位清零。对中断悬挂寄存器可进行读写操作,通过检测中断悬挂寄存器内容,就可判定在指定时间内是否发生过中断请求。对该寄存器进行写操作,可在软件的控制下清除中断源发出的中断请求信号。也可将该寄存器中的各个位置1,即由软件来模拟某个中断源的中断请求。中断悬挂寄存器的地址是09H。

4.中断屏蔽寄存器(INT-MASK)

中断屏蔽寄存器的地址是08H,它是PSW的低8位,中断屏蔽寄存器与各中断源的对应关系与中断悬挂寄存器是完全相同的。通过软件置位或清零中断屏蔽寄存器中的某些位,可使得对应的中断被允许或被禁止(即开放或屏蔽对应的中断)。由于中断屏蔽寄存器是PSW的低8位,因此当采用指令PUSHF和POPF,来保护和恢复PSW中的内容时,中断屏蔽寄存器也同其地位一样得到保护和恢复。

5.开中断标志位I

开中断标志位I是程序状态字的PSW的第9位,它控制着整个中断系统的开放或关闭。使用指令EI(允许中断)可使I位置1;使用指令DI(禁止中断),可使I位清零。当PSW.9=0时,则关闭所有的中断;当PSW.9=1时,则将中断开放,坦CPU是否响应中断信号,还要由中断屏蔽寄存器来控制。中断开放时,CPU便按优先级别的高低响应中断;在中断关闭时,当中断源发出中断请求后,中断请求信号将保存在中断悬挂寄存器中,直到中断开放后,CPU才响应中断源在开中断之前发出的中断请求信号。保存在中断悬挂寄存器之中的中断请求信号,可由复位信号来清除,也可由软件来清除,否则中断请求信号将一直保存在中断悬挂寄存器之中。

6.中断优先级别

中断的优先级别在表1中已结出,当多个中断源同时发出中断请求信号时,中断优先编码器分析那些既已悬挂又被允许的所有中断信号,选择出一个优先级别最高的中断,然后由中断发生器按照对应的中断矢量单元之中的内容,强制使程序转移到相应的中断服务程序之中。

进入中断服务程序之后,8098的CPU并不象有的芯片那样自动关中断,8098在响应中断之后,仍然将中断开放。8098在进入中断服务程序后,至少要执行一条指令,才会响应比本级中断更高级别的中断请求。一般来说使用PUSH这条指令要好些,这是因为在执行PUSHDF之后,PSW的所有位都被清零,这样不但关闭了所有的中断(因为PSW.9被清零),而且清除了中断屏蔽寄存器中的所有位(因为中断屏蔽寄存器是PSW的低8位字节)。

如果希望使用多级中断,可在执行了指令PUSHP之后,再重新设置中断屏蔽寄存器中的内容,接着再用一条EI(开中断)指令将中断开放,这样就可在中断服务程序之中,又重新设定了哪些中断是允许的,哪些中断是不允许的,从而可构成任何一种所期望的中断服务系统。如果希望程序在中断服务程序执行完毕之后返回到原来被打断之处,在中断服务程序的最后两条指令可以是POPF(恢复PSW的原内容)和RET(返回)指令。当然也可在中断服务程序执行完之后,直接跳到程序别的地方,采用这种方式时,应注意栈指针的值,因为在进入中断服务程序时,堆栈加深2个字节,返回时又自动减少2个字节。

为了更好地了解中断优先级的改变,请看下面一个例子:假设在进入中断服务程序之中时,串行口中断优先级低于HSI数据有效中断,但高于其他一切中断,具体程序见实验程序1。

标号SIO-INT是串行口中断向量200CH中的数据,这也是串行口中断服务程序的入口地址,当串行口中断时,程序就直接跳到这个服务入口。在中断服务程序之中,第一条指令就是PUSHF,当它被执行之后,中断就被关闭了,从而保证了在任何情况下都能顺序执行LDB INT-MASK,#04H这条指令。LDB INT-MASK,#04H这条指令又重新允许HSI中断,也就是说在执行串行口中断服务程序的过程中,是允许HSI中断的,这时就可认为HSI中断优先于串行口中断。虽然8098在硬件上已经规定了中断优先级,但我们可按上述方法,建立起与硬件无关的中断软件的优先级,也就是说可重新定义各中断的优先级,这是8098的一个特点。在上述程序中EI这条指令使中断重新开放,这时如果出现HSI输入数据有效中断请求的话,它就立即会被响应。在中断服务程序的末尾,POPF这条指令恢复了PSW中原来的内容。由于8098从硬件上是不允许在执行完POPF之后立即响应中断请求的,故可保证在响应其他中断之前先执行RET这条指令。

7.中断响应时间:

从中断源发出中断请求信号到执行中断服务程序的第一条指令,需要一段响应时间,这个响应时间的长短与一些因素有关。如果一个中断请求信号离正在执行的这条指令结束还有4个状态周期仍未出现,那么CPU将在下一条指令执行完毕之后,才可能会响应这个中断。这是因为一条指令执行结束前的4个状态周期,CPU已经开始预取下一条指令的操作。从响应中断到按向量调用中断服务程序,共需要21个状态周期,如果堆栈设在外部RAM之中,那还要增加3个状态周期。这期间8098完成把程序计数器的内容压栈,取出中断向量并产生跳转。

不难算出,从中断源发出中断信号到开始执行中断服务程序中的第一条指令,最少也需要25(4+21)个状态周期。若正在执行的指令结束时,CPU没有响应中断,而这条指令又是执行时间花费最长的NORMAL(43个状态周期),那么最长的中断响应时间就为71(43+4+24)个状态周期。

还应当注意的一点就是,在执行完下列6条指令中的任何一条指令后,必须再执行一行指令,CPU才会响应中断:

(1)允许中断指令EI;(2)禁止中断指令DI;(3)标志入栈指令PUSHF;(4)标志出栈指令POPF;(5)实现带符号乘除的前缀(FE)指令;(6)软件中断指令TRAP。

8.中断优先级改变实例:

从表1可以看出EXTINT的优先级比HSI.0的高,但现在希望进入EXTINT服务程序中后,能允许HSI.0中断,即认为HSI.0的优先级高于EXTINT的优先级,具体程序见实验程序2。

执行实验程序2无中断发生时,程序在HERE处循环等待。如果有HSI.0中断发生则进入HSI.0的中断服务程序BS2。在进入HSI.0中断服务程序之后,已经将中断关闭,这时其他中断都不能打断HSI.0的中断服务程序。当程序处于HERE处等待时,发生了EXTINT中断,程序就进入EXTINT的中断服务程序BS1,进入BS1后,又允许HSI.0中断且开放中断,如果这时将HSI.0引脚对地短接一下,EXTINT的服务程序就会被HSI.0中断请求信号所打断,而程序则会优先去执行一次HSI.0中断服务程序。

五、定时器

1.8098共设有7个定时器,其中有3个硬件定时器(定时器T1,定时器T2,监督定时器)和4个软件定时器,它们都是16位的定时器。定时器T1主要是作为内部部件工作时的时间参考,定时器T2主要用作外部事件记数器,监督定时器用来监视8098的运行,一旦8098工作不正常,监督定时器将强行使8098复位。软件定时器使用起来比较灵活和方便,可直接用软件来对它们进行设置和启动。

2.定时器T1:定时器T1是8098芯片内部的实时时钟,它是一个16位的定时器,它的时钟脉冲来自8098的时钟信号发生电路,8098正常工作时,它一直循环计数,计数值从0000H~FFFFH循环。当定时器T1计满时,CPU便将IOS1.5置位,并同时发出一个中断请求信号。定时器T1是按每8个状态周期自动加1,当采用12MHz晶振时2μs自动加1,计满16位约需132ms。无法用软件使它停止或复位,只有使用硬件复位的方法才能使定时器T1清零。

定时器T1的计数值存放在0AH(低8位)和0BH(高8位)单元之中,它们分别是特殊功能寄存器TIMER1(LO)和TIMER1(HI)。CPU随时都可读取定时器T1之中的数值,但走时器T1只能按字读出,否则就会读出错误的结果。

3.定时器T2:定时器T2也是一个16位的定时器,它的计数脉冲来自引脚HSI.1,因此可认为它是一个外部事件计数器,当HSI.1引脚上发生正跳变或负跳变时,定时器T2计数加1,当定时器T2计数溢出时,CPU置位IOSI.4,并发出一个中断请求信号。

通过软件或硬件都可使定时器T2复位。定时器T2的计数值存入0CH(低8位)和0DH(高8位)单元之中,它们分别是特殊功能寄存器TIMER2(LO)和TIMER2(HI)。CPU随时也可读取定时器T2之中的数值,与定时器T1一样,定时器T2也只能按字读出。

定时器T2的功能可由输入输出状态控制器0(IOC0)来设定,当IOC0.7为1时,允许定时器T2对HSI.1引脚的跳变信号进行计数。为了保证定时器T2每计数一次都对CAM之中的事件时间值进行检查一遍,要求HSI引脚发生跳变的最小间隔应大于8个状态周期。

图4
图4 🔍原图 (656×482)

定时器T2可由软件清零,图14是定时器的时钟源和复位选择方式。从图可以看出,对于8098定时器T2的时钟源,只能使用HSI.1作为外部时钟,定时器T2没有选择内部时钟的能力。定时器T2的复位途径有4种:

(1)硬件复位,当8098的复位信号有效时,定时器T2就被复位;

(2)将输入输出状态控制器0的第一位(IOC0.1)置1;

(3)触发HS0的PEH通道,即将HSO—COMMAND寄存器中的1~3位全部置1(1110B);

(4)将IOC0.3和IOC0.5置1,可用HSI.0引脚来复位定时器T2。

4.定时器T1和定时器T2的中断:定时器T1和定时器T2都能触发定时器溢出中断和置位定时器溢出标志(IOS1.4或IOS1.5)。是否允许定时器T1或定时器T2中断,可由输入输出控制器(IOC1.2和IOC1.3)来控制,当IOC1.2=1时,允许定时器T1中断;当IOC1.3=1时,允许定时器T2中断。

由于定时器T1和定时器T2共用一个中断向量地址(2000H),当同时允许定时器T1和定时器T2中断时,在进入中断服务程序后,还应检查IOSI中的定时器T1和定时器T2的溢出标志(IOS1.4和IOS1.5).来判别是哪一个定时器发出了中断请求信号。关于对IOSI检查应注意的问题,前面我们已经详细讲过。

5.监督定时器:监督定时器(WDT,俗称看门狗电路)提供了一种使程序从混乱中摆脱出来的方法。当系统由于干扰或其他原因使软件运行混乱时,监督定时器能使系统复位。监督定时器是由一个8位的定时器和一个8位的预置量计数器组成。由于预置量计数器的计数不与内部时钟同步,故当监督定时器被清零之后,大约经过65280~65535个状态周期会溢出。当监督定时器溢出时,它将8098的RESET端拉低,并保持至少2个状态周期,这样使8098复位。

启动监督定时器的方法是,先将‘1EH’写入到特殊寄存器0AH之中,接着再将‘0E1H’写入到0AH之中,清监督定时器的方法与启动监督定时器的方法是一样的。一旦启动监督定时器,就必须在它溢出之前清一次,没有别的办法使监督定时器停下来。当采用12MHz晶振时,清监督定时器之后,大约16ms它就会溢出。如果不想使用监督定时器就不要启动监督定时器。

外来干扰和内部电路的噪声都可能引起地址总线上的数据混乱或程序计数状态的改变,而导致程序运行出错。为了提高系统的抗干扰能力和迅速摆脱失控状态,除了使用监督定时器之外,还应在不用的ROM空间全部填入RST指令,也就是将不用的空单元全部填入0FFH,这样一旦程序失控,而从ROM的空单元取指令的话,应用系统只能执行RST指令,从而返回程序的起站地址。此外还可在8098的数据总线上接入8个上接电阻,当系统失误从未存入程序的存储空间取指令的话,由于这些上接电阻的作用,使得8098读入的指令为RST(0FFH),从而使系统复位。

6.软件定时器,软件定时已在HSO部件中介绍过。

7.定时器应用举例:

(1)用定时器T1测量脉冲宽度,将被测信号送到P0.7引脚上,脉冲的上跳时刻送到40H中,下跳时刻送到42H中,定时器T1的溢出次数送到44H中,由于HH-98采用6MHz晶振,每8个状态周期的时间为4μs,脉冲宽度可由下式算出:T=[(42H)-(40H)+(44H)×216]×4(μs)

具体程序见实验程序3

(2)利用定时器T2作计数器用,将计数信号送到HSI.l引脚,利用PO.7来禁止和允许计数,计数值放在40H中。具体程序见程序4。(朱小华 陈尚品 梁建国)

实验程序1:

SIO-INT:PUSHF ;保存PSW的内容

LDB INT-MASK, # 04H;只允许HSI中断

EI ;开中断

POPF ;恢复PSW的内容

RET ;返回主程序

实验程序2:

ORG 2008H

DCW BS2;将HSI.0的中断服务入口送2008H中

ORG

DCW BS1;将EXT1NT的中断服务入口送200EH中

ORG 2080H

TEST42:LD SP, # 0C0H;将栈指针设定为 0C0H

LDB I0C1,#00H;将P2.2设置成外部中断口

CLRB INT-PENDING;清悬挂寄存器

LDB INT——MASK,# 90H;允许 EXT1NT和HSI.0中断

EI;开中断

HERE:SJMP HERE;等待中断

ORG 2200H;EXTINT中断入口

BS1: PUSHF;关中断并清INT-MASK

LDB INT-MASK, #10H;允许HSI.0中断

EI;开中断

NOP;模拟EXTINT中断服务程序

CLR AX

INC AX

INC AX

NOP;模拟EXTINT中断服务程序结束

POPF

ORG 2300H;HSI.0中断入口

BS2: PUSHF;关中断并清INT-MASK

NOP;模拟HSI.0中断服务程序

CLR BX

INC BX

INC BX

NOP;模拟HSI.0中断服务程序结束

POPF

RET

实验程序3:

ORG 2000H

DCW INT-T1;将中断入口送定走时器向量单元

ORG 2080H

TEST51:LD SP,#00C0H;设置栈指针

DI;关中断

LDB INT-MASK, # 0AH;允许定时器中断

PHI: JBC P0.7,PHI等待P0.7引脚电平上升

LD 40H,T1;将上跳时刻送40H

CLR 44H;清溢出次数寄存器

LDB IOC1,#04H;允许定时器T1中断

CLRB INT-PENDING;清悬挂寄存器

EI;开中断

PLO: JBS P0.7,PLO;等待P0.7引脚电平下降

LD 42H,T1;将下跳时刻送42H

DI;关中断

SJMP,PHI;跳到PHI进行一次测量

INT-T1:INC 44H;累计定时器T1的溢出次数

实验程序4:

ORG 2080H

TEST52:LD SP,#00C0H;设置栈指针

LDB IOC0,# 86H;将HSI.1作时钟源并复位T2

LD 40H,00H;清40H

COUNT: LD 40H,T2;将定时器T2的内客送40H

JBC P0.7,COUNT;若P0.7为低则允许计数

HERE: JBS P0.7,HERE;若P0.7为高则禁止计数

SJMP COUNT;循环计数

(朱小华 陈尚品 梁建国)

图1
图1 🔍原图 (956×844)