田邱林
(桂林理工大学高等职业技术学院,广西 南宁 530001)
51单片机指令SJMP $不宜滥用
田邱林
(桂林理工大学高等职业技术学院,广西 南宁 530001)
51单片机的指令SJMP $,是诸如HERE:SJMP HERE的简略表示,其目标地址即为当前地址,相当于定义了一个没有退出条件的循环,即所谓“死循环”,因此,该指令不可滥用。
单片机;微机控制;指令SJMP $
51单片机指令SJMP $,是诸如HERE:SJMP HERE的简略表示,其目标地址即为当前地址,相当于定义了一个没有退出条件的循环,即所谓“死循环”。令人诧异的是,这样一个麻烦制造者却在一些51单片机教材中屡屡现身,从手头的教材中随机抽取几本,统计程序示例中指令SJMP $(含AJMP $)出现的频度,结果少则5、6处,多的超过10处,这尚未包括目标地址为“$”的条件转移指令。只有厘清指令 SJMP $的作用,才能诠释使用它的意义。
51单片机的SJMP rel是一条无条件短转移指令,偏移量rel是一个用补码表示的8位带符号数,转移范围为相对指令当前地址-128~+127的256个单元,所以也被称作相对转移指令。当rel取值为FEH时,指令可表示为SJMP $,程序就地转入无条件循环,终止下行。
51单片机的AJMP addr11是一条无条件指定页转移指令,也被称为绝对转移指令或短转移指令,addr11提供同一个2KB页范围内的转移空间。当addr11指向该指令当前位置时,亦可表示为 AJMP $,作用与指令 SJMP $相同,但不如 SJMP $的可读性强。
相关教材给出了指令SJMP $的三个用途,即程序隔离、程序暂停和等中断。
程序隔离的实质,是令程序在即将进入非顺序模块前转向,其实(包括SJMP rel在内的)所有转移指令都可以完成程序跳转,不必刻意使用SJMP $。
讨论程序暂停的意义,不妨看一段引文对指令SJMP $的描述。
若偏移量rel取值为FEH,则目标地址等于源地址,相当于动态暂停,程序“终止”在这条指令上。动态暂停指令在调试程序时很有用。MCS-51没有专用的停止指令,若要求动态暂停可以用SJMP指令来实现:
HERE:SJMP HERE;动态停机(80H,FEH)
尽管描述有些混乱,仔细梳理仍可见端倪。
首先,“MCS-51没有专用的停止指令”,堪称一语中的,因为设计者压根没打算停机。自创一条停止指令SJMP $,无端耗费有限的机器时间资源,显然有悖设计初衷。
其次,指令SJMP $在终止程序下行后仍允许中断响应,这就是“动态暂停”的由来。
再者,若无中断可响应,程序被迫“终止”(在 SJMP $上),故而注释为“动态停机”,以示有别于“动态暂停”。对于这种运行状态,一般PC机用户更习惯直呼为死机。
至于“动态暂停指令在调试程序时很有用”,则属于套用PC机的概念,意指借指令JMP $(罕用,常用WAIT和DEBUG专用指令 HLT)将待调程序分段调试。须知,替换 PC机 RAM中的指令易如反掌,单片机 EPROM中的程序却不允许随机删改。对于单片机,可自程序分段处跳转至键盘模块,经键盘馈入调试引导信息,完成调试后,调试引导模块或作为手动模块保留,需要时经由键盘激活。
下面一段引文描述了借指令SJMP $等中断的过程。
这是一条死循环令,如果系统的中断是开放的,那么SJMP $指令实际上是在等待中断,当有中断申请后,CPU转至执行中断服务程序。中断返回时,仍然返回到这条死循环指令,继续等待中断,而不是返回到该指令的下一条指令。这是因为执行SJMP $后,PC仍指向这条指令,中断的断点就是这条指令的首字节地址。
所谓等中断也套用了PC机的概念。PC机可提供多达256个32位的中断矢量,还能扩充中断链等硬件予以支持,除去系统占用和保留的之外,可供用户灵活使用的依然十分丰富,因此,PC机的许多功能的确是建立在(包括软调用)中断基础之上的。相比之下,单片机区区几个16位的中断矢量,即便全部“中断是开放的”也仅能应对少数紧急事件,主程序仍要承担大量常规操作。设计中断方式的本意,是在满足实时性要求的前提下,使计算机仍有充裕时间处理各种事务,因此,空耗机器时间等候中断实属不当应用。换个角度来看,等中断实际上改变了中断的运行方式,稍有不慎可能事与愿违。
上述三个用途缺少中断配合均意味着死机,所以可归结为等中断,而等中断终归不当应用。
本节通过几个例子来考察指令SJMP $的作为。例1.
FW:LCALL DELAY;令电机正向转动300次DELAY子程序的时间
DJNZ TIME,FW
MOV TIME,#300
SETB IN1
CLR IN2
FAN:LCALL DELAY;令电机反向转动300次DELAY子程序的时间
DJNZ TIME,FAN
STOP:CLR IN1;令电机停转
CLR IN2
AJMP $
本例令电机正反转一次后停转。众所周知,电机是反复运转的设备,本例需要利用中断服务程序修改堆栈中的断点,重新指向电机驱动程序,才能再次启动电机。本例试图演绎指令AJMP $的暂停功能却落入陷阱,与其借由中断逃脱束缚,不如直接用中断方式控制电机更快捷更可靠。
例2.
LOOP:JNB FO,$;等待计数5000时产生中断
SETB P1.0;绕线机停止工作
本例用户标志 F0未置位时,指令 JNB F0,$执行结果与SJMP $相似。例中注释表明F0由计数器中断置位,意在强调等中断,但之后的指令 SETB P1.0可以被任意中断,致使部分线包匝数失准,除非关闭其余中断。P1.0和F0都是位名称,操作雷同,若P1.0由中断直接置位,且设该计数器中断为唯一高优先级,则能保证线包匝数准确,亦不必等待和限制其他中断。
例3.
LOOP:JNB TF1,LOOP;查询等待
CLR TF1;TF1清零
CPL P1.0;P1.0取反
MOV TH1,#OEOH;重新装入时间常数初值
MOV TL1,#18H
AJMP LOOP;继续生成波形本例的LOOP:JNB TF1,LOOP也可以表示为JNB TF1,$,与例2的区别在于TF1可由硬件直接置/复位。置位TF1必须启动定时器T1,但JNB TF1,$是双周期指令,T1中断约有半数机会抢先使 TF1硬复位,导致波形畸变,所以又必须关闭T1中断。鉴于例中TF1采用软复位,可认为T1中断已被关闭,即便如此,仍不能阻止其他中断干扰定时器T1重置,波形畸变依旧难免。如果再关闭其他中断,则所有中断均被关闭,这样一来,单片机仅相当于一只固定频率振荡器。循环体本质属于子程序,因自动就地重复可免调用,本例循环体添一条返回指令即可供T1中断调用,若再采用高优先级,不但不会延误重置,还可取消 TF1软复位,也不影响在低优先级下应用其他中断。
例4.
B.查询方式
对于采用查询方式时,则需要把EOC与8031一条I/O口线相连。本例中用P1.7边EOC,因此,8031通过对P1.7的状态进行不断的查询,来判断 A/D转换是否结束。实现中断方式的具体程序如下:
MAIN:MOV R1,#50H;置转换结果存放数据区首址
MOV DPTR,#7FF8H;DPTR指向ADC0809的通道IN0地址
MOV R7,#08H;置转换通道数
LOOP:MOVX @DPTR,A;启动A/D转换
WAIT:MOV A,P1;未转换完,继续查询
JNB ACC.7,WAIT
MOVX A,@DPTR;读取转换结果
MOV @R1,A;转换结果存入结果数据区
INC DPTR;指向下一个通道
INC R1;修改结果数据区指针
DJNZ R7,LOOP;8路模拟信号是否都已转换完成?
SJMP $
本例是一段 8通道模拟信号采样程序,在顺利完成第一次8通道循环后,遇到SJMP $,难以 “不断的查询”,由于程序未按中断方式编写,也不能“实现中断”取值,没有后续检测则控制无以为据。可行的做法是利用定时器建立周期指针,为“实现中断”测控方式提供节律。本例采用集中测(控),即使采用中断也难免“不断的查询”,如果采用分散测控并令测控节律略大于A/D转换周期,使A/D转换与测控程序平行运行,实现中断内无条件取值,不但节省查询等待时间,还可使测控时标更精确。
引述以上4例皆因其典型,绝非其他使用SJMP $及其近义指令的程序就没有问题,至少,耗在一个点上等待实际上已造成程序阻塞,许多功能被屏蔽是既成事实。
下面是一个概略的程序参考框架。
… ;初始化模块MOV PTER,#00H;启动自行待机
KEY: … ;键盘解码模块
JNB F0,SEQU ;运行/调试选择
TEST: … ;键盘二次解码
MOV PTER,A ;保存散转指针
DISP1: ACALL DISP ;调用显示模块MOV A,PTER ;提取散转指针
RL A
SELECT: JMP @A+DPTR ;选择运行模式
SJMP KEY ;目标地址很近AJMP SEQU ;目标地址较近AJMP SELE1…
LJMP SEELN ;目标地址较远… ;被隔离区
SEQU: SETB EA ;主模块开中断CLR F0 ;关闭手动调试…
ACALL DISP ;进行人机对话AJMP KEY
TABLE: … ;数据表隔离区
SELE1: CLR EA ;暂停输出模块SETB F0 ;激活手动调试AJMP KEY ;保持人机对话… ;被隔离区
… ;其他功能模块
SEELN: … ;模块N
LJMP KEY
… ;被隔离区
DISP: … ;显示模块
RET
… ;被隔离区
TIMER0: … ;定时中断0
RETI
… ;被隔离区
… ;其他中断
INTT1: … ;外部中断1
RETI
… ;被隔离区
从例举的程序框架可以看出,赋予指令SJMP $的三种功能,其实都是误解。
其一,程序中能自然产生许多被隔离区,根据需要灵活分配即可。
其二,所谓暂停可分程序暂停和单片机暂停两层含义。程序暂停因无严格定义而无从讨论,但并不妨碍质疑其意义何在及尔后如何唤醒。单片机仅需临时关闭其控制(信号输出)功能,其中也包括阻止具有输出功能的中断服务程序,此时外在表现即为暂停,并不需要关闭其监视(信号输入)功能,也就是说,程序无需暂停。
单片机不能完全避免(有别于暂停的)待机,程序框架例举了一种解决方案。系统启动后处于无中断待机状态,可随时借助键盘修改散转指针PTER,选择程序各项功能。选择运行主模块时开中断,随即取消调试/手动功能,当然机器时间充裕时不取消也无妨,但始终保留人机对话功能,以便于状态转换。如果确实需要待机,通过选择可选模块 SELE1关闭中断的同时激活调试/手动功能,将待机视为启用调试/手动功能的前奏,要比单纯待机更安全。
其三,中断是一种满足响应条件即可随机插入子程序的运行方式,空等专侯就枉费了。
通过检讨可知,指令SJMP $的表现乏善可陈,亦无独到专长,故类似指令切勿滥用。
[1]王用伦.微机控制技术[M].重庆:重庆大学出版社,2004.
[2]李全利.单片机原理及应用技术[M].北京:高等教育出版社,2001.
[3]张晔.王玉民.单片机应用技术[M].北京:高等教育出版社,2006.
[4]王效华.单片机原理及应用[M].北京:北京交通大学出版社,2007.
TP368.1
A
1008-1151(2011)04-0046-02
2011-01-12
田邱林(1952-),男,河北完县人,桂林理工大学高等职业技术学院(南宁校区)高级工程师,副教授,研究方向为计算机组成原理、单片机、计算机控制技术等。