我个人对PIC教程的一段晦涩文字的理解

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

应该肯定你的钻研精神。

书的作者可能对中断过程理解有误。如果说要发生文中“读-修改-写”的情况,唯一的机会是在图中②的位置,但PIC单片机在这个指令周期之内不执行任何指令,只是一个空操作的延时,所以书中写的情况是不可能发生的。<br />实际上,读-修改-写的情况在许多其它种类单片机中都会出现,一般都是发生在对端口的操作过程中,由于端口外部电压的不确定性,会导致读取的数据与原先写入的数据不符从而误操作。
systemchip 发表于 2007-9-19 09:32 | 显示全部楼层

:

还有一种情况应该注意:<br />&nbsp;&nbsp;&nbsp;即当我们执行BCF&nbsp;INTCON,GIE用于禁止全局中断的时候,当这条指令执行过程中某个中断发生,因为这个中断发生的时候,GIE位还未被请0,而当这条指令执行完后,将立即响应中断,当中断完成返回时候(执行&nbsp;RETFIE),GIE位将自动被置一,这样导致的结果将是GIE期望被禁止而实际并没有被禁止。所以可以采取下面措施:<br /><br />here:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bcf&nbsp;INTCON,GIE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;btfsc&nbsp;INTCON,GIE<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto&nbsp;&nbsp;here<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.....<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;....
yewuyi 发表于 2007-9-19 09:56 | 显示全部楼层

关于LS提到的那个问题

好象已经讨论了很多次,应该也是错误。<br /><br /><br />当时还有人从PICC生成的代码中看,PICC也并没有做类似处理。<br /><br />张明峰先生和MARTIN过去都曾就此问题做过论述,**中,似乎不需要做此处理。
martin 发表于 2007-9-19 10:11 | 显示全部楼层

楼上说的情况是历史了

楼上说的是PIC16C7X时代的问题了,现在新出的Flash的PIC都不需要做这个冗余的操作。在执行bcf&nbsp;INTCON,GIE这条指令是,如果发生中断,系统架构会在执行该指令周期的Q4把GIE清零,而中断系统是固定的3个指令周期的延时,中断响应与否取决于在这个延时期间对GIE位的判断。有先后之分,所以这种情况绝对不会出现。不要为了些古老的资料而误导了自己的思路。
 楼主| huangleche 发表于 2007-9-19 16:52 | 显示全部楼层

n+1对应的指令

还有一个问题,就是设XX对应的是中断标志位,PC=n的时候取BSF&nbsp;INTCON,XX指令,同时发生int中断,在前一个n+1的时候BSF&nbsp;INTCON,XX&nbsp;被执行,不知大家注意过没,在于此同时还取了一条指令,根据时序图是PC=n+1对应的指令,那这条n+1对应的指令是不是还是BSF&nbsp;INTCON,XX&nbsp;呢?恳请各位大虾指教
 楼主| huangleche 发表于 2007-9-19 17:10 | 显示全部楼层

接上面所述

接上面所述,如果n+1对应的指令是BSF&nbsp;INTCON,XX,则在进入XX中断之后的n+2的周期BSF&nbsp;INTCON,XX还会被执行一边,在这时MCU还是不是依旧会再响应XX中断一边呢?
yewuyi 发表于 2007-9-19 22:15 | 显示全部楼层

bcf INTCON,GIE就可以,不需要考虑

  
 楼主| huangleche 发表于 2007-9-19 22:32 | 显示全部楼层

看起来会进入死循环

不知各位大虾是否看出我上面的有个说法有点疑问的:<br />设PC=n的时候取BSF&nbsp;INTCON,XX指令,同时发生int中断,在n+1的时候BSF&nbsp;INTCON,XX&nbsp;被执行,而此时按时序表看,GIE还是等于1,接着进入了XX对应的中断,XX对应的中断结束后再返回继续执行int中断,所以中断会被执行两次。前提是XX对应的是中断标志位,而不是原文所说的中断允许位。<br /><br />在前一个n+1的时候BSF&nbsp;INTCON,XX&nbsp;被执行,不知大家注意过没,在于此同时还取了一条指令,根据时序图是PC=n+1对应的指令,那这条n+1对应的指令是不是还是BSF&nbsp;INTCON,XX&nbsp;呢?如果是BSF&nbsp;INTCON,XX就不是我上面所说的中断会被执行两次那么简单了,看起来会进入死循环,恳请各位大虾指教<br />
xieyuanbin 发表于 2007-9-20 07:04 | 显示全部楼层

楼主的问题惊动了不少人啊。

MARTIN老版主也出来了。SYSTEMCHIP也是一位重量级人物呢。<br />对于楼主的问题解答如下:<br />“设PC=n的时候取BSF&nbsp;INTCON,XX指令,同时发生int中断,在n+1的时候BSF&nbsp;INTCON,XX&nbsp;被执行,而此时按时序表看,GIE还是等于1,接着进入了XX对应的中断,XX对应的中断结束后再返回继续执行int中断,所以中断会被执行两次。前提是XX对应的是中断标志位,而不是原文所说的中断允许位。”<br />这里如果XX中断允许位没开,当然不会进入中断,而且不管如何,PIC还是有中断优先级,也有个先来后到的时序,所以此时仍然进入INT中断,而XX中断会在INT中断之后,执行了BSF&nbsp;INTCON,XX指令的下一条指令之后执行。<br /><br />“在前一个n+1的时候BSF&nbsp;INTCON,XX&nbsp;被执行,不知大家注意过没,在于此同时还取了一条指令,根据时序图是PC=n+1对应的指令,那这条n+1对应的指令是不是还是BSF&nbsp;INTCON,XX&nbsp;呢?如果是BSF&nbsp;INTCON,XX就不是我上面所说的中断会被执行两次那么简单了,看起来会进入死循环,恳请各位大虾指教”<br />PC=N+1对应的指令是BSF&nbsp;INTCON,XX后面的一条指令,进入中断前压栈的就是这条指令的地址。所以不会出现死循环。<br />
 楼主| huangleche 发表于 2007-9-20 19:45 | 显示全部楼层

PIC有硬件检测中断谁先来谁先响应??

&nbsp;&nbsp;&nbsp;&nbsp;LS说:“PIC还是有中断优先级,也有个先来后到的时序”不是吧,我看《PIC单片机入门与实战》里P40说的清清楚楚“PIC单片机的中断入口只有一个,故对中断优先级的控制也由编程人员通过软件来实现。”即由软件编写程序来实现谁先检测谁中断的原则,在后面一段书中也说:“如果现在正在处理低优先级的中断,就算有高优先级的中断发生,也必须等到低优先中断处理完毕后才相应”但书中有一个前提即:“在响应任何中断请求时,PIC单片机会自动把全局中断使能位(INTCON的第7位)清除。这样其他中断请求就暂时不被响应”。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;然而我不知道LS注意了时序图没,我所说的BSF&nbsp;INTCON,XX(当然XX是指某中断的标志位)被执行是在GIE被硬件清0之前发生的,我要问的是,此后是继续后一个n+1周期呢?还是会因XX标志位的置1而重新开始中断过程??<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;换而言之就是,PIC单片机在发生INT中断后GIE被硬件清0前的时刻,别的中断标志位被置1,CPU是不是会响应那个中断标志位被置1的中断??PIC单片机有没有硬件检测中断谁先来谁先响应的功能(除GIE被硬件自动清0外)??
yewuyi 发表于 2007-9-20 21:42 | 显示全部楼层

优先级问题见数据手册

16系列没有优先级,其余问题见以上回答
xieyuanbin 发表于 2007-9-21 08:45 | 显示全部楼层

中断优先在硬件上还是有一些区分。

但在软件处理上没什么区别。因为不管如何,进入中断后还是要软件来判断中断标志。<br />楼主有些钻牛角尖了,险些被你弄晕。<br />&nbsp;“换而言之就是,PIC单片机在发生INT中断后GIE被硬件清0前的时刻,别的中断标志位被置1,CPU是不是会响应那个中断标志位被置1的中断??PIC单片机有没有硬件检测中断谁先来谁先响应的功能(除GIE被硬件自动清0外)??”<br />像这样的情况,当进入中断时,如果那个XX中断发生,中断标志一样会被置1,如果你的软件去处理,就是响应了。换句话说,即使你xx中断允许位没开,相应的中断标志在中断条件符合时也一样会置1,这样的情况常常用在普通程序中判断一个工作是否完成,比如AD转换等。而此时如果你在中断处理中判断了这个标志,程序也一样会去处理这个中断,这完全取决于你的程序。
 楼主| huangleche 发表于 2007-9-23 00:04 | 显示全部楼层

彻底搞明白了

对不起,是我把PC的内容和指令存储的程序存储器地址搞混了,所以思维发生混乱,所以也在上面一张图中发生了个错误,在此修正一下,压栈的该是n+1,而不是上面那些图中的n+2<br />
 楼主| huangleche 发表于 2007-9-23 00:12 | 显示全部楼层

谢谢版主的耐心

另外楼上的楼上说法是正确的,谢谢版主的耐心回应,谢谢<br />&nbsp;&nbsp;&nbsp;&nbsp;当进入中断时,如果那个XX中断发生,中断标志一样会被置1,如果你的软件去处理,就是响应了。换句话说,即使你xx中断允许位没开,相应的中断标志在中断条件符合时也一样会置1,这样的情况常常用在普通程序中判断一个工作是否完成,比如AD转换等。而此时如果你在中断处理中判断了这个标志,程序也一样会去处理这个中断,这完全取决于你的程序。我也将这种情况的时序图整理了一下,画了出来,不知道对不对,请各位大大指教<br />
兰天白云 发表于 2007-9-25 14:39 | 显示全部楼层

本人以前也有LZ的担心,但又无法验证

最后搞了个歪招<br />在BSF&nbsp;INTCON,XX&nbsp;之前先清除对应的标志位,不过这招对TO特别没用<br /><br />1:清除对应的标志位<br />2:BCF&nbsp;INTCON,GIE&nbsp;<br />3:BSF&nbsp;INTCON,XX&nbsp;<br />4:BSF&nbsp;INTCON,GIE&nbsp;<br /><br />后来觉得这样也不好,更改设计,先允许对应中断,最后再BSF&nbsp;INTCON,GIE&nbsp;<br />而且再整个程序中就只有这么一句置位GIE的指令
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

16

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部