《单片微型计算机与接口技术》思考题与习题解答01 下载本文

《单片微型计算机与接口技术》思考题与习题解答 第0章 基础知识

0.1 将下列十进制数转换为十六进制数:64,98,80,100,125,255。 0.1 40H,62H,50H,64H,7DH,FFH

0.2 将下列十六进制无符号数转换为十进制数:32CH,68H,I)5H,100H,B78H,3ADH。 O.2 812,104,213,256,2936,941

0.3 写出下列十进制数的原码和补码,用8位或16位数填人表1中(要求用十六进制数表示)。

表1

十进制数 28 -28 l00 -130 0.3

十进制数 28 -28 100 -130 原码 1CH 9CH 64H 8082H 补码 1CH E4H 64H FF7EH 十进制数 250 -347 928 -928 原码 FAH 815BH 03AOH 83AOH 补码 FAH FEA5H 03AOH FC60H 原码 补码 十进制数 250 -347 928 -928 原码 补码 0.4 用十进制数写出下列补码表示的机器数的真值:1BH,97H,80H,F8H,397DH,7AEBH,9350H,CF42H。

O.4 机器数的真值分别为:27,233,-128,-8,14717,31467,-27824,-12478

0.5 用补码运算完成下列算式,并指出溢出OV和进位CY:

(1) 33H+5AH (2) -29H-5DH (3) 65H-3EH (4) 4CH-68H O.5 (1) 33H+5AH=8DH,OV=1,CY=O (2) -29H-5DH=7AH,OV=0,CY=1

(3) 65H-3EH=27H,OV=0,CY=1 (4) 4CH-68H=E4H,0V=O,CY=O 0.6 将表2中的十进制数按要求转换,用十六进制数填入。

表2

十进制数 38 255 483 764 1000 1025 压缩BCD数 非压缩BCD数 ASCII码 1

O.6

十进制数 38 255 483 764 1000 1025 压缩BCD数 38H 255H 483H 764H 1000H 1025H 非压缩BCD数 0308H 020505H 040803H 070604H 01000000H 01000205H ASCII码 3338H 323535H 343833H 373634H 31303030H 31303235H 0.7 写出下列ASCII码表示的十六进制数(如313035H为105H):374341H,32303030H,3841353DH。

0.7 ASCIl码表示的十六进制数分别为:105H,7CAH,200¨。H,8A50H

第1章 MCS-51单片机

1.1 什么是嵌入式系统?其控制核心有哪几种类型? 1.1 见绪论

1.2 单片微型计算机与微处理器在结构上和使用中有什么差异?单片机和DSP在使用上有什么差别?

1.2 单片微型计算机是包含CPU、存储器和I/O接口的大规模集成芯片,即它本身包含了除外部设备以外构成微机系统的各个部分,只需接外设即可构成独立的微机应用系统。微机处理器仅为CPU,CPU是构不成独立的微机系统的。DSP是数据处理的专用芯片,单片机主要用做控制,也具有简单的数据处理能力。

1.3 51系列单片机内部有哪些功能部件? 1.3 见1.1.1节

1.4 51系列单片机有哪些品种?结构有什么不同?各适用于什么场合? 1.4 见绪论

1.5 51系列单片机的存储器可划为几个空间?各自的地址范围和容量是多少?在使用上有什么不同? 1.5 见表1-5

1.6 在单片机内部RAM中,哪些字节有位地址,哪些没有位地址?特殊功能寄存器SFR中哪些可以位寻址?有什么好处? 1.6 见表1-1和表1-2

1.7 已知PSW=10H,通用寄存器R0~R7的地址分别是多少?

1.7 当PSw=10H,表明选中的为第二组通用寄器RO~R7的地址为10H~17H

1.8 程序存储器和数据存储器可以有相同的地址,而单片机在对这两个存储区的数据进行操作时,不会发生错误,为什么?

1.8 序存储器和数据存储器尽管地址相同,但在数据操作时,所使用的指令不同,选通信号也不同,因此不会发生错误。

1.9 填空:

堆栈设在 存储区,程序存放在 存储区,I/0接口设置在 存储区,中断服务程序存放在 存储区。

2

1.9 内部数据 程序 外部数据 程序

1.10 若单片机使用频率为6MHz的晶振,那么状态周期、机器周期和指令周期分别是多少?

1.10 振荡周期=0.1667us,机器周期=2us,指令周期=2~8us

1.11 复位时,A= ,PSW= ,SP= ,P0~P3= 1.11 A=0,PSW=0,SP=07,P0~P3=FFH

第2章 指令系统

2.1 MCS-51单片机有哪几种寻址方式,适用于什么地址空间?用表格表示。 2.1 见2.1节

2.2 MCS-51单片机的PSW程序状态字中无ZERO(零)标志位,怎样判断某内部数据存储单元的内容是否为O?

2.2 因为累加器A自带零标志,因此,若判断某内部RAM单元的内容是否为零,必须将其内容送到A,通过 JZ指令即可进行判断。

2.3 设A=0,执行下列两条指令后,A的内容是否相同,说明道理。 (1) MOVC A,@A+DPTR (2) MOVX A,@DPTR

2.3 当A=O时,两条指令的地址虽然相同,但操作码不同,MOVC是寻址程序存储器,MOVX是寻址外部数据存储器,送入A的是两个不同存储空间的内容。

2.4 指出下列各指令中操作数的寻址方式

指 令 ADD A,40H PUSH ACC MOV B,20H ANL P1,#35H MOV @R1,PSW MOVC A,@A+DPTR MOVX @DPTR,A 目的操作数寻址方式 源操作数寻址方式 2.4 目的操作数 源操作数 寄存器 直接 SP间接寻址 直接 直接 直接 直接 立即 寄存器问址 直接 寄存器 变址 寄存器间址 寄存器

2.5 执行下列程序段 MOV A,#56H ADD A,#74H ADD A,ACC

后,CY= ,OV= ,A= 。 2.5 CY=1,OV=0,A=94H

2.6 在错误的指令后面括号中打×。

MOV @R1,#80H ( ) MOV R7,@R1 ( ) √ ×

3

MOV 20H,@R0 ( ) MOV R1,#0100H ( ) √ × CPL R4 ( ) SETB R7,0 ( ) × × MOV 20H,21H ( ) ORL A,R5 ( ) √ √ ANL R1,#OFH ( ) XRL P1,#31H ( ) × √ MOVX A,2000H ( ) MOV 20H,@DPTR ( ) × × MOV A,DPTR ( ) MOV R1,R7 ( ) × × PUSH DPTR ( ) POP 30H ( ) × √ MOVC A,@R1 ( ) MOVC A,@DPTR ( ) × × MOVX @DPTR,#50H ( ) RLC B ( ) × × ADDC A,C ( ) MOVC @R1,A ( ) × ×

2.6 √ × √ × × × √ √ × √ × × × × × √ × × × × × ×

2.7 设内部RAM中(59H)=50H,执行下列程序段: MOV A,59H MOV R0,A MOV A,#0 MOV @R0,A MOV A,#25H MOV 51H,A MOV 52H,#70H

问A= , (50H)= , (51H)= , (52H)= 。 2.7 A=25H,(50H)=O,(51H)=25H,(52H)=70H

2.8 设SP=60H,内部RAM的(30H)=24H,(31H)=10H,在下列程序段注释的括号中填执行结果。

PUSH 30H ;SP=( ), (SP)=( ) PUSH 3lH ;SP=( ), (SP)=( ) POP DPL ;SP=( ), DPL=( ) POP DPH ;SP=( ), DPH=( ) MOV A,#00H MOVX @DPTR,A

最后执行结果是( )。 2.8 SP=(61H),(SP)=(24H) SP=(62H),(SP)=(10H) SP=(61H),DPL=(10H)

SP=(60H),DPH=(24H)执行结果将0送外部数据存储器的2410单元。

4

2.9 对下列程序中各条指令作出注释,并分析程序运行的最后结果。 MUV 20H,#0A4H MOV A,#017)6H MOV R0,#20H MOV R2,#57H ANL A,R2 0RL A,@R0 SWAP A CPL A ORL 20H,A SJMP $

2.9 程序运行后内部RAM(20H)=B4H,A=90H

2.10 将下列程序译为机器码。 机器码 源程序

LA: MOV A,#01H LB: MOV P1,A RL A

CJNE A,#10,LB SJMP LA

2.10 机器码 源程序

7401 LA:M()V A,#01H F590 LB:M()V P1,A 23 RL A

B40AFA CJNE A,#10,LB 80F6 SJMP LA

2.11 将累加器A的低4位数据送P。口的高4位,P。口的低4位保持不变。 2.11 ANL A,#0FH SWAP A

ANL P1.#OFH ORL P1,A SJMP $

2.12 编程将R0(R2)的内容和R1(R3)的内容相交换。 2.12 MOV A,RO XCH A,R1 MOV R0,A SJMP $ 2.12 MOV A,R2 XCH A,R3 MOV R2,A SJMP $

2.13 试用3种方法将A累加器中的无符号数乘4,积存放于B和A寄存器中。 2.13

(1)利用乘法指令 MOV B,#04H

5

MUL AB SJMP $ (2) 利用位移指令 RL A RL A

MOV 20H。A ANL A,#03H MOV B,A MOV A,20H ANL A,#OFCH SJMP $

(3) 用加法指令完成 ADD A,ACC

MOV RO,A :RO=2A MOV A,#0 ADDC A。#0

MOV B,A ;B存2A的进位 MOV A,RO ADD A,ACC

MOV R1,A ;R1=4A MOV A,B

ADDC A,B ;进位x 2 MOV B,A ;存积高位 MOV A,R1 ;存积低位 SJMP $

2.14 编程将内部RAM 40H单元的中间4位变反,其余位不变放回原单元。 2.14 方法1:XRL 40H,#3CH SJMP $

方法2:MOV A,40H CPL A

ANL A,#3CH ANL 40H,#OC3H ORL 40H,A

SJMP $

2.15 有两个BCD码数存放在(20H)和(21H)单元,完成(21H)+(20H)=>(23H)(22H)。

(24H)+(25H)=>(23H)(22H)

2.15 MOV A,20H ADD A,21H DA A

MOV 22H,A ;存和低字节 MOV A,#O ADDC A,#0

MOV 23H,A ;存进位 SJMP $

6

2.15 MOV A,24H ADD A,25H DA A

MOV 22H,A ;存和低字节 MOV A,#O ADDC A,#0

MOV 23H,A ;存进位 SJMP $

2.16 如果R0的内容为0,将R1置为0,如R0内容非0,置R1为FFH,试进行编程。 2.16 MOV A.R0 JZ ZE

MOV R1.#OFFH SJMP $

ZE:MOV R1,#O SJMP $

2.17 完成(51H)×(50H)=>(53H)(52H)的编程(式中均为内部RAM)。 2.17 MOV A,50H MOV B,51H MUL AB MOV 53H。B MOV 52H,A

SJMP $

2.18 将P1.1和P1.0同时取反10次。(将P1.2和P1.0同时取反10次) 2.18 MOV R7,#0AH WOP:XRL P1,#03H DJNZ R7,WOP SJMP $

2.18 MOV R7。#0AH

WOP:XRL P1,#05H

DJNZ R7,WOP SJMP $

2.19 将内部RAM单元3字节数(22H)(21H)(20H)×2送(23H)(22H)(21H)(20H)单元。 2.19 单片机的移位指令只对A,且只有循环移位指令,为了使本单元的最高位移进下一单元的最低位,必须用大循环移位指令移位4次。

ORG O CLR C MOV A,20H RLC A MOV 20H,A MOV A,21H RLC A MOV 21H,A MOV A,22H

7

RLC A

MOV 22H.A MOV A,#O RLC A MOV 23H,A SLMP $

第3章 程序设计

3.1 编写程序,把片外数据存储器0000H~0050H中的内容传送到片内数据存储器20H~70H中。

3.1 因为是多个单元操作,为方便修改地址,使用问址操作。片外地址用DPTR指示.只能用M()Vx指令取数到A,片内地址用RO或R1指示,只能用MOV指令操作,因此,循环操作外部数据存储器一A一内部数据存储器。 ORG OOOOH

MOV DPTR,#0000H

MOV R0,#20H

LOOP:MOVX A,@DPTR MOV @R0,A

INC DPTR INC R0

CJNE R0,#71H, LOOP SJMP $

3.2 编写程序,实现双字节加法运算,要求RIR0+R7R6=>(52H)(51H)(50H)(内部RAM)。 3.2 要注意两高字节相加应加低字节相加时产生的进位,同时要考虑最高位的进位。

ORG 0 MOV A,RO ADD A,R6 MOV 50H,A MOV A,R7 ADDC A,R1 MOV 51H,A MOV A,#0 ADDC A,#O MOV 52H,A SJMP$

3.3 设X在累加器A中(0≤X≤20),求X2并将平方数高位存放在R7中,低位存放在R6中。试用查表法编出子程序。 3.3 A中放X(小于14H)的数,平方表的一个数据占2个字节,可用BCD码或二进制数存放(如A中放的是 BCD码,则要先化成二进制数再查表)。

ORG 0

MOV DPTR,#TAB ADD A,ACC ;A*2 PUSH ACC

MOVC A,@A+DPTR

8

MOV R7,A POP ACC INC A

MOVC A,@A+DPTR MOV R6,A

SJMP $

TAB:DB 00,00,00,01,OO,04,OO,09,OO,16H,? DB? 04H,00

3.4设内部RAM的20H和21H单元中有两个带符号数,将其中的大数存放在22H单元中,编出程序。

3.4 先用异或指令判两数是否同号,在同号中判大小,异号中正数为大。 ORG 0 MOV A,20H XRL A.21H ANL A,#80H JZ CMP

JB 20H.7,BG AG:MOV 22H,20H SJMP $

BG:MOV 22H,21H

SJMP $

CMP:MOV A,20H CJNE A,21H,GR GR:JNC AG MOV 22H,21H

SJMP $

3.5若单片机的晶振频率为6MHz,求下列延时子程序的延时时间。 DELAY: MOV R1,#0F8H LOOP: MOV R3,#0FBH DJNZ R3,$ DJNZ R1,LOOP RET

3.5 fosc=6MHz,MC=2us

机器周期数 DELAY:MOV R1,#OF8H 1 LOOP: MOV R3,#0FBH 1 DJNZ R3,$ 2 DJNZ R1,LOOP 2

RET 2 (1+2+(1+2×251+2)×248)×2us=250.48ms

3.6 编程将内部数据存储器20H~24H单元压缩的BCD码转换成ASCII码存放在25H开始的单元内。

3.6 将待转换的数分离出高半字节并移到低4位加30H;再将待转换的数分离出低半字节并加30H,安排好源地址和转换后数的地址指针,置好循环次数。 ORG 0000H

9

MOV R7,#05H MOV RO,#20H

MOV R1,#25H NET:MOV A,@RO ANL A,#OFOH SWAP

ADD A,#30H MOV @R1,A INC R1

MOV A,@RO ANL A,#OFH ADD A,#30H MOV @R1,A INC R0 INC R1

DJNZ R7,NE SJMP $ END

