千芯科技网站

千芯科技服务与支持 >> 产品应用支持 >> 灵活使用PIC16C57的PROGRAM MEMORY

灵活使用PIC16C57的PROGRAM MEMORY

当您使用Microchip公司的PIC16C57在设计程序时,是否被它的PROGRAM MEMORY需分PAGE使用,而PAGE之设定又影响到goto、call、addwf、movwf 2四个指令之执行结果而困扰不已呢?以下心得与大家分享。 PIC16C57 之PROGRAM MEMORY共有2 K words,分为四个PAGE,每个PAGE有512个words;goto、call、addwf 2、movwf 2四个指令之执行,会改变PROGRAM COUNTER内容,其结果也受STATUS WORD REGISTER f3之bit 6, 5的影响,如图(一)所示;改变STATUS WORD REGISTER之bit 6, 5以下一律以AGE(的)控制称呼。 除此之外,每个PAGE分为前半部及后半部,call、addwf 2、movwf 2三个指令执行结果只会跳到某一PAGE内的前半部,因为这三个指令执行后会使PROGRAM COUNTER的bit 8变为0,而goto指令则不受限制,可跳到一个PAGE之前、后半部。 PROGRAM MEMORY 地址7FF是reset后第一个被执行的指令,正常情况下放入goto指令,而且STATUS WORD REGISTER bit 6, 5在 reset后全变为0,所以这个goto指令会使程序跳到PAGE 0去执行。至于要goto到何处?我们先以main 的label来代表,下文再继续讨论。 结构化的程序撰写是由主程序呼叫许多子程序组成的,为了能善用这四个PAGE,又不要让程序在呼叫子程序时或做goto之前也要同时注意PAGE的设定值,我对PAGE 0做以下安排:PAGE 0的前半部先存放所有的第一阶(即主程序直接呼叫的)子程序,接下来才存放主程序,上一段所提及的label — main 就是安排在这个地方;整段主程序只能放在PAGE 0内,否则分置于两个PAGE内的goto指令前需有不同的PAGE控制,此举不但麻烦又易出错,尤其是尚在发展更改中的程序,更难掌握。 当上述的第一阶子程序太大或太多,以致无法全部放入PAGE 0的前半部时,或是会造成主程序分跨于PAGE 0与PAGE 1时,就要将部分子程序的身体移到别的PAGE中,但头仍需保留在PAGE 0的前半部,头是个重要的媒介,其任务就是要把子程序导引到正确的PAGE上执行;而被移走的子程序其尾(retlw之前)需加上指令,把PAGE的控制转回PAGE 0;如此安排,主程序就不用管它所呼叫的子程序主体究竟位于哪个PAGE上了。请参考如下范例: LIST p=16c57 ;**************************************************************** ORG 0 ;page 0 前半部 ;**************************************************************** init: ; 子程序的头 bsf STATUS,5 ;page selector point to page 1 goto sub1_1 ; ------------------------------------------------------------------------------------------------ tx: ; 子程序的头 bsf STATUS,6 ;page selector point to page 2 goto sub2_1 ; ------------------------------------------------------------------------------------------------ rx: ; 子程序的头 bsf STATUS,6 ;page selector point to page 2 goto sub2_2 ; ------------------------------------------------------------------------------------------------ rd_eeprom: ; 子程序的头 bsf STATUS,5 ;page selector point to page 3 bsf STATUS,6 goto sub3_1 ; ------------------------------------------------------------------------------------------------ ……………… ; 其它的第一阶副程的头 ;========================================================= main: ; 主程序 ……………… call init ; 直接呼叫,不必管PAGE问题 ……………… call rd_eeprom ; 直接呼叫,不必管PAGE问题 ……………… call tx ; 直接呼叫,不必管PAGE问题 ……………… call rx ; 直接呼叫,不必管PAGE问题 ……………… ;**************************************************************** ORG 0x200 ;page 1 前半部 ; 此前半部可用以放置第二阶子程序,而且是仅接受PAGE 1程序的呼叫;同样的,这些子程序进入点也需全部位于PAGE 1的前半部,否则会被呼叫不到;如此规划,对PAGE的控制才会单纯。 ;------------------------------------------------------------------------------------------------ rout1_1: ……………… retlw 0 ; 如此规划不必更改PAGE控制 ;------------------------------------------------------------------------------------------------ rout1_2: ……………… retlw 0 ; 如此规划不必更改PAGE控制 ;========================================================= sub1_1: ; 子程序的身体 ……………… call rout1_1 ……………… call rout1_2 ……………… bcf STATUS,5 ;page selector point to page 0 retlw 0 ;**************************************************************** ORG 0x400 ;page 2 前半部 ; 此前半部的规划与PAGE 1同 ;------------------------------------------------------------------------------------------------ sub2_1: ; 子程序的身体 ……………… bcf STATUS,6 ;page selector point to page 0 retlw 0 ; ------------------------------------------------------------------------------------------------ sub2_2: ; 子程序的身体 ……………… bcf STATUS,6 ;page selector point to page 0 retlw 0 ;**************************************************************** ORG 0x600 ;page 3 前半部 ; 此前半部的规划与PAGE 1同 ;------------------------------------------------------------------------------------------------ sub3_1: ; 子程序的身体 ……………… bcf STATUS,5 ;page selector point to page 0 bcf STATUS,6 retlw 0 ;**************************************************************** ORG 0x7FF ;reset vector goto main ;**************************************************************** END 上例中将PAGE 1、2、3的前半部优先放置第二阶子程序,而且此子程序只由同一PAGE中的第一阶子程序所呼叫使用;若其它PAGE也有第一阶子程序需用到此第二阶子程序,那就把有此需要的第一阶子程序搬来同一PAGE吧。如此用心良苦有以下几个好处:1、第一阶子程序可直接call第二阶子程序,不用改变PAGE的控制,2、第二阶子程序执行结束时只需retlw,也不用改变PAGE的控制,3、PAGE的管理单纯,不易出错,4、整个程序代码可减少bcf- SATUS,5、bcf STATUS,6、bsf STATUS,5、bsf STATUS,6的数量;当主程序也有必要直接呼叫此第二阶子程序时,可以有两种做法,第一种做法可以保持程序PAGE管理的一致性,就是为主程序另外设计一个第一阶子程序,来间接呼叫这个第二阶子程序,这会增加5个(若这个第二阶子程序在PAGE 3则需再加2个)指令及其运行时间,第二个做法就是破坏原则,由主程序直接呼叫,但在call指令的前后需加上PAGE控制,这种做法有其缺点,就是当此第二阶子程序被移到别的PAGE时,主程序内所有为呼叫该第二阶子程序所做之PAGE控制,全需因应修改,而且呼叫的次数愈多,PAGE控制也跟着多,修改起来也更费事且易出错;两种做法各有其利弊,何者适用则全由阁下视情况自行判断选择了。 程 序组译(assemble)完一定要开启listing檔(扩展名.lst),看看有无跨PAGE的现象,有的话就要调整该PAGE内一部分的子程序到别的PAGE,同时被搬动过的子程序的头及尾也需因应修改,同时要注意的是,是否把相对应的第二阶子程序也一齐搬动;另外要看看子程序(第一阶或第二阶)之进入点,有没有落于每个PAGE的前半部(即Address的bit* 8为0的区域),没有的话也要调整以消除此现象,不然会造成呼叫不到的bug。 现在将以上程序PAGE安排原则总结如下: 一、PAGE0的前半部先放第一阶子程序的头(若空间足够也可放整个子程序),头负责把PAGE控制转到该子程序的身体所座落之PAGE。 二、接下来放置主程序,主程序需全部置于PAGE0内。 三、第一阶子程序的身体可置于任一PAGE内,该子程序的尾负责把PAGE控制转回PAGE 0。 四、第二阶子程序与呼叫它的第一阶子程序放在同一PAGE内。 五、呼叫第二阶子程序不用改变PAGE控制(例外:主程序的呼叫);第二阶子程序的尾也不用改变PAGE控制。 六、所有的子程序,不管是第一阶或第二阶,其进入点皆需位于每一PAGE的前半部。 如 此安排后,对子程序的呼叫均不需处理PAGE控制,此控制是由子程序的头及尾处理掉了;而主、子程序当中的goto指令就可安心使用,不虞会GOTO到错误的PAGE上。 以上安排是不是会让您安心撰写程序而不用担心PAGE的控制呢?如果您发现到更好的方法也请不吝指教,谢谢!
[来源:来自网络] [作者:不详] [日期:11-01-08]
联系电话 
0755-33076986
15818599500
 联系人:张先生
 
电子邮箱 
 
合作伙伴 
 
友情链接 
 
联系地址 
联系地址
联系地址:深圳市龙岗区吉华路687号融和大厦7楼
 
©2010-2016 深圳千芯科技有限公司 版权所有. 粤ICP备13074652号