您好,欢迎访问三七文档
第五章中断在上一章的UART接收试验中,我们使用的是查询的方式来实现的,在查询接收期间CPU就只能等待是否有数据传输进来而不能做其他的事情,查询接收占据了CPU的全部可用时间,特别浪费CPU资源。如何把CPU从这种简单而又重复的事件中解脱出来,充分利用CPU的全部有效时间是一个值得深入考虑的问题。对于像UART这种异步发生的事件,现在的CPU一般会采用中断的方式进行处理。所谓中断,即打断CPU目前正在执行的程序而转向执行其他程序的一种CPU运行机制。如图5.1所示。程序A程序A程序B图5.1CPU中断CPU正在执行程序A,但是因为某些事件的发生使得CPU不得不暂时放弃目前的程序A而转向执行程序B,在B程序执行完成之后再重新回来执行程序A。这就是一个中断过程,其中程序A叫做被中断程序,而程序B叫做中断服务程序,引起中断的事件叫做中断源。芯片内部许多部件都可以作为中断源,比如UART,定时器等。LPC213X的中断系统模型如图5.2所示。CPUFIQ使能外设1中断外设i中断外设n中断向量地址寄存器VICVectAddr0VIC控制寄存器VICVectCntl0IRQSlot0向量地址寄存器VICVectAddr15VIC控制寄存器VICVectCntl15IRQSlot15中断使能寄存器VICIntEnable中断使能清零寄存器VICIntEnClearIRQ使能...图5.2LPC213X中断模型从图5.2可以看出,一个中断信号是否可以送到CPU出并让CPU是去处理主要取决于以下几个因素:1、外部设备是否产生了中断;2、中断向量控制器是否给外设分配了中断向量入口;3、FIQ、IRQ是否已经使能。与LPC213X的其他片内外设一样,VIC也是通过寄存器来控制的,VIC中所有的寄存器都为字寄存器,不支持字节和半字的读和写操作。中断的使用步骤如图5.3所示。中断源使能相关中断选择中断类型分配IRQ槽设置中断服务程序地址使能中断图5.3中断使用流程上一章中,我们学习了如何通过UART口来控制LED闪亮的次数,在这一章中我们将学习如何基于UART中断接收数据的方式来控制LED闪亮的速度。5.1使能中断源中断能产生中断的外设叫做中断源,要想使用中断,第一步就要启动中断源的中断使能。外设中断的启动一般都在外设的相关寄存器中设置,经过查询UART的寄存器中,可以找到其有一个中断使能寄存器UxIER。该寄存器的描述如表5.1所示。UxIER描述复位值0RBR中断使能。1:使能RDA中断;0:禁止RDA中断。01THRE中断使能。1:使能THRE中断;0:禁止THRE中断。02Rx线状态中断使能。1:禁止Rx线状态中断;0:禁止Rx线状态中断;该中断状态可从UxLSR[4:1]读出。07:3保留,用户软件不要向这些位写入1。未定义表5.1UxIER寄存器描述从寄存器内容描述中我们可以看到,UART共有两个基本中断和一个混合中断。两个基本中断分别是RBR中断和THRE中断。RBR中断即接收到有效数据中断,当UART接收到有效数据时发生该中断。THRE中断即发送缓冲区空中断,发送完成后产生的中断。还有一个线状态混合中断,对于这个混合中断的具体中断源可以通过UxLSR寄存器查询得到。本章我们将使用中断的方式从UART0接收数据,从UxIER寄存器的描述中可知,要想通过中断的方式从UART接收数据,要将RBR中断使能位置1,即执行以下的语句:U0IER=U0IER|0x01;5.2选择中断类型LPC213X的中断可以分成IRQ和FIQ两种,所谓FIQ,是快速中断请求(FIQ,FastInterruptreQuest)的缩写,而IRQ叫中断请求(InterruptreQuest),两者没有最大的区别在于处理的优先级不等,即当同时发生IRQ和FIQ时,优先响应FIQ,而后再响应IRQ。每一个中断源选择IRQ或者FIQ类型中断是通过中断选择寄存器(InterruptSelectRegister)来选择的,该寄存器记作VICIntSelect,该寄存器的每一位刚控制了一个中断源,各中断源的位置与中断源列表所示相同。向相应的位写入1,则对应的中断分配为FIQ中断,写入0,则为IRQ中断。如表5.2所示。位中断源复位值0WDT01ARM内核02ARM内核03ARM内核04定时器005定时器106UART007UART108PWM009I2C0010SPI0011SPI1(SSP)012PLL013RTC014外部中断0(EINT0)0位中断源复位值15外部中断1(EINT1)016外部中断2(EINT2)017外部中断3(EINT3)018A/D0019I2C1020BOD031:21保留0表5.2中断选择寄存器在本章中我们将UART0的接收中断设置成IRQ类型,查询中断选择寄存器表,我们需要执行一下的程序:VICIntSelect=VICIntSelect&(~(16));注意:快速中断请求(FIQ,FastInterruptreQuest)要求具有最高优先级,如果分配给FIQ的请求多于1个,VIC将中断请求“相或”后向ARM处理器产生FIQ信号。当只有一个中断被分配为FIQ时可实现最短的FIQ等待时间,因为FIQ服务程序只要简单地启动器件的处理就可以了,但如果分配给FIQ级的中断多于1个,FIQ服务程序需要读取FIQ状态寄存器来识别产生中断请求的FIQ中断源。5.3分配中断槽LPC213X的向量中断是通过中断槽(IRQSlot)的方式来实现的,所谓中断槽,就相当于了一个空的接口,这个接口可以连接很多外部设备,同时也可以进行一些属性的设置。LPC213X一共有16个IRQSlot,其中slot0具有最高优先级,而Slot15则为最低优先级。每一个中断槽有两个属性可以设置,分别是VIC控制器寄存器(VICVectCntlx),VIC控制寄存器总共有16个,分别为VICVectCntl0~VICVectCntl015,该寄存器控制的是该IRQSlot连接到哪一个外部设备中和是否使能该IRQSlot。注意:在VICVectCntl寄存器中可以禁止一个向量IRQslot,但不会禁止中断本身,该中断只是由原来的向量形式变为非向量形式。该系列的寄存器描述如表5.3所示。VICVectCntlx描述复位值4..0分配给此优先级向量IRQ中断的中断源编号05该位为1,使能当前优先级的向量IRQ中断。否则为禁止07..6保留未使用0表5.3向量中断控制寄存器如表5.3所示,其[4..0]位应该写入的是中断源编号。中断源,即是能产生中断的外设,在LPC213X中,中断源多达21个,每一个中断源都有一个中断源编号,用来相互区别,如表5.4所示。模块可能产生中断的原因编号WDT看门狗中断(WDINT)0ARM内核保留给软件中断1ARM内核EmbeddedICE,DbgCommRx2ARM内核EmbeddedICE,DbgCommTx3定时器0匹配0-3(MR0,MR1,MR2,MR3)捕获0-3(CR0,CR1,CR2,CR3)4定时器1匹配0-3(MR0,MR1,MR2,MR3)捕获0-3(CR0,CR1,CR2,CR3)5UART0Rx线状态(RLS)发送保持寄存器空(THRE)Rx数据可用(RDA)字符超时指示(CTI)6UART1Rx线状态(RLS)发送保持寄存器空(THRE)Rx数据可用(RDA)字符超时指示(CTI)7PWM0匹配0-6(MR0,MR1,MR2,MR3,MR4,MR5,MR6)8模块可能产生中断的原因编号I2C0SI(状态改变)9SPI0SPI中断标志(SPIF)模式错误(MODF)10SPI1(SSP)TxFIFO至少一半为空(TXRIS)RxFIFO至少一半为满(RXRIS)接收超时条件(RTRIS)接收溢出(RORRIS)11PLLPLL锁定(PLOCK)12RTC计数器增加(RTCCIF)报警(RTCALF)13外部中断外部中断0(EINT0)14外部中断1(EINT1)15外部中断2(EINT2)16外部中断3(EINT3)17A/D0A/D转换器018I2C1SI(状态改变)19BOD掉电检测20表5.4中断源与中断编号本章中,我们将UART0的接收中断分配到IRQSlot2中,查询向量中断控制寄存器,我们要执行一下的程序才能实现:VICVectCntl2=0x20|0x06;其中,VICVectCntl2是我们需要设定的IRQSlot2的向量中断控制寄存器;而0x02是用来VICVectCntl2的第5为设置成1,从使能IRQSlot2的中断;0x06是UART0的中断源编号,从中断源与中断源编号表中可以查询到。此外,每一个IRQSlot还有一个对应的向量地址寄存器,该寄存器保存的是该IRQSlot的中断服务程序的入口地址,即该中断服务的程序名。向量地址寄存器也总共有16个,分别是VICVectAddr0~VICVectAddr15。该系列寄存器的描述如表5.4所示。VICVectAddrx描述复位值[31..0]该向量中断的中断服务程序入口地址0表5.4向量地址寄存器在本章中,我们UART0的中断服务程序是UART0_RcvByte(),所以我们要在我们以及选定的IRQSlot2的向量地址寄存器中VICVectAddr2中写入我们的中断服务程序入口地址UART0_RcvByte(),需要执行下面的程序:VICVectAddr2=(unsignedint)UART0_RcvByte;注意:VICVectAddr2和VICVectCntl2必须成对出现,因为他们是属于同一个IRQSlot的;(unsignedint)UART0_RcvByte的(unsignedint)可以写也可以不写,从程序的健壮性考虑,最好写。如果一个中断被分类成了向量中断,则去中断服务程序的地址将从相应的向量地址寄存器中读取,对于其他没有设置成向量中断的,则从默认向量地址寄存器中读取中断服务程序的入口地址。该寄存器为:VICDefVectAddr,该寄存器描述如表5.5所示。VICDefVectAddr描述复位值[31..0]其他非向量中断的入口地址0表5.5默认向量地址寄存器5.4中断服务程序所谓中断服务程序,就是CPU被中断后转向执行的程序,实际上就是真正实现中断处理功能的程序。在ADS1.2开发环境中,对于处理程序有一定的格式要求。格式一般为:void__irq中断服务程序名(void){}上面的格式中,__irq是ADS1.2中中断服务程序的关键字,在编写中断服务程序的时候一定不可缺少。同时,作为中断服务程序,是没有输入参数也是没有返回值的,所以两个都是void。一般而言,中断服务程序的流程如图5.4所示。中断程序入口查询产生中断的原因中断处理中断源中断结束处理VIC中断结束处理退出中断服务程序图5.4中断服务程序对于ARM处理器而言,同一个外设一般会产生多种中断,所以在中断服务程序中必须首先要找出发生中断的具体原因,然后才根据不同的中断原因进行中断处理,同时因为产生中断发原因很多,在退出中断服务程序之前,必须要根据外设的要求进行中断源中断结束前的处理,比如清除某个寄存器某位或者复位某个寄存器等。在完成了中断源中断结束前处理后,还必须马上进行VIC中断结束处理,在LPC213X中,VIC中断结束处理就要复位VICVectAddr寄存器。本章中使用的UART接收中断处理程序流程如图5.5所示。中断程序入口复位VICVectAddr退出中断服务程序有未处理的中断?接收数据中断或者是超时中断?全部数据接收完?NNNYYY中断原因查询中断处理VIC中断退出处理图5.5UART0接收中断具体的实现程序如下所示:void__irqUART0_RcvByte(void){unsignedcharIIR;IIR=U0IIR;if((IIR&0x01)==0){IIR=IIR&0x0e;if((IIR==0x04)||(IIR==0x0c)){while(U0LSR
本文标题:第五章中断
链接地址:https://www.777doc.com/doc-2188920 .html