一旦把工作寄存器W腾空后,紧接着就应将状态寄存器STATUS的内容转移到W中。完成这一操作的指令也不能影响到STATUS寄存器内部原有的标志位,原因是STATUS寄存器的内容在此之前还没有安全地保护起来。经过仔细分析得知,PIC16系列
单片机的指令系统中有3条“MOV”传送指令。但是,只有1条“MOVF f,W”是以RAM单元为源寄存器,以W为目标寄存器的;而这条指令的操作过程又偏偏会影响“Z”标志位。因此,该指令就不能使用了,只好用1条既有高、低半字节交换功能又有传递功能的“SWAPFSTATUS,W”来勉强顶替(对应程序中第2条指令)。不过在此只利用它的传递功能,其交换功能带来的多余操作还得记下来,等到工作完成之后还得把它倒换
回来。
STATUS寄存器的内容已经保存到W中时,就可以大胆地将其清0了,以便把定义着STATUS_TEMP和PCLATH_TEMP的体0设置为当前体(对应程序中第3条指令)。经过以上几步特别需要谨慎的操作过后,就可以轻而易举地将寄存器STATUS和PCLATH的内容保存到各自的临时备份寄存器中了(对应程序中第4~6条指令)。
在单片机初始加电时,自动将PCLATH清0,以避免其内容出现随机值,也就是为了避免在以后的程序运行过程中CPU发生不可预料的跳转,而造成程序的“跑飞”。由此可见,寄存器PCLATH对于程序的安全运行是至关重要的,不可轻视。程序一旦进入服务程序后,PCLATH的当前值为何就无从考证,实际上就失去了对于PCLATH内容的知情权。只好像单片机初始上电那样将其清0,重新把它强行“拉入”知情范围(对应程序中第7条指令)。
PCLATH的内容在2种情况下会影响到程序的走向:第1种情况是当执行GOTO和CALL这2条跳转指令时,11位地址码来源于指令码中,决定程序存储器页面的(PC值的)最高2位,来源于PCLATH<4:3>,即这种情况下只有PCLATH的2位影响程序走向。单单就这一种情况而言,只要用户程序不超过第0页(或称页0)的2KB范围,对于程序员来说,PC值的最高2位可以忽略,因而PCLATH寄存器PCLATH<4:3>的2位也可以忽略。第2种情况是,以PCL为目标的算术运算、逻辑运算或传送操作指令(PIC16系列单片机的指令系统中具备14条这样的指令),在操作过程中,自动用PCLATH寄存器的低5位装载PC的高5位PC<12:8>,影响程序走向的PCLATH内容就多达5位。即使对于用户程序不超过(第0页范围内的)2KB的情况,也至少会有3位影响到程序的走向。对于程序员来说,PCLATH的内容就不可忽略,必须保护。
总而言之,对于寄存器PCLATH的保护和处理(对应程序中阴影标出的部分指令,即第5~9条)并不是什么情况下都是必需的,但是在编写
中断服务程序时,统一安排这些指令也没有任何坏处。只要主程序和中断服务程序中都不需要修改PCLATH寄存器的内容,就可以不保护它。具体地说,只有当同时满足以下2个条件时,阴影标出的部分指令(即第5~9条)才可以省略。
(1) 在主程序和中断服务程序中不都存在跨页跳转。例如:用户程序没有使用第0页2KB空间之外的程序存储器,或者用户程序虽然超出了2KB的范围,但是,在主程序和中断服务程序中没有同时用到GOTO或CALL指令,都能满足该条。
(2) 在主程序和中断服务程序中没有同时使用以PCL为目标的操作指令(比如查表)。
保护现场的操作次序与恢复现场的操作次序应该相反。程序中的第8~11条就是按照相反的顺序恢复寄存器PCLATH和 STATUS内容的。但是,不要忘记保护现场时采用“SWAPF STATUS,W”指令产生的多余的交换操作,在此只好再采用同样的方法将其交换回来(对应程序中第10条指令)。最后2条指令,将W_TEMP内容的高、低半字节交换了2遍,才被恢复到工作寄存器W中。如果只用1条传送指令“MOVF W_TEMP,W”又会产生1个新的问题:“MOVF W_TEMP,W”指令会影响“Z”标志位,会破坏此前已经被恢复的寄存器STATUS的内容,这是我们所不希望的,也是不能容忍的。因此,在程序中利用了2条不影响标志位的SWAP指令(即第12,13两条指令)。虽然麻烦一点,但可以使这个问题得到圆满的解决。