PRG0: …
… … PRGn: … 三、循环程序设计 1、循环程序的结构
循环程序包括以下四个部分: 置循环初
值循环体
循环控制变量修改 循环终止控制
常用于循环控制的指令有: DJNZ、CJNE、JC、JNC 等控制类指令。 2、单循环
终止循环控制采用计数的方法,即用一个寄存器作为循环次数计数器,每次循环后计数加1或减1,达到终止值后退出循环。
例4-6 计算50个8位二进制数(单字节)之和。
要求:50个数存放在30H开头的内部RAM中,和放在R6R7中。
分析:采用DJNZ循环体的流程框图如下页所示,在参考程序中,R0为数据地址指针,R2为减法循环计数器。 在使用DJNZ控制时,循环计数器初值不能为0,当为0时,第一次进入循环执行到DJNZ时,减1使R2变为FFH,循环次数成了256,显然不合题意。
START:MOV R6, #0
MOV R7, #0 MOV R2, #50
MOV R0, LOOP:MOV A,
ADD A,
#30H R7 @R0
MOV R7, A CLR A ADDC A, R6
MOV R6, A INC R0 DJNZ R2, LOOP
SJMP $ 3、多重循环
如果在一个循环程序中嵌套了其他的循环程序,称为多重循环程序。在用软件实现延时时显得特别有用。
例4-7 设计1秒延时子程序,假设fosc=12MHz。
分析:软件延时与指令的执行时间关系密切,在使用12MHz晶振时,一个机器周期的时间为1,us,执行一条DJNZ指令的时间为2us,我们可以采用三重循环的方法写出延时1秒的子程序
流程、程序如右图所示: DELAY: MOV R7, #10;
6
DL3: MOV R6, DL2: DL1:
MOV
DJNZ DJNZ DJNZ
#200 ;
R5, #250 ; R5, DL1 ; R6, DL2 ; R7, DL3 ;
RET
4、按条件转移控制的循环
例4-8 把内部RAM中从ST1地址开始存放的数据传送到以ST2开始的存储区中,数据块长度未知,但已知数据块的最后一个字节内容为00H,而其它字节均不为0。并设源地址与目的地址空间不重复。
分析:显然,我们可以利用判断每次传送的内容是否为 0 这一条件来控制循环。也可用CJNE来比较与0是否相等设计。利用判A转移控制的循环流程图如右图所示。
START:MOV R0, #ST1 MOV R1, #ST2 LOOP:MOV
A, @R0
JZ ENT
MOV @R1,A INC R0 INC R1
SJMP ENT:RET
LOOP
四、查表程序设计
用于查表的指令有两条:
MOVC A,@A+PC; MOVC A,@A+DPTR;
当使用DPTR作为基址寄存器时查表比较简单,查表的步骤分三步 1)基址(表格首地址)送DPTR数据指针;
2)变址值(在表中的位置是第几项)送累加器A; 3)执行查表指令MOVC A,@A+DPTR,进行读数,查表结果送回累加器A。 当使用PC作为基址寄存器时,由于PC本身是一个程序计数器,与指令的存放地址有关,查表时其操作有所不同。查表的步骤也分三步: 1)变址值(在表中的位置是第几项)送累加器A;
2)偏移量(查表指令的下一条指令的首地址到表格首地址之间的字节数)+ A → A;(修正)
3)执行查表指令MOVC A,@A+PC。 例4-9 二位十六进制数与ASCII码的转换程序。设数值在R2中,结果低位存在R2中,高位存在R3中。
分析:对于2位16进制数必须进行2次查表,因此,取数后通过屏蔽的方法来实现高低位分开。
(1)利用DPTR作基址的参考程序如下 HEXASC: MOV DPTR, #TABLE
MOV A, R2 ANL A, #0FH MOVC A, @A+DPTR ;查表
7
XCH R2, A ANL A, #0F0H
SWAP A ;
MOVC A, @A+DPTR MOV R3, A
;查表
RET
TABLE: DB 30H,31H,32H,33H,34H ;ASCII表
DB 35H,36H,37H,38H,39H DB 41H,42H,43H,44H,45H,46H (2)利用PC作基址的参考程序如下:
HEXASC: MOV A, R2
ANL
ADD
A, #0FH A, #9
MOVC A, @A+PC ;查表 XCH R2, A
ANL A, #0F0H
SWAP A ADD A, #2
MOVC A, @A+PC ;查表 MOV R3, A
RET
TABLE: DB “0”,“1”,…,“F” ;ASCII表
例4-10 利用查表指令,根据R2的分支序号找到对应的转向入口地址送DPTR,清ACC后,执行散转指令JMP @A+DPTR,转向对应的分支处理,假定分支处理程序在ROM 64KB的范围内分布。
程序如下:
ORG 1000H
START:MOV DPTR, #TAB
MOV ADD
JNC INC
MOV
A, R2 A, R2 ST1 DPH R3,
A
ST1:
MOVC A, @A+DPTR ;查表 XCH A, R3 INC A
MOVC A, @A+DPTR MOV MOV CLR
DPL,A DPH,R3 A
@A+DPTR PRG0
JMP TAB: DW
DW PRG1 … … 五、应用控制流程设计
8
例4-11 电机的简单起停控制;其框图如下页图 a 所示
1)分析:简单的电机起动停止控制,其控制的示意图及I/O分配如图 b 所示。 输入信号:启动按钮SB1、停止按钮SB2 输出信号:继电器KA
假定:按下按钮,相应的接口信号为低电平(P1.1=0)时;
若:程序使 P1.3=1,即KA = 1; 则:电机启动。
2)按照上述的控制思路,我们可以方便的画出流程图,如下图所示。
ORG 1000H STR:MOV P1, WT1:JB
P1.1,
#00000110B WT1
;启动?
SETB P1.3 ;电机启
P1.2,
WT2
;停止?
WT2:JB
CLR P1.3 ;电机停
SJMP WT1 END
(三)习题与思考题
1、循环程序由哪几部分构成。
2、什么是子程序?对子程序设计有什么要求?
3、 将(R2R3)和(R6R7)两个双字节无符号数相加,结果送R4R5。
NADD:MOV A,R3 ADD A,R7 MOV R5,A MOV A,R2 ADDC A,R6 MOV R4,A
RET
4、 将(R2R3)和(R6R7)两个双字节无符号数相减,结果送R4R5。
NSUB:MOV A,R3
9
CLR C
SUBB A,R7 MOV R5,A MOV A,R2 SUBB A,R6
MOV R4,A
RET
5、 将A中所存放的8位二进制数转换为BCD码,存于片内RAM的20H、21H单元。
MOV B,#100
DIV AB
MOV R0,#21H MOV @R0,A DEC R0
MOV A,#10 XCH A,B DIV AB SWAP A ADD A,B MOV @R0,A
RET
6、 将A中所存的一位十六进制数转换为ASCII码。
TRANS:MOV R2,A ADD A,#F6H MOV A,R2 JNC AD30 ADD A,#07H AD30: ADD A,#30H
RET
7、 编写一程序段,其功能为:内部RAM的30H(高)~32H(低)和33H(高)~35H(低)两个三字节无符号数相加,结果存入30H(高)~32H(低)单元,设三字节相加时无进位。
MOV R0,#32H
MOV R1,#35H MOV R2,#03H CLR C
LOOP:MOV A,@R0 ADDC A,@R1 MOV @R0,A DEC R0 DEC R1
DJNZ R2,LOOP
END
8、 编写一程序段,其功能为:内部RAM的32H(高)~30H(低)和35H(高)~33H(低)两个三字节无符号数相加,结果存入32H(高)~30H(低)单元,设三字节相加时无进位。
MOV R0,#30H
10