3.7 从内部存储器30H单元开始,有16个数据,试编一个程序,把其中的正数、负数分别送40H和50H开始的存储单元,并分别将正数、负数和零的个数送R4,R5,R6。 3.7 片内RAM间址寄存器只有Ro和R1,而正数、负数和零共需3个寄存器指示地址,这时可用堆栈指针指示第3个地址,POP和PUSH指令可自动修改地址。RO指正数存放地址,Rl指负数存放地址,SP指源数据存放的末地址,POP指令取源数据,每取一个数地址减1。 ORG 0000H MOV R7,#10H MOV A,#0 MOV R4,A MOV R5,A MOV R6,A MOV R0,#40H MOV R1,#50H

MOV SP,#2FH NEXT:POP ACC JZ ZER0 JB ACC.7,NE INC R4 MOV @RO,A INC R0 AJMP DJ NE:INC R5 MOV @R1,A INC R1

AJMP DJ ZER0:INC R6

DJ:DJNZ R7,NEXT

10

SJMP $ END

3.8 内部存储单元40H中有一个ASCII字符,试编一个程序给该数的最高位加上奇校验。 3.8 可直接用P标志判断(JB P,ret) ORG 0000H MOV A。40H

JB P,EN ;奇数个1转移

0RL A,#80H ;偶数个1最高位加“1” EN:SJMP$

3.9 编写一段程序,将存放在自DATA单元开始的一个四字节数(高位在高地址)取补后送回原单元。

3.9 取补不同于求补码,求补码应区别正、负数分别处理,而取补不分正、负,因正、负数均有相对于模的补数。可用取反加l求补,也可用模(00H)减该数的方法求补。

ORG 0000H MOV R7,#03H MOV R0,#DATA MOV A,@RO CPL A ADD A,#01 MOV @RO,A AB:INC RO MOV A,@RO CPL A ADDC A,#O DJNZ R7,AB SJMP $

3.10 以BUFl为起始地址的外存储区中,存放有16个单字节无符号二进制数,试编一个程序,求其平均值并送BUF2单元,余数存在BUF2—1单元。 3.10 16个单字节累加应用ADD指令而不能用ADDC指令,和的低位存A,当和超过一个字节时,和的高字节存于B,并要加低位相加时产生的进位,16个单字节加完后,采用右移4次进行除16求平均值的运算,商在 BUF2单元,余数在BuF2-1单元。 0RG 0000H MoV R7,#0FH MOV R0,#BUFl MOV B,#0 MOV A,@R0

MOV R2,A

NEXT:MOV A,R2 INC R0 ADD A,@R0 MOV R2,A MOV A,B ADDC A,#0 MOV B,A

11

DJNZ R7,NEXT ;以上完成求和 MOV R6,#04H MOV BUF2,A

MOV BUF2-1,#O NEX:CLR C MOV A,B RRC A MOV B,A MOV A,BUF2 RRC A

MOV BUF2,A MOV A,BUF2-1 RRC A

MOV BUF2-l,A DJNZ R6,NEX SJMP $

;以上完成除16运算

3.11 将内部RAM的20H单元中的十六进制数变换成ASCII存入22H,21H单元,高位存入22H单元,要求用子程序编写转换部分。

3.11 将20H单元的内容分解为高4位和低4位,根据是否大于9分别进行加37H和30H处理。

0RG 0000H MOV A,20H ANL A,#0F0H SWAP A

ACALL ASCII MOV 22H,A MOV A.20H ANL A,#0FH ACALL ASCII MOV 21H,A SJMP $ END

ASCII:CJNE A,#0AH,NE NE:JC A30 ADD A,#37H RET

A30:ADD A,30H RET

3.12 编写一段程序,以实现图中硬件的逻辑运算功能。

12

3.12要注意,位的逻辑运算其中一个操作数必须在C。

ORG 0000H MOV C,20H ANL C,2FH CPL C

ORL C,/2FH CPL C

ANL C,53H MOV P1.0,C SJMP $ END

3.13 用位操作指令实现下面的逻辑方程(×表示逻辑乘,+表示逻辑加): P1.2=(ACC.3×P1.4×-ACC.5)+(-B.4×-P1.5) 3.13 ORG 0000H MOV C,ACC.3 ANL C。P1.4 ANL C,/ACC.5 MOV 20H,C MOV C,B.4 CPL C

ANL C,/P1.5 ORL C,20H MOV P1.2,C SJMP $

END

3.14 试编写一个三字节无符号数乘一字节的乘法程序。

3.14 设一字节乘数存放在R1,三字节的被乘数存放在data开始的内部RAM单元,且低字节存放在低位地址单元,R0作为被乘数和积的地址指针,用MUL指令完成一字节乘一字节,每一次部分积的低位加上一次部分积的高位,其和的进位加在本次部分积的高位上,并暂存,三字节乘一字节共需这样3次乘、加、存操作.以R7作循环3次的计数寄存器。 ORG 0000H MOV R7,#03H MOV R0,#data

MOV R2,#0 NEXT:MOV A,@R0

13

MOV B,R1 MUL AB ADD A,R2 MOV @RO,A

MOV A,#O ADDC;A,B MOV R2,A INC R0

DJNZ R7,NEXT MOV @R0,B SJMP $ END

第4章 单片机的C语言

4.1 改正下面程序的错误。

4.1 1:#include 本程序有如下错误: 2:main()

3:{a=c; ①变量a,c必须先定义再引用

4:int a=7,c; ②第5句调用函数后必须加分号 . 5:delay() ③main()函数没有反大括号

6:void delay(); ④被调函数delay()在main()后面,必须在前面先声明 7:{

8:char i; ⑤第6句函数说明语句后的分号应去掉 9:for(i=O;i<:255;i++); 10:}

4.2 试说明为什么xdata型的指针长度要用2个字节?

4.2 因为xdata是外部数据存储器,最大可有64KB的存储单元,xdata指针是表示外部数据存储单元的地址,要表示64KB个单元地址,所以必须用2个字节,共16位表示。

4.3 定义变量a、b、c; a为内部RAM的可位寻址区的字符变量; b为外部数据存储区浮点型变量;c为指向int型xdata区的指针。 4.3 bdata char a; xdata float b:

xdata int~c;

4.4 编程将8XX51的内部数据存储器20H单元和35H单元的数据相乘,结果存到外部数据存储器中(位置不固定)。 4.4 main()

{char data*pl,*p2; xdata int a; p1=0x20; p2=0x35; a=*p1*(*p2);

}

4.5 将如下汇编程序译成C程序(等效即可)。 ORG 0000H MOV P1,#04H

14

MOV R6,#0AH MOV R0,#30H CLR P1.O SETB P1.3 ACALL TLC SJMP $

TLC:MOV A,#0 CLR P1.3 MOV R5,#08

LOOP: MOV C,P1.2 RLC A SETB P1.0 CLR P1.O DJNZ R5,LOOP MOV @RO,A INC R0

DJNZ R6,TLC2543 RET END

4.5 #include(reg51.h)

#define uchar unsigned char sbit P1_0=P1^0;

sbit Pl_l=P1^1; sbit P1_2=P1^2; sbit P1_3=P1^3; sbit msb=ACC^7; sbit lsb=ACC^0; uchar tlc(void); main( ){ uchar *P; P1=0x04; P=0x30; P1_0=0;

Pl_3=1;

for(i=O;i<10;i++) {*P=tlc( ); P++:}

}

uchar tlc(void){ uchar i,y; ACC=0; Pl_3=0;

for(i=0:i<8:i++){

P1_1=msb; /*发出ACC的低位*/

15

y=ACC<<1; /*ACC右移1位*/

lsb=P1_2; /*接收一位放在ACC的高位*/ P1_0=1; P1_0=O; }

return y; } 4.6 8051的片内数据存储器25H单元中放有一个0~10的整数,编程求其平方根(精确到5位有效数字),将平方根放到30H单元为首址的内存。 4.6 方法l:使用查表法

float code tab[11]={0,1,1.4142,1.7321,2,2.2361, 2.4495,2.6458,2.8284,3,3.1623}: main()

{char data*P1; float data*P2; P1=0x25; P2=0x30;

*P2=tab[*P1]; }

方法2:使用库函数

#lnclude main(){ float*P2; char*P1;

P1=0x25;

*P2=sqrt(*P1); }

4.7 完成逻辑表达式P1.2=P1.4×ACC.0+ACC.7(“×”表示逻辑与,“+”表示逻辑或)。 4.7 #include sbit P12=P1^2: main()

{P12=~(P1^4&ACC^0)|ACC^7;}

4.8 将外部RAM的10H~15H单元的内容传送到内部RAM的10H~15H单元。 4.8 #lnclude main()

{

char pdata *m; char data *n; P2=0;

for(m=0x10;m<=0x15;m++) {n=m;*n=*m;}

}

4.9 内部RAM的20H、21H和22H、23H单元分别存放着两个无符号的16位数,将其中的大数置于24H和25H单元。

16

4.9 #define uint unsigned int main() {

uint data*m,*n,*P; for(;;){

m=0x20;n=0x22;P=0x24; if(*m<*n)*P=*n; else *P=*m: } }

4.10 将内部RAM 21H单元存放的BCD码数转换为二进制存入30H为首址的单元,BCD码的长度存放在20H单元中。 4.10 main() {

int data a=O,*P3: char i,*P1,*P2; Pl=0x20: P2=0x21: P3=0x30;

for(i=O;i<*P1;i++) {

a=a*10+*P2; P2++; }

*P3=a; }

4.11 将内部RAM 30H单元存放的2字节二进制数转换为十进制数存于21H为首的单元中,长度存放于20H单元中。 4.11 main()

{unsigned int a,k,*P3; char i,*P1,*P2: P1=0x20: P2=0x25: P3=0x30;

a=*P3;k=10000;

while(a/k==0)k=k/10; for(i=0;a!=0;i++) {*P2=a/k; a=a%k; P2++; k=k/10: *P1=i: }

第5章 并行口

17

5.1 8XX51的4个I/()端口的作用是什么?8XX51对外的三总线是如何分配的? 5.2 8XX51的4个I/0端口在结构上有何异同?使用时应注意什么? 5.3 为什么说8XX51能全部作为I/O口使用的仅有P1端口? 5.1~5.3 参阅5.1节

5.4 在例5-2中有如下语句:

MOV P1,#0FFH ;高4位的LED全灭,低4位输入线送“1” ABC: MOV A,P1 ;读P1口引脚开关状态,并送入A

为什么执行了ABC语句后A的值低4位为开关状态,而不是前一句的FFH,那么它的高4位值是什么呢?

5.4 由内部结构图可知,MOV P1,#0FFH将使锁存器Q=1,同时Q=0,VT截止,当执行MOV A,P1时,读引脚信号有效,低4位的开关电平通过门2进入内部总线到A,而读锁存器信号无效,门1关闭,Q的信号进不了内部总线,高4位没有引脚新的电平变化,由于VT截止,二极管也截止,进入门2的是VT的漏极电压Vcc,因此,高4位通过门2读入的均是高电平即1111 B。

5.5 利用8XX51的P1口,监测某一按键开关,使每按键一次,输出一个正脉冲(脉宽随意),画出电路并编出程序。 5.5 用P1.7监测按键开关,P1.0引脚输出正脉冲,正脉冲的产生只需要将P1.0置零、置1、延时、再置零即可。P1.0接一示波器可观察波形。如果再接一发光二极管,可观察到发光二极管的闪烁。电路设计图如习题5.5图。 汇编语言程序 ORG 0000H ABC:CLR P1.0 SETB P1.7

JB P1.7,$ ;等键按下 JNB P1.7,$ ;待键弹起 SETB P1.0

MOV R2,#0 DAY:NOP NOP

DJNZ R2,DAY

SJMP ABC

C语言编程

sfr P1=0x90: sbit p1_O=P1^O; sbit p1_7=P1^7; main(){

unsigned char i; while(1){ P1=0x80:

do{}while(p1_7==1);/*等键按下*/ do{}while(p1_7==O);/*等键弹起*/

p1_0=1; for(i=O;i<255;i++); }}

18

5.6 利用8XX51的P1口控制8个发光二极管LED。相邻的4个LED为一组,使两组每隔0.5s交替发亮一次,周而复始,画出电路并编写程序(设延时0.5s子程序为D05,已存在)。

5.6 电路见习题5.6图,初始值送0FH到P1,再和0FFH异或从P1口输出,或使用SWAP A指令。然后从P1口输出,循环运行,注意输出后要延时。

汇编语言程序 ORG 0000H MOV A,#OFH ABC:MOV P1,A ACALL D05 SWAP A SJMP ABC

D05:MoV R6,250 DY:MOV R7,250 DAY:NOP NOP

DJNZ R7,DAY DJNZ R6,DY RET END

C语言编程

sfr P1=0x90; main( ){ int i;

19

P1=0xf0; while(1){ P1=~P1;

fOr(i=0;i<5000;i++); }

5.7 用89C51/89S51并行口设计显示?个数码的电路,使数码管循环显示“O”~“F”。 5.7 如使用共阴极数码管,阴极接地,阳极a~g分别接P0~P3的某个口的7位,将0~F的段码列成表,表的内容顺次从该口输出。如数码管接P3口。 汇编语言程序 0RG 0000H

MOV DPTR,#TAB AGAIN:MOV R0,#0 NEXT:MOV A,RO MOVC A,@A+DPTR MOV P3,A MOV R7,#0 DAY:NOP NOP

DJNZ R7,DAY INC R0

CJNE R0,#10H,NEXT

SJMP AGAIN ;段码表(略) TAB:DB 3FH,06H? END

C语言程序

#include(reg51.h)

#defint uint unsigned int #define uchar unsigned char main(){ umtj; uchar i; uchar code

tab[16]={0x3f,0x06??);,/*段码表(略)*/ while(1){ for(i=O;i<=15;i++) {P3=tab[i]};

for(j=O;j<10000;j++);/*延时*/ } }

5.8 设计一个能显示4位数码的电路,并用C语言和汇编语言编程使“8”能跑马显示8遍。

5.8 电路设计见习题5.8图,分别用汇编语言和C语言的编程如下: 汇编语言程序

20

0RG 0000H MOV A,#08H

M()V DPTR,#TAB MOVC A,@A+DPTR MOV P1,A

MOV R2,#08H AGAIN:M()V A,#01 NEXT:M()V P3,A ACALL DAY RL A

CJNE A,#10H,NEXT DJNZ R2,AGAIN TAB:DB 3FH,06H? END

C语言程序

#include

#definc uint unslgned int #deflne uchar unsigned char main(){ uchar code

tabl[]={0x3f,0s06?} uchar i,m; uint j;

for(m=O;m<8;i++){ P3=0x01:

for(i=0;i<4;i++){ P1=tabl[8] P3<<=1:

for(j=0;j<=25000;j++); }}}

21

5.9 利用89C51/89S51并行口设计8×8的矩阵键盘并用箭头标明信号的方向。

5.9 P1口的8根线接行线,输出行扫描信号,P3口的8根线接列线,输入回馈信号。见习题5.9图。

第6章 中断

6.1 8XXSl有几个中断源?各中断标志是如何产生的,又如何清除? 6.2 8XX51中断源的中断请求被响应时,各中断入口地址是多少?在什么物理存储空间? 6.3 MCS-51系列单片机的中断系统有几个优先级?如何设定? 6.4 简述8XX51中断处理的过程,画出流程图。 6.1~6.4 参见 6.1节~6.2节

6.5 用8XX51的P1口接8个LED发光二极管,由INT0接一消抖开关,开始P1.0的LED亮,以后每中断一次,下一个LED亮,顺序下移,且每次只一个LED亮,周而复始。画出电路图,并编制程序。

6.5 电路设计见习题6.5图 汇编语言程序 ORG 0000H AJMP MAlN 0RG 0003H

RL A ;中断服务 MOV P1.A RETI

MAIN:MOV A,#0FEH

MOV P1,A ;第一灯亮 SETB EA SETB EX0 SETB IT0 SJMP$ C语言程序

#include int0() interrpt 0{

22

P1=P1<<1|0x01; }

main(){ P1=0xfe; EA=1;EX0=1; IT0=1;

do{}whik(1);}

汇编语言中只有一个中断源,不存在占用别的中断源向量地址问题,程序顺序排下,应注意程序的执行过程。C语言无循环移位指令,移位后,后面补零,因此和01相或。

6.6 在题6.5电路的基础上,要求8个LED同时亮或同时灭,每中断一次,变反一次,编出程序。 6.6 略

6.7 要求同题6.6,要求亮、灭变换5次(一亮,一灭为一次),编出程序。 6.7 汇编语言程序 ORG O000H AJMP MAIN

ORG 0003H ;中断服务 XRL P1,#OFFH DJNZ R0,NE

CLR EA NE:RETI

ORG 0030H MAIN: SETB EA SETB EXO SETB ITO

MOV P1,#OFFH MOV R0,#OAH

SJMP$ ;等待中断 C语言程序

#include char i:

ic()itrrupt 0{ i++:

if(i<=10)P1=~P1:

23

eIse EA=O: }

main()

{EA=1;EX0=1;IT0=1; P1=0xff: for(;;);/*等待中断*/

}

因一亮一灭为一次,所以共10次。

6.8 利用8XX51的并行口接2个数码管,显示INT1中断次数(次数不超过FFH)。 6.8两个数码管阳极经驱动器接P1口,阴极分别接P3.0、P3.1。 #include void intr(void) void delay(void);

unsigned char a,b,i=0;

unsigned char code

tab[16]={0x3f,0x06,0x5b,Ox4f,0x66,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x73}:

sbit p3_O=P3^0; sbit p3_1=P3^1; main(){ a=tab[O]; b=tab[0]; p3_0=O; p3_1=0; EA=1; EX0=1; IT0=1; for(;;){

p3_O=1; p3_1=0; P1=b: delay();

p3_0=O; p3_1=1; P1=a: delay(); }}

void intr()interrupt 0{ unsigned charj,k; EX0=O; i++;

j=i&0x0f; k=i&0xf0; k>>=4; a=tab[k];

24

b=tab[j]; EX0=1;}

void delay(void){ int x;

for(x=0;x<1000;x++); }

第7章 定时计数器

7.1 8XX51单片机内部设有几个定时/计数器?它们是南哪些专用寄存器组成的? 7.2 8XX51单片机的定时/计数器有哪几种工作方式?各有什么特点?

7.3 定时/计数器用做定时时,其定时时间与哪些因素有关?用做计数时,对外界计数频率有何限制? 7.1~7.3参7.1节

7.4 设单片机的fosc=6MHz,定时器处于不同工作方式时,最大定时范围分别是多少? 7.4 方式0:16.38ms,方式1:131ms,方式2:512us

7.5 利用8XX51的T0计数,每计10个脉冲,P1.0变反一次,用查询和中断两种方式编程。

7.5 使用方式2,计数初值c=100H—OAH=F6H 查询方式: 0RG 0000H MOV TMOD,#06H MOV THO,#0F6H MOV TL0,#0F6H SETB TR0

ABC:JNB TF0,$ CLR TF0 CPL P1.0 SJMP ABC 中断方式: ORG 0000H AJMP MAIN ORG OOOOBH CPL P1.0 RETI

MAIN:MOV TMOD,#06H MOV TH0,#OF6H SETB EA SETB ET0 SETB TR0

SJMP $ ;等待中断 C语言程序查询方式: #include sbit p10=P1^O; main(){

25

TMOD=Ox06;THO=-10;TLO=-10; TRO=1:{ while(1)

dO{}while(TF0==0) TF0=0;p10=~p10; }}

中断方式:#include sbit p1_O=P1^O; tov()interrrupt 1 {p1_O=~p1_O; } maln(){

EA=1;ET0=1;TMOD=0x06; TH0=0xf6;TL0=0xf6;TR0=1; while(1);}/*等待中断*/

7.6 在P1.0引脚接一驱动放大电路驱动扬声器,利用T1产生lOOOHz的音频信号从扬声器输出。 7.6 1000Hz的周期为1ms,即要求每500us P1.0变反一次,使用T1方式1,MC=12/fosc=1us,C=216-500us/1us=FE0CH,除TMOD=10H,TH0=FEH,Tl0=0CH外,程序与7.5题相同,注意每次要重置TH0和TL0。

7.7 已知8XX51单片机系统时钟频率为6MHz,利用定时器T0使P1.2每隔350us,输出一个50us脉宽的正脉冲。

7.7 fosc=6MHz,MC=2us,方式2的最大定时为512us,合乎题目的要求。50us时,计数初值为C1=256-25=E7H,350us时,计数初值为C2=256-175=51H 汇编语言程序 ORG 0000H MOV TMOD,#02H

NEXT:MOV TH0,#51H MOV TL0,#51H CLR P1.2 SETB TR0

AB1:JBC TF0,EXT

SJMP AB1 EXT:SETB P1.2 MOV TH0,#0E7H

MOV TL0,#0E7H AB2:JBC TF0,NEXT SJMP AB2 C语言程序

#include

void timet(unsigned char t); sbit p1_2=P1^2 main(){for(;;)

p1_2=O;timer(7); p1_2=1;timer(1); }

26

void timer(unslgned char t) {unsigned char i;

for(i=0;i

TH0=-25/256;TL0=-25%6; TR0=1: While(TF0!=1); TR0=0: }}

上述的计数初值没有考虑指令的执行时间。因此误差较大,查每条指令的机器周期,扣除这些时间.算得 C—E3H,这样误差较小。

7.8 在8XX51单片机中,已知时钟频率为12MHz,编程使P1.0和P1.1分别输出周期为2ms和50us的方波。

7.8 P1.0输出2ms脉冲,P1.1输出50us脉冲。 汇编语言程序 ORG 0000H MOV TMOD,#02H MOV TH0,#06H MOV TL0,#06H SETB TR0

MOV R0,#04H NE: JNB TF0,$ CLR TF0 CPL P1.1 DJNZ R0,NE CPL P1.O AJMP NE C语言程序

#include sbit p11=P1^l; sbit p10=P1^0; main(){ char i;

TMOD=0x02;TH0=06;TL0=06:TR0=1; while(1){

for(i=0;i<4:i++){ do{}while(!TF0); P11=~P11: }

P10=~P10: }}

7.9 设系统时钟频率为6MHz,试用定时器T0。作为外部计数器,编程实现每计到1000个脉冲后,使T1定时2ms,然后T0又开始计数,这样反复循环。 7.9 C语言程序

T0计数1000个脉冲,采用方式1;T1定时2ms,fosc=6MHz,C=-2ms/2us=-1000

27

include

counter(){ TH0=-1000/256; TLO=-1000%6; TR0=1;TR1=0; while(TF0!=1); TF0=0; }

timer(){

TH1=-1000/256;TL1=-1000%6;TR1=1;TR0=0; while(TF1!=0); TF1=0; }

main() TMOD=0x15; for(;;){ counter(): timer():

7.10 利用8XX51单片机定时器T0测量某正单脉冲宽度,已知此脉冲宽度小于10ms,主机频率为12MHz。编程测量脉宽,并把结果转换为BCD码,顺序存放在以片内50H单元为首地址的内存单元中(50H单元存个位)。 7.10 C语言程序

#lnclue sbit p3_2=P3^2; main(){

unsingcd char *P,i; int a;

P=0x50;

TMOD=0x09; TL0=0;TH0=0;

while(P3_2==1);/*等待INT0变低*/ TR0=1;

while(P3_2==0);/*等待-INT0变高*/ while(P3_2==1);/*等待-INT0变低*/

TR0=0; i=TH0;

a=i*256+TL0; for(;a!=O;)

{ /*转换为非压缩IR7D码*/

*P=a; a=a/10;

P++; } }

第8章 串行口

28

8.1 什么是串行异步通信?它有哪些特点?MCS-51单片机的串行通信有哪几种帧格式? 8.1见8.1节

8.2 某异步通信接口按方式3传送,已知其每分钟传送3600个字符,计算其传送波特率。

8.2 方式3为每帧11位数据格式.即3600*11/60=660(波特)

8.3 为什么定时器T1用做串行口波特率发生器时,常采用工作方式2? 若已知系统时钟频率、通信选用的波特率,如何计算其初值?

8.3 T1的方式2模式不需要重装时间常数(计数初值),不影响cPU执行通信程序。设波特率为fboud计数初值为X,依据公式

fbaud=(2smod/32)*(fosc/12(256-X)) 求得X=256-((2smod/32)*(fosc/fbaud))。

8.4 已知定时器T1设置为方式2,用做波特率发生器,系统时钟频率为6MHz,求可能产生的最高和最低的波特率是多少?

8.4最低波特率为,T1定时最大值时,此时计数初值为256,并且SMOD=0,得

fbaud=(1/32)*(fosc/(12(256-0))=61

最高波特率为T1定时最小值且SOMD=1时,得 fbaud=(2/32)*fosc/(12(256-1))=31250

8.5 设甲、乙两机采用方式1通信,波特率为4800,甲机发送O,1,2,?,1FH,乙机接收存放在内部 RAM以20H为首址的单元,试用查询方式编写甲、乙两机的程序(两机的fosc=6MHz)。

8.5取SMOD=1计算TH1=TL1=B2;

;***********************发送查询方式******

ORG 0000H

MOV TMOD,#20H MOV THl,#OB2H MOV TL1,#0B2H SETB TR1

MOV SCON,#40H MOV A,#O

NEXT:MOV SBUF,A TES:JBC T1,ADD1 SJMP TES ADD1:INC A

CJNE A,#20H,NEXT SJMP $ END

;************************发送中断方式********************************* ORG 0000H

AJMP MAIN;转主程序 ORG 0023H ;中断服务 CLR TI INC A

MOV SBUF,A

CJNE A,#20H,RE

29

CLR ES RE:RETI

MAIN:MOV TMOD,#20H;主程序 MOV TH1,#0B2H MOV TL1,#082H SETB TR1

MOV SCON,#40H SETB EA SETB ES MOV A,#O MOV SBUF,A

SJMP$ ;等待中断

;*******************************接收查询方式***************************

ORG 0000H MOV TMOD,#20H MOV TH1,#0B2H MOV TL1,#0B2H SETB TR1

MOV SCON,#50H MOV RO。#20H TEC:JBC R1,REC

SJMP TES REC:MOV @R0,SBUF INC R0

CJNE R0,#40H,TEC

SJMP $ END

;******************************接收中断斤方式**************************** ORG O000H

AJMP MAIN;转主程序 ORG 0023H;中断服务 CLR RI

MOV @RO,SBUF INC R0

CJNF R0,#40,RE CLR ES RE:RETI

MAlN:MOV TMOD,#20H;主程序 MOV TH1,#0B2H MOV TL1,#0B2H SETB TR1

MOV SCON,50H SETB EA SETB ES

SJMP$ ;等待中断 END

30

8.6 一个8XX511单片机的双机通信系统波特率为9600, fosc=12MHz,用中断方式编写程序,将甲机片外RAM 3400H~34AOH的数据块通过串行口传送到乙机的片外RAM 4400H~44AOH单元中去。 8.6

/********************************发送程序***************************/ #include

#define uchar unsigned char VOId int4(void) uchar xdata*P; {P=Ox3400 TMOD=0x20;

TL1=0xfd;TH1=0xfd; SCON=0x40:

TR1=1;EA=1;ES=1; SBUF=*P:

whaile(1);/*等待中断*/ }

void int4(void)interrupt 4 {TI=O: P++: SBUF=*P; if(P==0x34a0)EA=0; }

/***********************接收程序***************************/ #include

#define ucher Unsigeried char void int4(void) char xdata*P: void mian() {P=0x4400: TMOD=0x20; TL1=Oxfd: TH1=0xfd; SCON=0x50;

TR1=1;EA=1;ES=1; for(;;);/*等待中断*/ }

void int4(viod)interrupt 4 {RI=0; *P=SBUF; P++;

if(P==0x44a1)EA=O; }

8.7 数据传送要求同题8.6,要求每帧传送一个奇校验位,编出查询方式的通信程序。 8.7 利用串行通信方式2(波特率固定),采用奇校验方式,将校验位放在TB8中.乙机检验校验位,如正确,则存于片外4400H开始的RAM中,如错误,通知对方重发,R6存放数据

31

块长度。汇编语言程序如下: 发送方

ORG 0000H

MOV DPTR,#3400H MOV R6,#0A1H

MOV SCON,#90H MOV SBUF,R6 L2: JBC TI,L3

AJMP L2

L3: MOV A,@DPTR JB P,L4

SETB TB8 L4: MOV SBUF,A L5: JBC TI,L6

AJMP L5 L6: JBC RI,L7 AJMP L6

L7: MOV A,SBUF CJNE A,#0FFH,L8 AJMP L3 L8: INC DPL DJNZ R6,L4 SJMP $ 接收方

ORG 0000H

MOV DPTR,#4400H MOV SCON,#90H L1: JBC RI,L2 AJMP L1

L2: MOV A,SBUF MOV R6,A

L3: JBC RI,L4 AJMP L3

L4: MOV A,SBUF JB P,L5 JNB RB8,L8 sIMP $

L5: JB JB8,L8 L6:MOVX @DPTR,A INC DPL INC DPH DJNZ R6,L3

SJMP $ L8: MOV A,#0FFH MOV SBUF,A L9: JBC TI,L3

32

AJMP L9 SJMP $ END

8.8 利用89C51串行口设计4位静态数码管显示器,画出电路并编写程序,要求4位显示器上每隔1s交替地显示\和“4567”。 8.8 电路图见图8-12

/*****************************查询方式****************************/

#include

#define uchar unsigned char sbit P3_3=P3^3;

char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,

0x92,0x82,Oxf8,0xf8,0x80,0xg0}; void timer(uchar); main(){ucha i,a=3; SCON=0; for(;;) {P3_3=1;

for(i=0;i<4;i++) {SBUF=tab[a]; a--;

while(!TI); TI=O;

if(a==255)a=7; P3_3=0; timet(100); }}

void timer(uchre t) {uehar i;

for(i=O;i

33

TH0=-10000/256; TL0=-10000%6; } TR0=1; while(!TF0); TF0=0; }}

/*****************************中断方式******************************/ #include

#define uehar unsigned char sbit P3_3=P3^3; uchar a=3;

char code tab[]={0xc0;0xf9;0xa4,

0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; void timet(uchar t); void int4(void);

main()

{uchar i,j;

SCON=0;EA=1;ES=1; for(;;) {P3_3=1;

for(i=O,i<4,i++) {SBUF=tab[a]; j=a;

while(j==a); }

P3_3=0; timer(100); if(a==255)a=7;

}

void int4(void)interrupt 4 {TI=0; a--; }

void timer(uchar t)

{uchar i;

for(i=0;i

TMOD=0x01;

TH0=-10000/256; TL0=-10000%6: TR0=1;

while(!TF0);

34

TF0=0; }}

第9章 系统扩展

9.1 MCS-51扩展系统中,程序存储器和数据存储器共用16位地址线和8位数据线,为什么两个存储空间不会发生冲突? 9.1 参阅9.1节

9.2 在8XX51单片机上扩展一片6116(2KBX8位RAM)。

9.2 6116为2KBX8位RAM,共11根地址线A0~A10,接线见习题9.2图。

9.3 在8XX51单片机上扩展一片EPROM 2732和一片RAM 6264。 9.3 2732为4KBX8位EPROM,6264为8KBX 8位RAM,因各只有一片,所以各片选-CE接地·电路见习题9.3图。

9.4 在8XX51单片机上扩展一片RAM 6116和一片EPROM 2716,要求6116既能作为数据存储器,又能作为程序存储器使用。

9.4 6116为2KBX8位RAM,2716为2KBX8位EPROM,地址线均为1l根,地址线接线参见习题9·3图。

9.5 在8XX51单片机上扩展4片2764,地址从0000~7FFFH,采用74LSl38作地址译码,写出每片的地址空间范围。 9.5 设计电路见习题9.5图。

4片2764的-CE分别接138译码器为y0,yl,y2.y3端,各片地址为:

35

2764(4) 0000H~lFFFH 2764(3) 2000H~3FFFH 2764(2) 4000H~5FFFH 2764(1) 6000H~7FFFH

9.6 在8XX51单片机上接一片74LS244和一片74LS273,使74LS244的地址为BFFFH,74LS273的地址为DFFFH,并编程从74LS244输入向74LS273输出。

9.6 设计电路见习题9.6图。图中采用的是80C31,由于80C31内部无ROM,片外必须扩展一片程序存储器。图中扩展2764 8K×4 EPROM。根据地址需求,分别以P2.5和P2.6作为273和244的片选,程序参见例9-2。

9.7 在题9.6的基础上,74LS244接一按键开关,74LS273接一个数码管LED,编程序,使数码管显示按键次数。

9.7 程序参阅习题5.4,将MOV A,P1改为MOVX A,@DPTR,DPTR指向244地址BFFFH;将MOV P1,A改为MOVX @DPTR,A,DPTR指向273地址DFFFH。

9.8 设置8255地址为CFFCH~CFFFH,使用部分译码法设计电路,并设置A口方式1输出,B口方式 O输入,C口不用的初始化程序。 9.8 设计电路见习题9.8图。 MOV DPTR,#OCFFFH MOV A,#0A2H MOVX @DPTR,A

36

9.9 在8XXSl单片机上扩展一片8255,使A口可接1个数码管,PC0接阴极,使用C口的置位/复位控制字,数码管显示的“P”字闪烁。 9.9 按习题9.9图的设计,8255A口、B口、C口、控制口地址分别为7CFFH、7DFFH、7EFFH、7FFFH.A口

方式0输出,C口置位/复位控制。 汇编语言程序: MOV DPTR,#7FFFH

MOV A,#80H ;写控制字 MOVX @DPTR,A

MOV DPTR,#7CFFH ;指向A口 MOV A,#0F3H ;输出“P”段码 MOVX @DPTR,A

MOV DPTR,#7FFFH ;指向控制口

MOV A,#0H ;PC0置0控制字 NEXT:MOVX @DPTR,A ;写入控制口 ACALL DAY ;延时

XRL A,#OlH ;使PC0位变反 AJMP NEXT C语言程序

#inclde

#define COM8255 XBYTE[0x7fff] #define A8255 xBYTE[0x7fff] main(){

unsigned int j; COM8255=0x80; A8255=0xf3: while(1){ COM8255=0x0;

for(j=O;j<=10000;j++); COM8255=0x01:

for(j=0;j<=10000;j++); }}

37

9.10 在8XX51单片机上扩展一片8255,使用A口和C口设计4位数码管动态显示电路,显示\字符(G为小写)。

9.10 8255A口、B口、C口、控制口地址分别为7CFFH、7DFFH、7EFFH、7FFFH,A口方式O输出,C口输出,控制字80H。设计见习题9.10图。

ORG 0000H

MOV DPTR,#7FFFH ;指向控制口

MOV A,#80H ;A口、B口均采用基本输出方式 MOVX @DPTR,A ;写控制字 MOV DPTR,#7CFFH MOV A,#0

MOVX @DPTR,A ;清显示 AGAIN: MOV R0,#0 ;R0存字形表偏移量 MOV R1,#01 ;R1置数码表位选代码 NEXT: MOV DPTR,#7EFFH ;指向C口 MOV A,R1

MOVX @DPTR,A ;从C口输出位选码 MOV A,R0

MOV DPTR,#TAB ;置字形表头地址

38

MOVC A,@A+DPTR ;查字形码表 MOV DPTR,#7CFFH ;指向A口

MOVX @DPTR,A ;从A口输出字形码 ACALL DAY ;延时

INC R0 ;指向下一位字形 MOV A,R1

RL A ;指向下一位 MOV R1,A

CJNE Rl,#10H,NEXT ;4个数码管显示完 SJMP AGAIN

DAY:MOV R6,#50 ;延时子程序 DL2:MOV R7,#7DH DL1:NOP NOP

DJNZ R7,DLl DJNZ R6,DL2 RET

TAB1:DB 6FH,3FH,3FH,5EH;“good”(good)的字形码 9.1l 在8XX51单片机上扩展一片EPROM 27128、一片RAM 6264和一片8255,采用线选方式,写出各自的地址范围。

9.11 提示:EPROM 27128 16KB×8,地址线为14根,6264为8KB×8位,地址线为13根,电路参阅图9-22。

9.12 列出图9-26中的I/O口、RAM、计数器、控制口地址。 9.12 根据电路连线图,见习题9.12图。

I/O口:A口:FDF8H,B口:FDF9H,C口:FDFAH 命令/状态口:FDFBH

定时器TIMEL:FDFCH TIMEH:FDFDH 存储器RAM:FC00H~FCFFH

39

第10章 单片机接口技术

补充题1

设4位ADC;当数字量为1000B时,Vo=5v时满档10V的。求被测电压Vi=8.2V的逐次逼近波形图。 补充题1(答案)

电压 8.75V Vi=8.2V 10V 7.5V 5V 2.5V 0V 8.125V Vo D3 D2 D1 D0 时间 10.1 设计8XX51和DAC0832接口,要求地址为F7FFH,满量程电压为5V,采用单缓冲工作方式。画出电路图,编程使输出如下要求的模拟电压:

(1) 幅度为3V,周期不限的三角波电压。 (2) 幅度为4V,周期2ms的方波。

(3) 周期为5ms的阶梯波,阶梯的电压幅度分别为0V,1V,2V,3V,4V,5V,每一阶梯为1ms。

10.1 电路参照图10-3,不同的是将P2.7改为P2.3先计算各模拟量对应的数字量。3V对应的数字量为

5V/3V一255/X, X=153=99H

同样可算得1V,2V,4V对应的数字量分别为33H,66H,CCH ①三角波

MOV DPTR,#OF7FFH NEXTl:MOV A,#O

NEXT:MOVX @DPTR,A NOP NOP INC A

CJNE A,#9AH,NEXT NEXTA:DEC A MOVX @DPTR,A NOP NOP

CJNE A,#0,NEXTA SJMP NEXT1 END

40

#inclde #include

#define da0832 XBYTE[0xf7ff] main(){

unsigned char i,j; while{

for(i=O;i<=153:i++) {da0832=i:

for(j=0;j<=100;j++); }

for(i=153;i>=0:i--) {da0832=i;

for(j=O;j<=100;j++); }}}

②方波4V对应的数字量为CCH MOV DPTR,#0F7FFH MOV A,#0

NEXT:MOVX @DPTR,A ACALL D2MS XRL A,#0CCH SJMP NEXT

#include #include

#define da0832 XBYTE[0xf7ff] main(){

unsingde a=O,j; while(1){ da0832=a;

for(j=0;j<=255;j++); a=a^Oxcc: - }} ③阶梯波

MOV DPTR,#OF7FFH NEC:MOV A,#O

NEXT:MOVX @DPTR,A ACALL D1MS ADD A,#33H

CJNE A,#OFFH,NEXTA NEXTA:MOVX @DPTR,A ACALL D5MS SJMP NEC

main(){ unsigued char i; unsigued int j; while(1){

41

for(i=0;i<=255:i+=51) {da0832=i;

for(j=O;j<=100;j++;); }}}

10.2 题目要求同题10.1,采用双缓冲方式。

lO.2 电路参考图10-4,增加一个地址.使用两条输出指令才能输出一个数据,其他同上。

10.3 设计89S51和DAC0832的接口,采用单缓冲方式,将内部RAM 20H~2FH单元的数据转换成模拟电压,每隔1ms输出一个数据。 10.3 电路参照图10-3,地址为7FFFH。 ORG 0000H

MOV DPTR,#7FFFH MOV R0,#20H

MOV A,@R0

NEXT:MOVX @DPTR,A ACALL D11MS INC R0

CJNE R0,#30H,NEXT SJMP$ END

#include #include

#define da0809 XBYTE[Ox7fff] main(){

unsigned char *p,i,j; p=0x20;

for(i=0;i<=16;i++) {da0832= *p;

p++;

for(i=0,j<=255;j++); }}

10.4 内部RAM的30H~3FH中存放着8个12位的二进制数,其中高4位放在高地址单元,低8位放在低地址单元,利用DACl210转换成模拟电压输出,要求用P2.0,P2.1,P2.2进行线选,编出程序,画出硬件电路。

10.4 电路参阅图10-6,不同的是将P2.5~P2.7改为P2.0~P2.2各地址分别为FEFFH、FDFFH、FBFFH。程序参照10.1节,注意修改RAM地址,循环执行该程序。

10.5 设计89S51和ADC0809的接口,采集2通道10个数据,存入内部RAM的50H~59H单元,画出电路图,编出:(1)延时方式;(2)查询方式;(3)中断方式的程序。

1O.5电路参阅图10-9,不同的是:①延时方式:EOC悬空;②查询方式:EOC经非门接单片机P1.0(见习题10.6图);③中断方式同原图。

下面仅编查询程序。IN2的地址为7FFAH,由于EOC经非门接单片机P1.0端口线,查询到P1.0为零,即转换结束。

ORG 0000H MOV R7,#OAH MOV R0,#50H

42

MOV DPTR,#7FFAH

NEXT:MOVX @DPTR,A ;启动转换 JB P1.0,$ ;查询等待 MOVX A.@DPTR ;渎人数据 MOV @R0,A INC R0 DJNZ NEXT SJMP $

#includc #include

#define uchar unslgnde char

#define IN2 xBYTE[ox7ffa] /*IN2地址*/ sbit adbusy=P1^0); /*EOC*/ void main(void)

{uchar idata ad[10]; uchar i;

for(i=O;i<=10;i++); /*采集10个数*/ {IN2=0; /*启动转换*/

while(adbusy==1); /*D3C等于O循环*/ ad[i]=IN2 /*存转换结果*/}}

10.6 设计89C51和ADC0809的接口,使用中断方式顺序采集8路模拟量。存入地址为20H~27H的内部RAM中。

10.6 ADC0809采集8路模拟信号,顺序采集一次,将采集结果存放于数组ad中。ADC0809模拟通道0~7的地址为7FF8H~7FFFH,以P1.0查询ADC0809的转换结束端EOC,电路如习题10-6图所示的查询方式。 程序如下:

#lnclude #include

#define uchar unsigned char

#define IN0 XBYTE[0x7ff8] /*IN0地址*/ sbit adbusy=P1^0; /*EOC*/

void ad0809(uchar idata*x) /*A/D*/ {uchar ii;

uchar xdata*ad_adr; ad_adr=&IN0;

for(i=0;i<8;i++) /*处理8个通道*/

{ *ad_adr=0; /*启动转换*/

while(adbusy==1); /*查EOC*/ x[i]=*ad_adr; /*存转换结果*/ ad_adr++; /*指向下一通道*/ }}

void main(void)

{uchar idata ad[10];

ad0809(ad); /*采样AD0809通道的值*/}

43

10.7 设计8XX51和8279的接口,使外接8个数码管和2×8矩阵键盘。 (1) 画出硬件电路;

(2) 最左边数码管显示“—”;

(3) 每一次按键,键值“O”~“F”从左到右顺次显示在数码管上。 10.7 参见4.6节例。

第11章 串行接口技术

11.1 在AT89S52上扩展两片AT24C04。 11.1 见习题11.1图

习题11.1图

11.2 完成将O~9写入AT24C04的O~9单元。 11.2 参阅11.L 5节

11.3 完成将AT24C04的O~9单元内容读出并分别存入内部RAM的20H~29H单元。 11.3 参阅11.1.5节

11.4 试用一片TLC5615设计一个51波形发生器,使能产生方波、锯齿波。 11.4 参阅第13章实验指导的实验7

11.5 使用一片TLC549设计一个基于51单片机测量的低频有效值的电压表。 11.5 参阅第13章实验指导的实验8

第12章 嵌入式系统的设计与调试

12.1 单片机的抗干扰措施有哪些?

44

12.1 参阅12.3节

12.2 设计一个电子数字钟,并接一个小喇叭,使 (1) 具有交替显示年、月、日、时、分、秒的功能; (2) 具备校正功能;

*(3) 具备设定闹钟和定时闹钟响功能; *(4) 具备整点报时功能; *(5) 具备生日提醒功能。 其中,*为选做的扩展功能。

12.2 提示:利用定时/计数器定时l00ms,中断10次达1s,满60s,分加1s清O;满60分,小时加1分清0,同时分、秒均有十位数和个位数,按十进制进位,并送显示,显示可采用6个数码管(或8个数码管),校对可用按键中断方式或按键的查询进行加1校对,用并行口接驱动器(非门或三极管)驱动扬声器进行闹钟,如果采用89C51/S51做,由于片内已有程序存储器,4个口用户均可使用。

12.3 用单片机的定时器设计一个音乐盒,使能用按键选择演奏两支小乐曲,已知乐谱和频率的关系如下: C调音符 频率(Hz) 5 392 6 440 7 494 1 524 2 588 3 660 4 698 5 784 6 880 7 988 12.3 提示:使用定时器产生不同频率的信号构成节拍,可以两个定时器联合使用。

12.4 设计一个模拟量采集系统,将所采集的模拟量显示在4个LED显示器或4个LCD显示器上。

12.4 提示:硬件由单片机、A/D转换、LED显示器或LCD显示器及必要的驱动、译码等电路构成。

12.5 题目题12.4,要求利用串行通信,使采集的数据或波形显示在PC的电脑屏幕上。 12.5 略

第13章 单片机实验(略)

45