3.16 8051芯片需要外扩4KB 程序存储器,要求地址范围为1000~1FFFH,以便
和内部程序存储器地址相衔接。所用芯片除了地址线和数据线外,只有一个片选控制端/CS,画出扩展系统的连接图。
解:
3. 17 在图3.13中,若因某种原因,P2.2、P2.1、P2.0误接为P2.5、P2.4、P2.3, 这时所接的EPROM 寻址区是如何分布的? 解:
误接后,A10,A9,A8则分别与P2.5,P2.4,P2.3相接,
P2.7 P2.6 P2.5 P2.4 P2.3 P2.2 P2.1 P2.0 P0.7~P0.0
* * 0 0 0 * * * 00000000—11111111 * * 0 0 1 * * * 00000000—11111111 * * 0 1 0 * * * 00000000—11111111 * * 0 1 1 * * * 00000000—11111111 * * 1 0 0 * * * 00000000—11111111 * * 1 0 1 * * * 00000000—11111111 * * 1 1 0 * * * 00000000—11111111 * * 1 1 1 * * * 00000000—11111111 所以地址分布为:
0000H~00FFH, 0800H~08FFH, 1000H~10FFH, 1800H~18FFH, 2000H~20FFH, 2800H~28FFH, 3000H~30FFH, 3800H~38FFH
4.8 编写程序,进行两个16位数的减法:6F5DH~13B4H,结果存至内部RAM 的
30H 和31H 单元。30H 单元存差的低8位。 解:
MOV A, #5DH
CLR C
SUBB A, #0B4H MOV 30H, A MOV A, #6FH SUBB A, #13H MOV 31H, A SJMP $
4.9 编写程序,若累加器内容分别满足一下条件,则程序转至LABEL 存储单元。
(1)A ≥10 (2) A>10 (3) A≤10 (4) A<10 解:
(1) CLR C
CJNE A, #10, LOOP SJMP LABEL
LOOP: JNC LABEL SJMP $
(2) CJNE A, #10, LOOP
SJMP $
LOOP: JNC LABEL SJMP $
(3) CJNE A, #10, LOOP
SJMP LABEL
LOOP: JC LABEL SJMP $
(4) CJNE A, #10, LOOP
SJMP $
LOOP: JC LABEL SJMP $
4.10 已知SP=25H,PC=2345H,(24H)=12H,(25H)=34H,(26H)=56H,问在这种条件下执行RET 指令以后,SP,PC 分别是多少? 解:
在执行RET 指令后说明是一个子函数执行结束,则进行POP 操作,于是SP 在执行RET 指令后变为23H ,因为(25H)=34H, (24H)=12H,所以PC=3412H,因为在进入堆栈的时候是先压入低8位,然后进入堆栈的是高8位,出堆栈的时候正好相反。所以最后结果是:SP=23H,PC=3412H
4.11 若SP=25H,PC=2345H,标号LABEL 所在的地址为3456H ,问执行长调用指令 LCALL LABEL 之后,堆栈指针和堆栈内容发生什么变化?PC 是多少? 解:
在进行长调用指令 LCALL LABEL,则要进行堆栈保护, 而LCALL 指令是三字节的指令,所以PC 在进入堆栈之前变为2348H ,在执行完长指令LCALL 之后,
PC 进入子函数程序,则进入之前的地址要首先保护起来,所以SP=27H,堆栈的内容(26H)=48H,(27H)=23H,此时PC 将要指向子函数LABEL 的入口地址,即PC=3456H。
4.12 在4.11中的LCALL 指令能否直接换成“ACALL LABEL”指令?为什么? 解:
不能,因为ACALL 是短调用指令,子程序调用的范围为围绕调用指令的2KB 内,即它们的地址高5位应该是相同的。或者说,在执行ACALL 指令时,子程序入口地址的高5位是不能任意定的,只能由ACALL 指令所在的位置来确定,例如4.11在调用子函数之前的地址为2345H ,即高5位是00100,所以ACALL 调用的地址范围为:2000H ——27FFH ,而LABEL 所在的地址为3456H 已经超出调用范围,所以不能替换。
4.13 试编写程序,查找在内部RAM 的20H~50H单元中是否有0AAH 这一数据,若有这一数据,则将51H 单元置为01H, 若未找到,则使51H 单元置0。 解:
参考程序如下:
M0V R0,#31H M0V R1,#20H
LOOP: MOV A,@R1
CLR C
CJNE A,#0AAH,LOOP1 SJMP L00P2
LOOP1: INC R1
DJNZ R0,LOOP
M0V A,#00H SJMP LOOP3
LOOP2: MOV A,#01H LOOP3: MOV 51H,A SJMP $
4.14 试编写程序,查找在内部RAM 的20H~50H单元内部出现00H 的次数,并将查找的结果存入51H 单元。 解:
参考程序如下:
MOV R0,#31H MOV R1,#20H MOV R2,#00H
LOOP: MOV A,@R1
CJNE A,#00H,LOOP1 INC R2
LOOP1: INC R1
DJNZ R0,LOOP M0V 51H,R2
SJMP $
5. 6 从20H 单元开始存放一组带符号数,其数目已经存在1FH 单元。要求统计
出其中大于0,等于0和小于0的数的个数,并把统计结果分别存入ONE ,TWO,THREE 三个单元。 解:
参考程序如下:
ONE DATA #1CH TWO DATA #1DH THREE DATA #1EH MOV ONE,#00H MOV TWO,#00H MOV THREE,#00H MOV R0,#20H MOV R1,1FH
MOV A,R1 /*判断是否存有数*/ JZ FINISHI
LOOP: MOV A,@R0
CLR C
CJNE A,#00H,LOOP1 INC TWO SJMP LOOP3
LOOP1: JNC LOOP2 /*A>0时*/ INC THREE /*A
LOOP3: DJNZ R1,LOOP FINISHI: SJMP $
5.14 外部数据RAM 从2000H 开始有100个数据,现要将它们移到从2030H 开始的区域,试编写有关程序。 解:
参考程序如下(1):
MOV DPTR,#2000H MOV A,#63H MOV R0,#100 ADD A,DPL MOV DPL,A
LOOP: MOVX A,@DPTR /*取出最后一个数*/
PUSH DPL PUSH A
MOV A,DPL ADD A,#30H MOV DPL,A POP A
MOVX @DPTR,A POP DPL DEC DPL
DJNZ R0,LOOP SJMP $
参考程序如下(2):
MOV R0,#100
MOV DPTR,#2063H
LOOP: MOVX A,@DPTR
MOV R1,A MOV A,DPL ADD A,#30H MOV DPL,A MOV A,R1 MOVX @DPTR,A MOV A,DPL SUBB A,#30H MOV DPL,A DEC DPL
DJNZ R0,LOOP SJMP $
5.15 从内部数据RAM 的BLOCK 开始有一个无符号数数据块,长度存于LEN 单元,求出数据块中的最小元素,并将其存入MINI 单元。要求使用比较条件转移指令CJNE 。 解:
参考程序如下:
LEN DATA 20H MINI DATA 21H BLOCK DATA 22H MOV R0,LEN MOV R1,#BLOCK
MOV A,R0 /*检查数据长度是否0*/ JZ FINISH MOV MINI,@R1
LOOP: MOV A,@R1 INC R1
CLR C
CJNE A,MINI,LOOP1 SJMP LOOP2
LOOP1: JNC,LOOP2
MOV MINI,A
LOOP2: DJNZ R0,LOOP FINISH: SJMP $
5.20 若累加器A 中存放的是一个十六进制数,则将它转换为相应的ASCII 码,并将结果存入20H RAM单元,若A 中存放的不是十六进制数,则将20H 单元置为FFH, 试编写有关程序。 解:
参考程序入下:
MOV R1, A ANL A, #0F0H CJNE A, #00H,REL Clr c
CJNE A, #09H, LOOP SJMP LOOP1 (=9)
LOOP: JC LO0P1 (
ADD A,#07H (>9) LOOP1: ADD A,#30H MOV 20H,A SJMP $
REL: MOV 20H,#0FFH
SJMP $
7.1 用8031单片机的P1口和微型打印机连接以输出数据。数据传送采用中断方式。现要把外部数据RAM 中从20H 单元开始的100个数据送到打印机中去打印。试写出有关的程序,包括主程序和中断服务程序。
解:本题采用中断方式,用ACK 加到INTO 作为中断请求信号,用一个4输入译码器进行部分地址译码,系统的硬件连接图如下图所示:
主程序:
SETB EA SETB EX0 SETB PX0 SETB IT0
MOV RO,#20H MOV R1,#0F0H MOV R2,#99 MOVX A,@R0 MOVX @R1,A LOOP: SJMP $
中断服务程序:
ORG 0003H LJMP INT0
INT0: PUSH PSW PUSH ACC INC R0 MOVX A,@R0 MOVX @R1,A DEC R2 MOV A,R2 JNZ NEXT CLR EXO NEXT: POP ACC POP PSW RETI
7.3 用8255芯片扩展单片机的I/0口。8255的A 口用做输入,A 口的每一位接
一个开关,用B 口作为输出,输出的每一位接一个显示发光二极管。现要求某个开关接1时,相应位上的发光二极管就亮(输出为0),试编写相应的程序。
VCC
地
解:设8255的A 口地址为70H, B口地址为71H, C口地址为72H, 控制寄存器地址为73H 。
8255的工作方式为: A口:方式0,输入 B口:方式0,输出 C口:无关
由此可以确定8255的工作方式控制字为10010000H, 即90H 。有关程序如下:
MOV RO,#73H MOV A,#90H MOVX @R0,A
LOOP: MOV RO,#70H
MOVX A,@R0 CPL A INC RO MOVX @R0,A
SJMP LOOP
7.8 外部RAM 以DAT1开始的数据区中有100个数,现要求每隔150ms 向内部RAM 以DAT2开始的数据区中传送10个数。通过10次传送把数据全部传送完。以定时器1作为定时,8155作为接口芯片。试编写有关的程序。单片机时钟频率为6MHz 。 解:
现要求定时值为150ms ,在单片机时钟频率为6MHz 的情况,这个值已超过定时器可能提供的最大定时值。为了能够实现150ms 的定时值,可采用定时器定时和软件计数器相结合的方法。本题可设定时器的定时值为50ms ,另设一个软件计数器,初值为3。每50ms 定时时间到时,产生中断,在中断服务程序中使软件计数器减1,这样到软件计数器减到0时,就获得了150ms 的定时。
先计算50ms 定时所需的定时初始值。这时需采用定时器方式1,即16位计数器方式。故定时器初值为:
X=216-(50*10-3/(2*10-6)= 65536-25000 = 40536 = 95E8H
本题采用定时器1定时,工作方式为1,TH1初值为9EH,TL1初值为58H 。中断服务程序入口为001BH 。相关程序如下:
ORG 001BH LJMP BRT1
START: ORG 2000H MOV TMOD,#01H MOV TH1,#9EH MOV TL1,#58H MOV IE,#88H SETB TR1
MOV DPTR,#DAT1 MOV RO,#DAT2 MOV R1,#10 MOV R2,#10 MOV R3,#3 LOOP: SJMP $
中断服务程序:
BRT1: MOV TH1,#9EH MOV TL1,#58H
DJNZ R3,NEXT2
NEXT1: MOVX A,@DPTR MOV @RO,A INC DPTR INC R0
DJNZ R2,NEXT1 MOV R3,#3 DJNZ R1,NEXT2 CLR TR1 NEXT2: RETI
3.16 8051芯片需要外扩4KB 程序存储器,要求地址范围为1000~1FFFH,以便
和内部程序存储器地址相衔接。所用芯片除了地址线和数据线外,只有一个片选控制端/CS,画出扩展系统的连接图。
解:
3. 17 在图3.13中,若因某种原因,P2.2、P2.1、P2.0误接为P2.5、P2.4、P2.3, 这时所接的EPROM 寻址区是如何分布的? 解:
误接后,A10,A9,A8则分别与P2.5,P2.4,P2.3相接,
P2.7 P2.6 P2.5 P2.4 P2.3 P2.2 P2.1 P2.0 P0.7~P0.0
* * 0 0 0 * * * 00000000—11111111 * * 0 0 1 * * * 00000000—11111111 * * 0 1 0 * * * 00000000—11111111 * * 0 1 1 * * * 00000000—11111111 * * 1 0 0 * * * 00000000—11111111 * * 1 0 1 * * * 00000000—11111111 * * 1 1 0 * * * 00000000—11111111 * * 1 1 1 * * * 00000000—11111111 所以地址分布为:
0000H~00FFH, 0800H~08FFH, 1000H~10FFH, 1800H~18FFH, 2000H~20FFH, 2800H~28FFH, 3000H~30FFH, 3800H~38FFH
4.8 编写程序,进行两个16位数的减法:6F5DH~13B4H,结果存至内部RAM 的
30H 和31H 单元。30H 单元存差的低8位。 解:
MOV A, #5DH
CLR C
SUBB A, #0B4H MOV 30H, A MOV A, #6FH SUBB A, #13H MOV 31H, A SJMP $
4.9 编写程序,若累加器内容分别满足一下条件,则程序转至LABEL 存储单元。
(1)A ≥10 (2) A>10 (3) A≤10 (4) A<10 解:
(1) CLR C
CJNE A, #10, LOOP SJMP LABEL
LOOP: JNC LABEL SJMP $
(2) CJNE A, #10, LOOP
SJMP $
LOOP: JNC LABEL SJMP $
(3) CJNE A, #10, LOOP
SJMP LABEL
LOOP: JC LABEL SJMP $
(4) CJNE A, #10, LOOP
SJMP $
LOOP: JC LABEL SJMP $
4.10 已知SP=25H,PC=2345H,(24H)=12H,(25H)=34H,(26H)=56H,问在这种条件下执行RET 指令以后,SP,PC 分别是多少? 解:
在执行RET 指令后说明是一个子函数执行结束,则进行POP 操作,于是SP 在执行RET 指令后变为23H ,因为(25H)=34H, (24H)=12H,所以PC=3412H,因为在进入堆栈的时候是先压入低8位,然后进入堆栈的是高8位,出堆栈的时候正好相反。所以最后结果是:SP=23H,PC=3412H
4.11 若SP=25H,PC=2345H,标号LABEL 所在的地址为3456H ,问执行长调用指令 LCALL LABEL 之后,堆栈指针和堆栈内容发生什么变化?PC 是多少? 解:
在进行长调用指令 LCALL LABEL,则要进行堆栈保护, 而LCALL 指令是三字节的指令,所以PC 在进入堆栈之前变为2348H ,在执行完长指令LCALL 之后,
PC 进入子函数程序,则进入之前的地址要首先保护起来,所以SP=27H,堆栈的内容(26H)=48H,(27H)=23H,此时PC 将要指向子函数LABEL 的入口地址,即PC=3456H。
4.12 在4.11中的LCALL 指令能否直接换成“ACALL LABEL”指令?为什么? 解:
不能,因为ACALL 是短调用指令,子程序调用的范围为围绕调用指令的2KB 内,即它们的地址高5位应该是相同的。或者说,在执行ACALL 指令时,子程序入口地址的高5位是不能任意定的,只能由ACALL 指令所在的位置来确定,例如4.11在调用子函数之前的地址为2345H ,即高5位是00100,所以ACALL 调用的地址范围为:2000H ——27FFH ,而LABEL 所在的地址为3456H 已经超出调用范围,所以不能替换。
4.13 试编写程序,查找在内部RAM 的20H~50H单元中是否有0AAH 这一数据,若有这一数据,则将51H 单元置为01H, 若未找到,则使51H 单元置0。 解:
参考程序如下:
M0V R0,#31H M0V R1,#20H
LOOP: MOV A,@R1
CLR C
CJNE A,#0AAH,LOOP1 SJMP L00P2
LOOP1: INC R1
DJNZ R0,LOOP
M0V A,#00H SJMP LOOP3
LOOP2: MOV A,#01H LOOP3: MOV 51H,A SJMP $
4.14 试编写程序,查找在内部RAM 的20H~50H单元内部出现00H 的次数,并将查找的结果存入51H 单元。 解:
参考程序如下:
MOV R0,#31H MOV R1,#20H MOV R2,#00H
LOOP: MOV A,@R1
CJNE A,#00H,LOOP1 INC R2
LOOP1: INC R1
DJNZ R0,LOOP M0V 51H,R2
SJMP $
5. 6 从20H 单元开始存放一组带符号数,其数目已经存在1FH 单元。要求统计
出其中大于0,等于0和小于0的数的个数,并把统计结果分别存入ONE ,TWO,THREE 三个单元。 解:
参考程序如下:
ONE DATA #1CH TWO DATA #1DH THREE DATA #1EH MOV ONE,#00H MOV TWO,#00H MOV THREE,#00H MOV R0,#20H MOV R1,1FH
MOV A,R1 /*判断是否存有数*/ JZ FINISHI
LOOP: MOV A,@R0
CLR C
CJNE A,#00H,LOOP1 INC TWO SJMP LOOP3
LOOP1: JNC LOOP2 /*A>0时*/ INC THREE /*A
LOOP3: DJNZ R1,LOOP FINISHI: SJMP $
5.14 外部数据RAM 从2000H 开始有100个数据,现要将它们移到从2030H 开始的区域,试编写有关程序。 解:
参考程序如下(1):
MOV DPTR,#2000H MOV A,#63H MOV R0,#100 ADD A,DPL MOV DPL,A
LOOP: MOVX A,@DPTR /*取出最后一个数*/
PUSH DPL PUSH A
MOV A,DPL ADD A,#30H MOV DPL,A POP A
MOVX @DPTR,A POP DPL DEC DPL
DJNZ R0,LOOP SJMP $
参考程序如下(2):
MOV R0,#100
MOV DPTR,#2063H
LOOP: MOVX A,@DPTR
MOV R1,A MOV A,DPL ADD A,#30H MOV DPL,A MOV A,R1 MOVX @DPTR,A MOV A,DPL SUBB A,#30H MOV DPL,A DEC DPL
DJNZ R0,LOOP SJMP $
5.15 从内部数据RAM 的BLOCK 开始有一个无符号数数据块,长度存于LEN 单元,求出数据块中的最小元素,并将其存入MINI 单元。要求使用比较条件转移指令CJNE 。 解:
参考程序如下:
LEN DATA 20H MINI DATA 21H BLOCK DATA 22H MOV R0,LEN MOV R1,#BLOCK
MOV A,R0 /*检查数据长度是否0*/ JZ FINISH MOV MINI,@R1
LOOP: MOV A,@R1 INC R1
CLR C
CJNE A,MINI,LOOP1 SJMP LOOP2
LOOP1: JNC,LOOP2
MOV MINI,A
LOOP2: DJNZ R0,LOOP FINISH: SJMP $
5.20 若累加器A 中存放的是一个十六进制数,则将它转换为相应的ASCII 码,并将结果存入20H RAM单元,若A 中存放的不是十六进制数,则将20H 单元置为FFH, 试编写有关程序。 解:
参考程序入下:
MOV R1, A ANL A, #0F0H CJNE A, #00H,REL Clr c
CJNE A, #09H, LOOP SJMP LOOP1 (=9)
LOOP: JC LO0P1 (
ADD A,#07H (>9) LOOP1: ADD A,#30H MOV 20H,A SJMP $
REL: MOV 20H,#0FFH
SJMP $
7.1 用8031单片机的P1口和微型打印机连接以输出数据。数据传送采用中断方式。现要把外部数据RAM 中从20H 单元开始的100个数据送到打印机中去打印。试写出有关的程序,包括主程序和中断服务程序。
解:本题采用中断方式,用ACK 加到INTO 作为中断请求信号,用一个4输入译码器进行部分地址译码,系统的硬件连接图如下图所示:
主程序:
SETB EA SETB EX0 SETB PX0 SETB IT0
MOV RO,#20H MOV R1,#0F0H MOV R2,#99 MOVX A,@R0 MOVX @R1,A LOOP: SJMP $
中断服务程序:
ORG 0003H LJMP INT0
INT0: PUSH PSW PUSH ACC INC R0 MOVX A,@R0 MOVX @R1,A DEC R2 MOV A,R2 JNZ NEXT CLR EXO NEXT: POP ACC POP PSW RETI
7.3 用8255芯片扩展单片机的I/0口。8255的A 口用做输入,A 口的每一位接
一个开关,用B 口作为输出,输出的每一位接一个显示发光二极管。现要求某个开关接1时,相应位上的发光二极管就亮(输出为0),试编写相应的程序。
VCC
地
解:设8255的A 口地址为70H, B口地址为71H, C口地址为72H, 控制寄存器地址为73H 。
8255的工作方式为: A口:方式0,输入 B口:方式0,输出 C口:无关
由此可以确定8255的工作方式控制字为10010000H, 即90H 。有关程序如下:
MOV RO,#73H MOV A,#90H MOVX @R0,A
LOOP: MOV RO,#70H
MOVX A,@R0 CPL A INC RO MOVX @R0,A
SJMP LOOP
7.8 外部RAM 以DAT1开始的数据区中有100个数,现要求每隔150ms 向内部RAM 以DAT2开始的数据区中传送10个数。通过10次传送把数据全部传送完。以定时器1作为定时,8155作为接口芯片。试编写有关的程序。单片机时钟频率为6MHz 。 解:
现要求定时值为150ms ,在单片机时钟频率为6MHz 的情况,这个值已超过定时器可能提供的最大定时值。为了能够实现150ms 的定时值,可采用定时器定时和软件计数器相结合的方法。本题可设定时器的定时值为50ms ,另设一个软件计数器,初值为3。每50ms 定时时间到时,产生中断,在中断服务程序中使软件计数器减1,这样到软件计数器减到0时,就获得了150ms 的定时。
先计算50ms 定时所需的定时初始值。这时需采用定时器方式1,即16位计数器方式。故定时器初值为:
X=216-(50*10-3/(2*10-6)= 65536-25000 = 40536 = 95E8H
本题采用定时器1定时,工作方式为1,TH1初值为9EH,TL1初值为58H 。中断服务程序入口为001BH 。相关程序如下:
ORG 001BH LJMP BRT1
START: ORG 2000H MOV TMOD,#01H MOV TH1,#9EH MOV TL1,#58H MOV IE,#88H SETB TR1
MOV DPTR,#DAT1 MOV RO,#DAT2 MOV R1,#10 MOV R2,#10 MOV R3,#3 LOOP: SJMP $
中断服务程序:
BRT1: MOV TH1,#9EH MOV TL1,#58H
DJNZ R3,NEXT2
NEXT1: MOVX A,@DPTR MOV @RO,A INC DPTR INC R0
DJNZ R2,NEXT1 MOV R3,#3 DJNZ R1,NEXT2 CLR TR1 NEXT2: RETI