此篇文章中涉及的新指令如下:
数量 助记符 说明 字节数 执行时间 指令代码
79,ADDC A,Rn 寄存器内容加到累加器中(带进位) 1 1 38H-3FH
80,ADDC A,#data 立即数加到累加器中(带进位) 2 1 34,data
81,ANL A,direct 直接寻址字节逻辑与累加器A 2 1 55H,direct
82,ANL A,@Ri 间址寄存器RAM逻辑与到累加器A 1 1 56H-57H
83,ANL A,Rn 寄存器逻辑与到累加器A 1 1 58H-5FH
84,XRL A,@Ri 间址寄存器RAM逻辑异或到累加器A 1 1 66H-67H
85,MOV A,Rn 将寄存器内的内容送到A中 1 1 E8H-EFH
86,MOV @Ri,#data 寄存器Ri内为片内RAM地址,将立即数送到此地址中 2 1 76H-77H,data
87,JNZ rel 累加器A中内容不为零则转移 2 2 70H,rel
88,CJNE A,#data,rel 比较立即数和累加器A,其内容不等则转移 3 2 B4H,data,rel
89,CJNE Rn,#data,rel 比较立即数和寄存器,其内容不等则转移 3 2 B8H-BFH,data,rel
90,CJNE @Ri,#data,rel 比较立即数和间址寻址RAM,其内容不等则转移 3 2 B6H-B7H,data,rel
91,MOVC A,@A+PC (A)+(PC)构成ROM地址,将该地址内的数据送累加器A中 1 2 83H
92,JMP @A+DPTR 相对DPTR的间接转移 1 2 73H
题21
假设在起始地址为M的内部数据存储器中放有100个数,其中可能有一个数的值等于FEH,编程序求出这个数的地址,结果送N单元,若此数不存在,则送00H到N单元。
程序源码:
N EQU 06H
M EQU 08H
ORG 0100H
MOV R0,#M
MOV R7,#64H
LOOP:
CJNE @R0,#0FEH,PASS
SJMP RETU
PASS:
INC R0
DJNZ R7,LOOP
MOV R0,#00H
RETU:
MOV N,R0
HALT:
SJMP HALT
END
扩展:
假设在起始地址为M的外部数据存储器中放有100个数,其中可能有一个数的值等于51H,编程序求出这个数的地址,结果送内部RAM的NL和NH单元(低地址存NL)且对内部RAM地址为51H单元的内容清零,若此数不存在,则送51H到NL单元。
程序源码:
NL EQU 60H
NH EQU 61H
M EQU 0100H
ORG 0000H
MOV R0,#51H
MOV R1,#60H
MOV DPTR,#M
MOV R7,#64H
LOOP:
MOVX A,@DPTR
CJNE A,#51H,PASS
SJMP RETU
PASS:
INC DPTR
DJNZ R7,LOOP
MOV NL,#51H
SJMP HALT
RETU:
MOV NL,DPL
MOV NH,DPH
MOV @R0,#0
HALT:
SJMP HALT
END
题22
编程实现50毫秒延时子程序(不能使用定时器),设晶振12MHz。
解析:每条指令都有执行周期,根据这些指令周期进行延时。
程序源码:
; (((1+1+123*2+2)*200+1)+2)*1us=50.003ms
Delay50ms:
MOV R6,#0C8H
DEL1:
MOV R5,#123
NOP
DEL2:
DJNZ R6,DEL2
DJNZ R7,DEL1
RET
子程序有关知识补充:
子程序中涉及参数传递方式有:
第一,通过累加器或寄存器传递参数
第二,通过堆栈传递参数
第三,通过指针寄存器传递参数
实现两个8位的十六进制无符号数求和的子程序
ADDHXE:
MOV A,R7
ADD A,R6
JC L1
MOV R7,#00H
SJMP L2
L1:
MOV R7,#01H
L2:
MOV R6,A
RET
题23
将内部RAM中的两个4字节无符号数整数相加,和的高字节由R0指向数据采用小端模式存储。
解析:
大端模式(Big-endian):是指数据的高字节,保存在内存的低地址中,而数据的低字节,保存在内存的高地址中。
小端模式(Little-endian):是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内在的低地址中。
程序源码:
ADD1 EQU 60H
ADD2 EQU 64H
RESULT EQU 68H
ORG 0000H
MOV R0,#ADD1
MOV R1,#ADD2
MOV R2,#04H
MOV A,#80H
L1:
MOV @R0,A
MOV @R1,A
INC R0
INC R1
INC A
DJNZ R2,L1
;FOR TESTING
MOV R0,#ADD1
MOV R1,#ADD2
MOV B,#RESULT
MOV SP,#50H
MOV R2,#04H
CLR C
LOOP:
MOV A,@R0
MOV 70H,R0
MOV R0,B
ADDC A,@R1
MOV @R0,A
MOV R0,70H
INC B
INC R0
INC R1
DJNZ R2,LOOP
DEC B
MOV R0,B
SJMP $
END
题24
将内部RAM中60H单元中的十六进制数转换为两位ASCII码,分别存放在外部RAM中的0100H、0101H两个单元中
程序源码:
HEX EQU 60H
ASCII EQU 0100H
ORG 0000H
MOV SP,#50H
MOV R0,#HEX
MOV DPTR,#ASCII
PUSH HEX
ACALL HANGDLER
POP ACC
MOVX @DPTR,A
INC DPTR
MOV A,HEX
SWAP A
PUSH ACC
ACALL HANGDLER
POP ACC
MOVX @DPTR,A
SJMP $
HANGDLER:
DEC SP
DEC SP
POP ACC
ANL A,#0FH
ADD A,#07H
MOVC A,@A+PC
PUSH ACC
INC SP
INC SP
RET
ASCTAB:
DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H
DB 41H,42H,43H,44H,45H,46H
END
扩展:
将内部RAM中60H单元中的十六进制数转换为两位ASCII码,分别存放在内部RAM中的61H、62H两个单元中
程序源码:
HEX EQU 60H
ASCII EQU 61H
ORG 0000H
MOV 60H,#51H;为了测试
MOV SP,#50H
MOV R0,#HEX
PUSH HEX ;51
ACALL HANGDLER;53
POP ASCII
MOV A,HEX
SWAP A
PUSH ACC;51
ACALL HANGDLER;53
POP ASCII+1
SJMP $
HANGDLER:
DEC SP
DEC SP
POP ACC
ANL A,#0FH
ADD A,#08H
MOVC A,@A+PC
PUSH ACC
INC SP
INC SP
NOP;FOR TESTING
RET
ASCTAB:
DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H
DB 41H,42H,43H,44H,45H,46H
END
仿真图:
将一个16进制数码0-F(R1的低四位)转换为相应的ASCII码,存放到原来位置。
程序源码:
方式一:
ORG 0000H
MOV DPTR,#TAB
MOV R7,#0FH
MOV A,R1
ANL A,R7
MOVC A,@A+DPTR
MOV R1,A
SJMP $
TAB:
DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H
DB 41H,42H,43H,44H,45H,46H
END
方式二:
DAT EQU 60H
UTILIZE EQU 61H
ORG 0000H
MOV DAT,#25;FOR TESTING
MOV R1,#DAT
MOV UTILIZE,#0FH
MOV R0,#UTILIZE
MOV A,@R1
ANL A,@R0
ADD A,#04H
MOVC A,@A+PC
MOV @R1,A
NOP
SJMP $
TAB:
DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H
DB 41H,42H,43H,44H,45H,46H
END
题25***散转程序设计***
编写程序,内部RAM地址为60H单元中的内容与内部RAM地址为61H中的内容进行逻辑与后存于62H单元,若:
(62H)=0,程序跳转到FUC1,执行间隔100毫秒亮灭LED0
(62H)=10H,程序跳转到FUC2,执行间隔100毫秒亮灭LED1
(62H)=20H,程序跳转到FUC3,执行间隔100毫秒亮灭LED2
(62H)=其它数值,程序跳转到HALT
LED电路图连接如下图:(LED0,LED1低电平点亮,LED2高电平点亮)
程序源码:
DAT1 EQU 60H
DAT2 EQU 61H
RESULT EQU 62H
LED0 BIT P1.0
LED1 BIT P1.1
LED2 BIT P1.2
ORG 0000H
MOV DAT1,#0FFH;FOR TESTING
MOV DAT2,#20H;FOR TESTING
MOV SP,#70H
SETB LED0
SETB LED1
CLR LED2
MOV DPTR,#FUC
MOV A,DAT2
ANL A,60H
MOV RESULT,A
MOV R2,A
JNZ CHECK
JMP @A+DPTR
CHECK:
CLR A
CJNE R2,#10H,SEL0
MOV A,#01H
JMP @A+DPTR
SEL0:
CJNE R2,#20H,SEL1
LJMP FUC3;for testing
SEL1:
SJMP HALT
FUC1:
CPL LED0
ACALL Delay100ms
AJMP FUC1
FUC2:
CPL LED1
ACALL Delay100ms
AJMP FUC2;FOR TESTING
FUC3:
CPL LED2
ACALL Delay100ms
AJMP FUC3
HALT:
SJMP HALT
Delay100ms:
MOV R6,#0C8H
DEL1:
MOV R5,#0F7H
NOP
DEL2:
DJNZ R6,DEL2
DJNZ R7,DEL1
RET
ORG 0055H
FUC:
LJMP FUC1
LJMP FUC2
LJMP FUC3
END
仿真图:
设被乘数存放在R7R6,乘数存放在R5R4中,试编写双字节无符号数的乘法子程序,结果依次存放在内部RAM中的60H-63H(乘积高位放高地址)。
例如:4030H*2010H=080A0300H
程序源码:
RESULT EQU 60H
ORG 0000H
MOV R4,#10H
MOV R5,#20H
MOV R6,#30H
MOV R7,#40H
;FOR TESTING
MOV R0,#RESULT
LCALL FUNC
SJMP $
ORG 0030H
FUNC:
MOV A,R6
MOV B,R4
MUL AB
MOV @R0,A
MOV R3,B
MOV A,R7
MOV B,R4
MUL AB
ADD A,R3
MOV R3,A
MOV A,B
ADDC A,#00H
MOV R2,A
MOV A,R6
MOV B,R5
MUL AB
ADD A,R3
INC R0
MOV @R0,A
MOV R1,#00H
MOV A,R2
ADDC A,B
MOV R2,A
JNC LOOP
INC R1
LOOP:
MOV A,R7
MOV B,R5
MUL AB
ADD A,R2
INC R0
MOV @R0,A
MOV A,B
ADDC A,R1
INC R0
MOV @R0,A
RET
END
仿真图:
设晶振频率为6MHz,内部RAM地址为50H开始的连续10个字节区域中存有数据,现编程将上述区域中的每个单元地址中的数据进行取反保存至原来地址中,然后从P1.0引脚输出周期为2ms的方波信号。
程序源码:
ORG 0000H
LJMP START
ORG 0030H
START:
MOV 50H,#17H
MOV 51H,#25H
MOV 52H,#38H
MOV 53H,#49H;FOR TESTING
MOV SP,#4AH
MOV R0,#50H
MOV R2,#10H
L1:
MOV A,#0FFH
XRL A,@R0
MOV @R0,A
INC R0
DJNZ R2,L1
SETB P1.0
L2:
CPL P1.0
ACALL Delay1ms
AJMP L2
SJMP $
Delay1ms:
MOV B,#0A6H
LOOP:
DEC A
JNZ LOOP
NOP
RET
END
仿真图: