以下是原文(来源于《PIC单片机实用教程-基础篇(第2版)》P246(19)段文字或《PIC单片机原理》P115(19)段文字): (19) 当CPU正在执行一条对INTCON寄存器进行“读-修改-写”操作的指令时(如 BSF INTCON等),如果恰好发生了中断请求,则中断服务程序会被执行两次。这是因为当中断请求发生后INTCON寄存器中的GIE位会被硬件自动清0(屏蔽所有中断),并且程序转入中断例程入口(0004H)。当GIE被清0后,如果这时正好CPU在执行一条对INTCON读-修改-写的指令,则GIE位还会被写回操作重新置1,这样会造成CPU两次进入中断服务程序。解决的方法是: 如果在程序中需对INTCON的某一中断允许位进行修改,则应事先置GIE=0,修改完成后再恢复GIE=1。程序如下: BCF INTCON,GIE BSF INTCON,XX BSF INTCON,GIE
该段解释晦涩难懂,我的理解是: 设XX对应的是中断标志位,且PC=n的时候取BSF INTCON,XX指令,同时发生int中断,在PC=n+1的时候BSF INTCON,XX 被执行,而此时按时序表看,GIE还是等于1,所以在未完全进入int引起的中断时进入了XX置1引起的中断,至于在置1引起的中断程序中具体响应int还是XX中断,则由中断程序中程序员编写的中断源查询代码段来决定。 若在中断程序中把INTIF清0,则XX置1引起的中断程序结束后返回继续执行主程序;否则将再次进入INTIF=1引起的中断,因为在中断返回执行RETFIE时会将GIE置1。同理在中断程序中把XXIF清0,则XX置1引起的中断程序结束后返回继续执行主程序;否则将再次进入XXIF=1引起的中断。当然以上这整段描述是发生在总前提XX对应的是XX中断标志位,而不是原文所说的中断允许位的情况下。 若XX是原文所说的中断允许位(除GIE外的),则应该是PC=n的时候取BSF INTCON,XX指令,同时发生int中断,在PC=n+1的时候BSF INTCON,XX 被执行,接着继续执行原来的int中断,中断并不会被执行两次。因为根据时序图可知,修改-写即执行BSF INTCON,XX指令时是在前面一个PC=n+1的指令周期,而GIE清0却是在后面一个PC=n+1的指令周期(注意时序图中有两个PC=n+1的指令周期) 另外原文中指:“当GIE被清0后,如果这时正好CPU在执行一条对INTCON读-修改-写的指令,则GIE位还会被写回操作重新置1,这样会造成CPU两次进入中断服务程序。”根据时序图可知,修改-写即执行BSF INTCON,XX指令时是在前面一个PC=n+1的指令周期,而GIE清0却是在后面一个PC=n+1的指令周期(注意时序图中有两个PC=n+1的指令周期),且后面一个PC=n+1的指令周期并不执行任何指令,因此得出结论“当GIE被清0后,如果这时正好CPU在执行一条对INTCON读-修改-写的指令,则GIE位并不会被写回操作重新置1”所以原文所述并不正确。
另外最后说明一下下面一张图中 压入堆栈的应是n+1,不是图中的n+2,还有图中XX是某中断标志位应改为XX是某中断允许位,因为下面这张图的本意是解释“当GIE被清0后,如果这时正好CPU在执行一条对INTCON读-修改-写的指令,则GIE位并不会被写回操作重新置1”的 |