单片机C51程序设计课后习题答案(复习专用) 下载本文

第一章

1. 给出下列有符号数的原码、反码和补码(假设计算机字长为8

位)。

+45 -89 -6 +112

答:【+45】原=00101101,【+45】反=00101101,【+45】补=00101101 【-89】原=11011001,【-89】反=10100110,【-89】补=10100111 【-6】原=10000110,【-6】反=11111001,【-6】补=11111010 【+112】原=01110000,【+45】反=01110000,【+45】补=01110000 2. 指明下列字符在计算机内部的表示形式。

AsENdfJFmdsv120

答:41H 73H 45H 4EH 64H 66H 4AH 46H 6DH 64H 73H 76H 31H 32H 30H

3. 什么是单片机?

答:单片机是把微型计算机中的微处理器、存储器、I/O接口、定时器/计数器、串行接口、中断系统等电路集成到一个集成电路芯片上形成的微型计算机。因而被称为单片微型计算机,简称为单片机。

4. 单片机的主要特点是什么? 答:主要特点如下:

1) 在存储器结构上,单片机的存储器采用哈佛(Harvard)结构 2) 在芯片引脚上,大部分采用分时复用技术

3) 在内部资源访问上,采用特殊功能寄存器(SFR)的形式

4) 在指令系统上,采用面向控制的指令系统 5) 内部一般都集成一个全双工的串行接口 6) 单片机有很强的外部扩展能力

5. 指明单片机的主要应用领域。

答:单机应用:1) 和智能接口;4)

工业自动化控制;2) 智能仪器仪表;3) 家用电器

计算机外部设备

多机应用:功能弥散系统、并行多机处理系统和局部网络系统。

第二章

1. MCS-51单片机由哪几个部分组成?

答:MCS-51单片机主要由以下部分组成的:时钟电路、中央处理器(CPU)、存储器系统(RAM和ROM)、定时/计数器、并行接口、串行接口、中断系统及一些特殊功能寄存器(SFR)。

2. MCS-51的标志寄存器有多少位,各位的含义是什么? 答:MCS-51的标志寄存器PSW有8位;

D7 6 C C 含义如下:

C(PSW.7):进位或借位标志位。 AC(PSW.6):辅助进位或借位可标志位。

F0(PSW.5):用户标志位。是系统预留给用户自己定义的标志位。

D5 A0 FS1 D4 RS0 D3 RV D2 OD1 D0 - P D

RS1、RS0(PSW.4、PSW.3):寄存器组选择位。可用软件置位或清零,用于从四组工作寄存器中选定当前的工作寄存器组。

OV(PSW.2):溢出标志位。在加法或减法运算时,如运算的结果超出8位二进制数的范围,则OV置1,标志溢出,否则OV清零。

P(PSW.0):奇偶标志位。用于记录指令执行后累加器A中1的个数的奇偶性。若累加器A中1的个数为奇数,则P置位,若累加器A中1的个数为偶数,则P清零。

其中PSW.1未定义,可供用户使用。

3. 在8051的存储器结构中,内部数据存储器可分为几个区域?各有什么特点?

答:片内数据存储器按功能可以分成以下几个部分:工作寄存器组区、位寻址区、一般RAM区和特殊功能寄存器区,其中还包含堆栈区。工作寄存器组区,00H~1FH单元,可用R0~R7等8个寄存器访问;位寻址区,20H~2FH单元,可按位方式访问;一般RAM区,30H~7FH单元;堆栈区,可从08到7F单元;特殊功能寄存器区位于80H~FFH单元。

4. 什么是堆栈?说明MCS-51单片机的堆栈处理过程。

答:堆栈是按先入后出、后入先出的原则进行管理的一段存储区域。CS-51单片机的堆栈是向上生长型的,存入数据是从地址低端向高端延伸,取出数据是从地址高端向低端延伸。入栈和出栈数据是以字节为单位的。入栈时,SP指针的内容先自动加1,然后再把数据存入到SP指针指向的单元;出栈时,先把SP指针指向单元的数据取出,然后再把SP指针的内容自动减1。

5. MCS-51单片机有多少根I/O线?它们和单片机的外部总线有什么关系? 答:MCS-51单片机有32根I/O线,由P0口经地址锁存器提供低8位(A7~A0),P2口提供高8位(A15~A8)而形成。数据总线宽度为8位,由P0口直接提供。控制总线由第二功能状态下的P3口和4根独立的控制线RST、EA、ALE和PSEN组成。

6. 什么是机器周期? MCS-51单片机的一个机器周期包括多少个时钟周期?

答:机器周期:机器周期是单片机的基本操作周期,每个机器周期包含S1、S2、?、S66个状态,每个状态包含两拍P1和P2,每一拍为一个时钟周期(振荡周期)。因此,一个机器周期包含12个时钟周期。

7. 如果时钟周期的频率为12MHz,那么ALE信号的频率为多少? 答:2MHZ

第三章

1.在MCS-51单片机中,寻址方式有几种?其中对片内RAM可以用哪几种寻址方式?对片外RAM可以用哪几种寻址方式?

答:寻址方式可分为数的寻址和指令寻址,数的寻址有:常数寻址(立即寻址)、寄存器数寻址(寄存器寻址)、存储器数寻址(直接寻址方式、寄存器间接寻址方式、变址寻址方式)和位寻址,指令的寻址有绝对寻址和相对寻址。片内RAM寻址有:寄存器寻址、直接寻址方式和寄存器间接寻址方式。片外RAM寻址有:寄存器间接寻址方式。

2.在对片外RAM单元寻址中,用Ri间接寻址与用DPTR间接寻址有什么区别?

答:片外数据存储器寻址中,用Ri间接寻址只能访问低端的256字节单元,而用DPTR作指针间接访问可访问整个64K字节。

3.在位处理中,位地址的表示方式有哪几种? 答:1.直接位地址(00H~0FFH)。例如:20H

2.字节地址带位号。例如:20H.3表示20H单元的3位。

3.特殊功能寄存器名带位号。例如:P0.1表示P0口的1位。

4.位符号地址。例如:TR0是定时/计数器T0的启动位 。

4.写出完成下列操作的指令。 (1)R0的内容送到R1中。

MOV A,R0 MOV R1,A

(2)片内RAM的20H单元内容送到片内RAM的40H单元中。

MOV 40H,20H

(3)片内RAM的30H单元内容送到片外RAM的50H单元中。

MOV A,30H MOV R0,#50H MOVX @R0,A

(4)片内RAM的50H单元内容送到片外RAM的3000H单元中。

MOV A,50H MOV DPTR,#3000H MOVX @DPTR,A

(5)片外RAM的2000H单元内容送到片外RAM的20H单元中。

MOV DPTR,#2000H MOVX A,@DPTR MOV 20H,A

(6)片外RAM的1000H单元内容送到片外RAM的4000H单元中。

MOV DPTR,#1000H MOVX A,@DPTR MOV DPTR,#4000H

MOV @DPTR,A

(7)ROM的1000H单元内容送到片内RAM的50H单元中。

MOV A,#0 MOV DPTR,#1000H MOVC A,@A+DPTR MOV 20H,A

(8)ROM的1000H单元内容送到片外RAM的1000H单元中。

MOV A,#0 MOV DPTR,#1000H MOVC A,@A+DPTR MOVX @DPTR,A

5.区分下列指令有什么不同? (1)MOV A,20H和MOV A,#20H

答:前者源操作数是直接寻址,后者源操作数立即寻址。

(2)MOV A,@R1和MOVX A,@R1

答:前者源操作数是访问片内数据存储器,后者源操作数访问片外数据存储器低256字节。

(3)MOV A,R1和MOV A,@R1

答:前者源操作数是寄存器寻址,后者源操作数寄存器间接寻址。

(4)MOVX A,@R1和MOVX A,@DPTR

答:前者源操作数是访问片外数据存储器低256字节,后者源操作数访问片外数据存储器整个64K字节。

(5)MOVX A,@DPTR和MOVC A,@A+DPTR

答:前者源操作数是访问片外数据存储器,后者源操作数访问程序数据存储器。

6.设片内RAM的(20H)=40H,(40H)=10H,(10H)=50H,(P1)

=0CAH。分析下列指令执行后片内RAM的20H、40H、10H单元以及P1、P2中的内容。

MOV R0,#20H MOV A,@R0 ;A=40H MOV R1,A ;R1=40H MOV A,@R1 ;A=10H MOV @R0,P1

;(40H)=0CAH

MOV P2,P1 P2=0CAH MOV 10H,A (10H)=10H MOV 20H,10H

(20H)=10H

结果:(20H)=10H、(10H)=10H、(40H)=0CAH、P2=0CAH和P1=0CAH 7.已知(A)=02H,(R1)=7FH,(DPTR)=2FFCH,片内RAM(7FH)

=70H,片外RAM(2FFEH)=11H,ROM(2FFEH)=64H,试分别写出以下各条指令执行后目标单元的内容。

(1)MOV A,@R1

结果:累加器A等于70H

结果:片外RAM(2FFCH)单元等于02H 结果: 累加器A等于64H

结果:累加器A等于00H,片内RAM(7FH)

(2)MOVX @DPTR,A (3)MOVC A,@A+DPTR (4)XCHD A,@R1 单元等于72H

8.已知:(A)=78H,(R1)=78H,(B)=04H,CY=1,片内RAM(78H)=0DDH,(80H)=6CH,试分别写出下列指令执行后目标单元的结果和相应标志位的值。

(1)ADD A,@R1

;累加器A等于55H,CY等于1

(2)SUBB A,#77H (3)MUL AB 等于1,OV等于0 (4)DIV AB CY、OV等于0

;累加器A等于00H,CY等于0

;累加器A等于E0H,B寄存器等于01H,CY;累加器A等于1EH,B寄存器等于00H,

(5)ANL 78H,#78H ;片内RAM(78H)单元等于58H (6)ORL A,#0FH (7)XRL 80H,A

;累加器A等于7FH ;片内RAM(80H)等于14H

9.设(A)=83H,(R0)=17H,(17H)=34H,分析当执行完下面指令段后累加器A、R0、17H单元的内容。

ANL A,#17H ORL 17H,A XRL A,@R0 CPL A

;A=03H

;(17H)=37H ;A=34H

;A=CBH

结果:A=CBH,(R0)=17H,(17H)=37H 10.写出完成下列要求的指令。

(1)累加器A的低2位清零,其余位不变。

ANL A,#11111100B

(2)累加器A的高2位置“1”,其余位不变。

ORL A,#11000000B

(3)累加器的高4位取反,其余位不变。

XRL A,#11110000B

(4)累加器第0位、2位、4位、6位取反,其余位不变。

XRL A,#01010101B

11.说明LJMP指令与AJMP指令的区别?

答:LJMP指令后面提供的是16位目标地址,所以可以转移到64KB程序存储器的任意位置,缺点是:执行时间长,字节数多。

AJMP指令后带的是11位直接地址,执行时,先将程序指针PC的值加2(该指令长度为2字节),然后把指令中的11位地址addr11送给程序指针PC的低11位,而程序指针的高5位不变,只能在当前2K范围内转移。 12.设当前指令CJNE A,#12H,10H的地址是0FFEH,若累加器A的值为10H,则该指令执行后的PC值为多少?若累加器A的值为12H呢?

答:指令执行后的PC值为1011H,若累加器A的值为12H,则指令执行后的PC值为1001H。

13.用位处理指令实现P1.4=P1.0?(P1.1?P1.2)?/P1.3的逻辑功能。

程序: MOV C,P1.1 ORL C,P1.2 ANL C,P1.0 ORL C,/P1.3 MOV P1.4,C

14.下列程序段汇编后,从1000H单元开始的单元内容是什么? ORG 1000H

TAB: DB 12H,34H

DS 3

DW 5567H,87H

答:(1000H)=12H,(1001H)=34H,(1002H)=00H,(1003H)=00,(1004H)=00,(1005H)=67H,(1006H)=55H,(1007H)=87H,(1008H)=00H

15.试编一段程序,将片内RAM的20H、21H、22H单元的内容依次存入片外RAM的20H、21H、22H中。

程序:

MOV MOV

R0,#20H R2,#03H

LOOP:MOV A,@R0

MOVX @R0,A INC

R0

DJNZ R2,LOOP SJMP $

16.编程实现将片外RAM的2000H~2030H单元的内容,全部搬到片内RAM的20H单元开始位置,并将源位置清零。

程序: MOV MOV MOV

R0,#20H DPTR,#2000H R2,#30H

LOOP: MOVX A,@DPTR

MOV @R0,A MOV A,#00 MOVX @DPTR,A INC

DPTR R0

INC

DJNZ R2,LOOP SJMP $

17.编程将片外RAM的1000H单元开始的100个字节数据相加,结果放于R7R6中。

程序: MOV

DPTR,#1000H

MOV MOV MOV

R2,#100 R7,#00 R6,#00

LOOP: MOVX A,@DPTR

ADD A,R6 MOV R6,A MOV A,R7 ADDC A,#0 MOV R7,A INC

DPTR

DJNZ R2,LOOP SJMP $

18.编程实现R4R3?R2,结果放于R7R6R5中。 程序:

ORG

0100H

MUL1:MOV A,R2

MOV B,R3

MUL AB ;R2?R3,结果的低字节直接存入积的R5 MOV R5,A ;结果的高字节存入R6中暂存起来 MOV R6,B

MUL2:MOV A,R2

MOV B,R4

MUL AB ;R2?R4,结果的低字节与R6相加后,再存入

R6中

ADD A,R6 MOV R6,A

MOV A,B ;结果的高字节加上进位位后存入R7中 ADDC A,#00 MOV R7,A SJMP

$

19.编程实现把片内RAM的20H单元的0位、1位,21H单元的2位、3位,22H单元的4位、5位,23H单元的6位、7位,按原位置关系拼装在一起放于R2中。

程序:

MOV C,20H.0 MOV A.0,C MOV C,20H.1 MOV A.1,C MOV C,21H.2 MOV A.2,C MOV C,21H.3 MOV A.3,C MOV C,22H.4 MOV A.4,C MOV C,22H.5 MOV A.5,C MOV C,23H.6 MOV A.6,C MOV C,23H.7

MOV A.7,C MOV R2,A

20.用查表的方法实现一位十六进制数转换成ASCII。

程序:(设一位十六进制数放在R2中,轮换的ASCII也放于R2中) C16STASC:MOV

MOV

A,R2

DPTR,#TAB

MOVC A,@A+DPTR MOV RET

R2,A

TAB:DB 30H,31H,32H,33H,34H,35H,36H,37H

DB 38H,391H,41H,42H,43H,44H,45H,46H

21.编程统计从片外RAM2000H开始的100个单元中“0”的个数放于R2中。

程序: MOV MOV MOV

DPTR,#2000H R3,#100 R2,#00

LOOP: MOVX A,@DPTR

JNZ INC

NEXT R2

DPTR

NEXT:INC

DJNZ R3,LOOP SJMP $

第四章

1. C语言有哪些特点? 答:C语言具有以下特点:

1) 语言简洁、紧凑,使用方便、灵活 2) 运算符丰富

3) 数据结构丰富,具有现代化语言的各种数据结构 4) 可进行结构化程序设计

5) 可以直接对计算机硬件进行操作 6) 生成的目标代码质量高,程序执行效率高 7) 可移植性好

2. 有哪些数据类型是MCS-51单片机直接支持的?

答:MCS-51单片机直接支持的数据类型标准分为基本数据类型和组合数据类型,基本数据类型有字符型char、短整型short、整型int、长整型long、浮点型float、双精度型double、特殊功能寄存器型和位类型,其中char型与short型相同,float型与double型相同。组合数据类型有数组类型、结构体类型、共同体类型和枚举类型,另外还有指针类型和空类型。

3. C51特有的数据类型有哪些?

答:C51特有的数据类型有特殊功能寄存器型和位类型。

4. C51中的存储器类型有几种,它们分别表示的存储器区域是什么? 答:C51中的存储器类型有6种,分别如下: data:直接寻址的片内RAM低128B,访问速度快

bdata:片内RAM的可位寻址区(20H~2FH),允许字节和位混合访问 idata:间接寻址访问的片内RAM,允许访问全部片内RAM pdata:用Ri间接访问的片外RAM低256B

xdata:用DPTR间接访问的片外RAM,允许访问全部64KB片外RAM code:程序存储器ROM 64KB空间

5. 在C51中,bit位与sbit位有什么区别?

答:bit位类型符用于定义一般的位变量。存储器类型只能是bdata、data、idata,只能是片内RAM的可位寻址区,严格来说只能是bdata。 sbit位类型符用于定义在可位寻址字节或特殊功能寄存器中的位,定义时需指明其位地址,可以是位直接地址,可以是可位寻址变量带位号,也可以是特殊功能寄存器名带位号。

6. 在C51中,通过绝对地址来访问的存储器有几种?

答:通过绝对地址来访问存储器有三种方法:1. 使用C51运行库中预定义宏。2. 通过指针访问。3. 使用C51扩展关键字_at_

7. 在C51中,中断函数与一般函数有什么不同?

答:中断函数在定义时后面带interrupt m修饰符,m的取值为0~31,对应的中断情况如下:0——外部中断0,1——定时/计数器T0,2——外部中断1,3——定时/计数器T1,4——串行口中断,5——定时/计数器T2,其他值预留。

编写MCS-51中断函数需要注意如下几点。

(1) 中断函数不能进行参数传递,如果中断函数中包含任何参数声明都将导致编译出错。

(2) (3)

中断函数没有返回值。

在任何情况下都不能直接调用中断函数

(4) 如果在中断函数中调用了其他函数,则被调用函数所使用的寄存器必须与中断函数相同,否则会产生不正确的结果。

(5) C51编译器对中断函数编译时会自动在程序开始和结束处加上相应的内容。

(6) C51编译器从绝对地址8m+3处产生一个中断向量,其中m为中断号,也即interrupt后面的数字。该向量包含一个到中断函数入口地址的绝对跳转。

(7) 中断函数最好写在文件的尾部,并且禁止使用extern存储类型说明。防止其他程序调用。

8. 按给定的存储类型和数据类型,写出下列变量的说明形式。 (1)

在data区定义字符变量val1。

char data val1; (2)

在idata区定义整型变量val2。

int idata val2; (3)

在xdata区定义无符号字符型数组val3[4]。

unsigned char xdata val3[4]; (4)

在xdata区定义一个指向char类型的指针px。

char xdata *px; (5)

定义可寻址位变量flag。

bit flag; (6)

定义特殊功能寄存器变量P3。

sfr P3=0xa0; (7)

定义特殊功能寄存器变量SCON。

sfr SCON=0x98; (8)

定义16位的特殊功能寄存器T0。

sfr16 T0=0x8a;

9. 写出下列关系表达式或逻辑表达式的结果,设a=3,b=4,c=5。 (1) (2) (3) (4) 10.

a+b>c&&b= =c 结果:假 a||b+c&&b-c 结果:真 !(a>b)&&!c||1 结果:真 !(a+b)+c-1&&b+c/2 结果:假 写出下列C51程序的执行结果。

(1)

#include

extern serial_initial(); main() {

int x,y,z;

serial_initial(); x=y=8;z=++x;

printf(\ x=y=8;z=x++;

printf(\ x=y=8;z=--x;

printf(\ x=y=8;z=x--;

printf(\ printf(\ while(1); }

结果: 8 9 9

8 8 9 8 7 7 8 8 7

(2)

#include

extern serial_initial();main() {

int x,y,z;

serial_initial();

printf(\ scanf(\

printf(\ printf(\

printf(\ z=xy; printf(\ z=x>=y; printf(\ z=x!=y; printf(\ z=x==y; printf(\ while(1); }

执行结果: input data x,y? 1 2

x y xy x>=y x!=y x==y 1 2 1 1 0 0 1 0 (3)

#include

extern serial_initial(); main() {

int x,y,z;

serial_initial();

printf(\scanf(\

printf(\printf(\

z=!y; printf(\z=x||y; printf(\z=x&&y; printf(\printf(\printf(\while(1); }

执行结果: input data x, y ? x y !x x||y x&&y 1 2 0 1 1 That is all

(4)

#include

extern serial_initial(); main() {

int a,b;

unsigned int x,y; serial_initial();

a=b=0xaa55;x=y=0xaa55;

printf(\ a=a<<1;b=b>>1; x=x<<1;y=y>>1;

printf(\printf(\ printf(\

printf(\

while(1); }

执行结果:

a=aa55 b=aa55 x=aa55 y=aa55 a=54aa b=d52a x=54aa y=552a That is all. 11.

break和continue语句的区别是什么?

答:break语句可以跳出switch结构,使程序继续执行switch结构后面的一个语句。break语句还可以从循环体中跳出循环,提前结束循环而接着执行循环结构下面的语句。

continue语句用在循环结构中,用于结束本次循环,跳过循环体中continue下面尚未执行的语句,直接进行下一次是否执行循环的判定。 continue语句和break语句的区别在于:continue语句只是结束本次循环而不是终止整个循环;break语句则是结束循环,不再进行条件判断。 12. 用分支结构编程实现:输入“1”显示“A”,输入“2”显示“B”,输入“3”显示“C”,输入“4”显示“D”,输入“5”结束。

参考程序:

#include

#include void main(void) {

unsigned char x; SCON=0x52; //串口初始化 TMOD=0x20; TH1=0XF3; TR1=1; while(1) {

printf(\ //输出提示信息 scanf(\ switch(x) {

case '1':printf(\case '2':printf(\case '3':printf(\case '4':printf(\case '5':printf(\default: printf(\}

if (x=='5') break; }

while(1); } 13. 输入3个无符号的字符数据,要求按由大到小的顺序输出。 参考程序:

#include #include void main(void) {

unsigned char x,y,z,m; SCON=0x52; TMOD=0x20; TH1=0XF3; TR1=1;

printf(\ scanf(\ printf(\

if (x

printf(\ while(1); }

//串口初始化

//输出提示信息

//输出

14. 用3种循环结构编写程序实现输出1到10的平方之和。

参考程序:

(1)while循环

#include //包含特殊功能寄存器库 #include //包含I/O函数库 void main(void) //主函数 {

int i,s=0; //定义整型变量 i=1;

SCON=0x52; //串口初始化 TMOD=0x20; TH1=0XF3; TR1=1;

while (i<=10) //累加1到10的平方之和在s中 {

s=s+i*i; i++; }

printf(\到10的平方之和=%d\\n\while(1); }

(2)do while循环

#include //包含特殊功能寄存器库 #include //包含I/O函数库 void main(void) //主函数 {

int i,s=0; //定义整型变量 i=1;

SCON=0x52; //串口初始化 TMOD=0x20; TH1=0XF3; TR1=1; do //累加1到10的平方之和在s中 {

s=s+i*i; i++; }

while (i<=10);

printf(\到10的平方之和=%d\\n\while(1); }

(3)for循环

#include #include void main(void) {

int i,s=0; SCON=0x52; TMOD=0x20;

//包含特殊功能寄存器库 //包含I/O函数库 //主函数

//定义整型变量 //串口初始化

TH1=0XF3; TR1=1;

for (i=1;i<=10;i++) s=s+i*i; //累加1到10的平方之和在s中 printf(\到10的平方之和=%d\\n\while(1); } 15. 排序。

对一个由5个元素组成的无符号字符数组按由小到大的顺序进行

参考程序:

#include //包含特殊功能寄存器库 #include //包含I/O函数库 main() {

unsigned char f[5],m,i,j;

SCON=0x52; //串口初始化 TMOD=0x20; TH1=0XF3; TR1=1;

printf(\输入任意5个字符:\

scanf(\printf(\

for (i=0;i<5;i++)

for (j=0;j<5-i;j++) if (f[j]>f[j+1])

{m=f[j];f[j]=f[j+1];f[j+1]=m;}

printf(\由小到大的顺序为:%c,%c,%c,%c,%c \printf(\while(1); } 16. 出。

用指针实现,输入3个无符号字符数据,按由大到小的顺序输

参考程序:

#include //包含特殊功能寄存器库 #include //包含I/O函数库 main() {

unsigned char x,y,z;

unsigned char *p,*p1,*p2,*p3; SCON=0x52; //串口初始化

TMOD=0x20; TH1=0XF3; TR1=1;

printf(\scanf(\printf(\

p1=&x;p2=&y; p3=&z;

if (*p1<*p2) {p=p1;p1=p2;p2=p;} if (*p2<*p3) {p=p2;p2=p3;p3=p;} if (*p1<*p2) {p=p1;p1=p2;p2=p;}

printf(\while(1); }

17. 有3个学生,每个学生都包括学号、姓名和成绩,要求找出成绩最高的学生的姓名和成绩。

参考程序:

#include //包含特殊功能寄存器库 #include //包含I/O函数库 struct student {

unsigned char number[10]; unsigned char name[10]; unsigned int grade; }p1[3]; main() {

unsigned char i,j=0; SCON=0x52; //串口初始化 TMOD=0x20; TH1=0XF3; TR1=1;

printf(\for (i=0;i<3;i++) {

printf(\scanf(\printf(\scanf(\printf(\scanf(\}

for (i=1;i<3;i++) {

if (p1[i].grade>p1[j].grade) j=i; }

printf(\成绩最高的学生是:%s,成绩是:%d\printf(\

}

while(1); }

第五章

1.单片机C语言与汇编语言混合编程有哪几种方式?通常采用什么方式? 答:单片机C语言和汇编语言混合编程分为汇编中调用C51函数和C51程序中引用汇编,通常使用的是在C51程序中引用汇编。在C51程序中使用汇编语言有两种情况:一种是汇编程序部分和C51程序部分为不同的模块,或不同的文件,通常由C51程序调用汇编程序模块的变量和函数(也可称为子程序或过程);另一种是嵌入式汇编,即在C51程序中嵌入一段汇编语言程序。

2.简述C51程序调用汇编程序时如何实现参数传递。

答:C51中调用汇编程序进行参数传递时都必须严格遵守C51函数的参数和返回值的相关约定。行参数传递的方式有两种,一种是通过寄存器传递参数,C51中不同类型的实参会存入相应的寄存器,在汇编中只需对相应寄存器进行操作,即可达到传递参数的目的;第二种是通过固定存储区传递。

3.简述嵌入式汇编的实现方法。

答:在C51程序中嵌入汇编程序通常的处理方法如下。 第一步:在C文件中以如下方式嵌入汇编程序。

第二步:在Keil C51软件的Project 窗口右击嵌入汇编程序的C文件,在弹出的快捷菜单中选择Options for ...命令,选中右边的Generate

Assembler SRC File和Assemble SRC File复选框,使检查框由灰色变成黑色(有效)状态。

第三步:根据选择的编译模式,把相应的库文件(如 Small 模式时,是 Keil\\C51\\Lib\\C51S.Lib)加入到工程中,该文件必须作为工程的最后文件。

4.简述C51中调用汇编程序的实现方法。

答:编写为C51调用的汇编程序,参数须按规定的寄存器或存储器传送,程序格式有相应的规则,这些规则比较繁琐,为了便于处理,在实际中我们往往先用C51写出这个程序的主体,然后用SRC控制指令编译产生asm文件,修改这个asm文件得到我们所要的汇编函数。处理过程具体如下。

第一步:先用C语言程序编写出程序框架,如文件名为a1.c(注意参数)。 第二步:在Keil C51的Project窗口中右击该C语言文件,在弹出的快捷菜单中选择Options for ...,右边的Generate Assembler SRCFile和Assemble SRC File,使检查框由灰色变成黑色(有效)状态;

第三步:根据选择的编译模式,把相应的库文件(如Small模式时,是Keil\\C51\\Lib\\ C51S.Lib)加入工程中,该文件必须作为工程的最后文件。库文件与编译模式的关系如前面。

第四步:编译后将会产生一个SRC的文件,将这个文件扩展名改为ASM。这样就形成了可供C51程序调用的汇编程序。随后可在该文件的代码段中加入所需的指令代码。

第五步:将该汇编程序与调用它的主程序一起加到工程文件中,这时工程文件中不再需要原来的C语言文件和库文件,主程序只需要在程序开始处用EXTERN对所调用的汇编程序中的函数作声明,在主程序中就可调用汇编程序中的函数了。

第六章

1. 何为“准双向I/O接口”?在MCS-51单片机的四个并口中,哪些是“准双向I/O接口”?

答:准双向I/O接口是能实现输入输出功能,但在使用时只能从输入和输出中选择一个。MCS-51单片机的四个并口中P1、P2、P3是准双向I/O接口。 2. 80C51单片机内部有几个定时/计数器?它们由哪些功能寄存器组成?怎样实现定时功能和计数功能?

答:80C51单片机内部有两个16位的可编程定时/计数器,由

TH0,TL0,TH1,TL1,TMOD和TCON功能寄存器组成。通过TMOD中的C/T位选择对机器周期计数实现计数功能,选择对外部脉冲计数实现计数功能。

3. 定时/计数器T0有几种工作方式?各自的特点是什么? 答:有四种工作方式,特点见下表: M1 0 0 1

M0 0 1 0 工作方式 方式说明 0 13位定时/计数器 1 16位定时/计数器 2 8位自动重置定时/计数器

1 1 3 两个8位定时/计数器(只有T0有) 4. 定时/计数器的四种工作方式各自的计数范围是多少?如果要计10个单位,不同的方式初值应为多少?

答:有四种方式。方式0计数范围:1~8192;方式1计数范围:1~65536;方式2计数范围:1~256;方式3计数范围:1~256。

如果计10个单位,方式0初值为:8192-10=8182;方式1初值为:

65536-10=65526;方式2初值为:256-10=246;方式2初值为:256-10=246。 5. 设振荡频率为12MHz,如果用定时/计数器T0产生周期为100ms的方波,可以选择哪几种方式,其初值分别设为多少?

答:只能选择方式1,初值为65536-50000=15536。 6. 何为同步通信?何为异步通信?各自的特点是什么?

答:异步通信方式的特点是数据在线路上传送时是以一个字符(字节)为单位,未传送时线路处于空闲状态,空闲线路约定为高电平“1”。特点是对发送时钟和接收时钟的要求相对不高,线路简单,但传送速度较慢。

同步通信方式的特点是数据在线路上传送时以字符块为单位,一次传送多个字符,传送时须在前面加上一个或两个同步字符,后面加上校验字符。特点是对发送时钟和接收时钟要求较高,往往用同一个时钟源控制,控制线路复杂,传送速度快。

7. 单工、半双工和全双工有什么区别?

答:单工方式只有一根数据线,信息只能单向传送;半双工方式也只有一根数据线,但信息可以分时双向传送;全双工方式有两根数据线,在同一个时刻能够实现数据双向传送。

8. 设某异步通信接口,每帧信息格式为10位,当接口每秒传送1000个字符时,其波特率为多少?

答:10000波特

9. 串行口数据寄存器SBUF有什么特点?

答:发送数据寄存器和接收数据寄存器合起用一个特殊功能寄存器SBUF(串行口数据寄存器),执行MOV SBUF,A发送时为发送数据寄存器,执行MOV A, SBUF接收时为接收数据寄存器。

10. MCS-51单片机串行口有几种工作方式?各自特点是什么?

答:有四种工作方式,分别是方式0、方式1、方式2和方式3。其中: 方式0,称为同步移位寄存器方式,一般用于外接移位寄存器芯片扩展I/O接口。

方式1,称为8位的异步通信方式,通常用于双机通信。 方式2和方式3,称为9位的异步通信方式,通常用于多机通信。 11.

说明SM2在方式2和方式3对数据接收有何影响。

答:通过SM2对方式2和方式3数据接收进行控制, SM2=1,那么只有接收的第9位为“1”才接收有效。如SM2=0,接收的第9位无论为1还是0都接收有效。

12.

怎样来实现利用串行口扩展并行输入/输出口?

答:利用串行口在方式0时,当外接一个串入并出的移位寄存器,就可以扩展并行输出口;当外接一个并入串出的移位寄存器时,就可以扩展并行输入口。

13.

什么是中断、中断允许和中断屏蔽?

答:在计算机中,由于计算机内外部的原因或软硬件的原因,使CPU从当前正在执行的程序中暂停下来,而自动转去执行预先安排好的为处理该原因所对应的服务程序。执行完服务程序后,再返回被暂停的位置继续执行原来的程序,这个过程称为中断,实现中断的硬件系统和软件系统称为中断系统。中断允许是允许中断请求送CPU产生中断,中断屏蔽是禁止中断请求信号送CPU产生中断。

14.

8051有几个中断源?中断请求如何提出?

答:MCS-51单片机提供5个硬件中断源:两个外部中断源INT0(P3.2)和INT1(P3.3),两个定时/计数器T0和T1中断;1个串行口中断。

外部中断源INT0和INT1的中断请求信号从外部引脚P3.2和P3.3输入;两个定时/计数器T0和T1的溢出中断TF0和TF1定时/计数器T0(或T1)溢出时提出;串行口中断由发送中断标志T1和接收中断标志R1产生。

15. 8051的中断源中,哪些中断请求信号在中断响应时可以自动清除?哪些不能自动清除?应如何处理?

答:工作在边沿触发方式下的两个外部中断源和两个定时/计数器中断中断请求信号在中断响应时可以自动清除,工作在电平触发方式下的两个外部中断源和串行口中断不能自动清除。工作在电平触发方式下的两个外部中断源的中断请求信号通过外加硬件和加软件的方式清除,串行口中断标志T1和标志R1完全由软件清除。

16.

8051的中断优先级有几级?在形成中断嵌套时各级有何规定?

答:8051的中断优先级有两级;形成中断嵌套时规定(1) 正在进行的中断过程不能被新的同级或低优先级的中断请求所中断,直到该中断服务程序结束,返回了主程序且执行了主程序中的一条指令后,CPU才响应新的中断请求。

(2) 正在进行的低优先级中断服务程序能被高优先级中断请求所中断,实现两级中断嵌套。 (3) 求。

CPU同时接收到几个中断请求时,首先响应优先级最高的中断请

17. 设8051的P1中各位接发光二极管,分别用汇编语言和C语言编程实现逐个轮流点亮二极管,并循环显示。

参考程序:

ORG 0000H LJMP MAIN

ORG 0100H ;主程序

MAIN: MOV A,#01H LOOP:MOV P1,A

CALL DELAY RL A SJMP LOOP SJMP $

DELAY:MOV R7,#0FFH

DJNZ R7,$

END

RET

C语言程序:

#include //包含特殊功能寄存器库 void delay(unsigned int x); void main() {

unsigned char i,j; while(1) {i=01;

for (j=0;j<8;j++)

{P1=i;

delay(100); i=i*2; }

} }

void delay(unsigned int x) {

unsigned char j; while(x--)

{for (j=0;j<125;j++);} }

18. 8051系统中,已知振荡频率为12MHz,用定时/计数器T0,实现从P1.0产生周期为2ms的方波。要求分别用汇编语言和C语言进行编程。 解:分析:从P1.0输出周期为2ms的方波,只须P1.0每1ms取反一次则可。当系统时钟为12MHZ,定时/计数器T0工作于方式1时,最大的定时时间为65.536ms,满足1ms的定时要求,方式控制字应设定为00000001B(01H)。定时1ms,计数值N为1000,初值X=65536-1000=64536,则TH0=FCH,TL0=18H。

采用中断处理方式: 程序如下:

ORG 0000H LJMP MAIN

ORG 000BH ;中断处理程序

MOV TH0,#0FCH MOV TL0,#18H CPL P1.0 RETI

ORG 0100H ;主程序

MAIN: MOV TMOD,#01H

MOV TH0,#0FCH MOV TL0,#18H SETB EA SETB ET0 SETB TR0 SJMP $ END

C语言程序:

#include //包含特殊功能寄存器库 sbit P1_0=P1^0; void main() {

TMOD=0x01;

TH0=0xFC;TL0=0x18; EA=1;ET0=1; TR0=1; while(1); }

void time0_int(void) interrupt 1 //中断服务程序 {

TH0=0xFC;TL0=0x18; P1_0=!P1_0; }

19. 8051系统中,已知振荡频率为12MHz,用定时/计数器T1,实现从P1.1产生周期为2s的方波。要求分别用汇编语言和C语言进行编程。

解:

从P1.1产生2s的方波,应产生500ms的周期性的定时,定时到对P1.1取反就可实现。由于定时时间较长,一个定时/计数器T1不能直接实现,采用定时/计数器T1产生周期性为10ms的定时,然后用一个寄存器R2对10ms计数100次来实现。系统时钟为12MHZ,定时/计数器T1定时10ms,计数值N为10000,只能选方式1,方式控制字为00010000B(10H),初值X:

X=65536-10000=55536=1101100011110000B 则TH1=11011000B=D8H,TL1=11110000B=F0H。 定时/计数器T1采用中断处理方式。 汇编程序:

ORG 0000H LJMP MAIN

ORG 001BH LJMP INTT1

ORG 0100H MAIN:

MOV TMOD,#10H

MOV TH1,#0D8H MOV TL1,#0F0H MOV R2,#00H SETB EA SETB ET1 SETB TR1

SJMP $

INTT1: MOV TH1,#0D8H

MOV TL1,#0F0H INC R2

CJNE R2,#64H,NEXT CPL P1.1 MOV R2,#00H

NEXT: RETI

END

C语言程序:

#include //包含特殊功能寄存器库 sbit P1_1=P1^1; char i; void main() {

TMOD=0x10;

TH1=0xD8;TL1=0xf0; EA=1;ET1=1; i=0; TR1=1; while(1); }

void time0_int(void) interrupt 3 //中断服务程序 {

TH1=0xD8;TL1=0xf0; i++;

if (i= =100) {P1_1=! P1_1;i=0;} }

20. 8051系统中,已知振荡频率为12MHz,用定时/计数器T1,实现从P1.1产生高电平宽度为10ms,低电平宽度为20ms的矩形波。要求分别用汇编语言和C语言进行编程。

解:

本题处理方式有多种,这里采用对定时/计数器T1形成10ms周期定时,用R2对10ms计数,当计到1,则对P1.1置1,当计到2和3,则对P1.1置0来实现。用定时/计数器T1形成10ms周期定时见上题。

程序如下:

ORG 0000H LJMP MAIN

ORG 001BH LJMP INTT1

ORG 0100H MAIN:

MOV TMOD,#10H

MOV TH1,#0D8H MOV TL1,#0F0H MOV R2,#00H SETB EA SETB ET1 SETB TR1 SJMP $

INTT1: MOV TH1,#0D8H

MOV TL1,#0F0H INC R2

CJNE R2,#01H,NEXT SETB P1.1

SJMP EXIT

NEXT: CJNE R2,#02H,NEXT1

CLR P1.1 SJMP EXIT

NEXT1:CJNE R2,#03H,NEXT

SETB P1.1 MOV R2,#00

EXIT: RETI

END

C语言程序:

#include //包含特殊功能寄存器库 sbit P1_1=P1^1; char i; void main() {

TMOD=0x10;

TH1=0xD8;TL1=0xf0; EA=1;ET1=1; i=0; TR1=1; while(1) {

if (i= =0) {P1_1=1;} if (i= =1) {P1_1=0;} if (i= =2) {P1_1=0;} } ; }

void time0_int(void) interrupt 3 //中断服务程序 {

TH1=0xD8;TL1=0xf0; i++;

if (i= =3) {i=0;} }

21. 用8051单片机的串行口扩展并行I/O接口,控制16个发光二极管依次发光,画出电路图,用汇编语言和C语言分别编写相应的程序。

解:

采用在串口连接两个CD4094来实现,电路图如下:

8051 RXD TXD P1.0 DATA CLK DATA CLK STB STB

程序如下; ORG 0000H LJMP MAIN

ORG 0100H

MAIN: MOV SCON,#00H

MOV R4,#10H MOV R3,#00H MOV R2,#01H CLR P1.0

START:MOV A,R3

MOV SBUF,A

LOOP: JNB TI,LOOP

MOV A,R2 MOV SBUF,A

LOOP1:JNB TI,LOOP1

SETB P1.0 ACALL DELAY CLR TI CLR C MOV A,R2 RLC A MOV R2,A MOV A,R3 RLC A MOV R3,A CLR P1.0 DJNZ R4,START1 SJMP MAIN

DELAY:MOV R7,#05H LOOP2:MOV R6,#0FFH LOOP1:DJNZ R6,LOOP1

DJNZ R7,LOOP2 RET END

C语言程序:

#include

void delay(unsigned int x); union {

unsigned int word;

struct{unsigned char high;unsigned char low;}bytes; }number;

void main() {

int i; SCON=0x00;

while(1) {

number.word=0x01; for (i=0;i<16;i++)

{SBUF=number.bytes.low; while(!TI); TI=0;

SBUF=number.bytes.high; while(!TI); TI=0;

delay(10);

number.word=number.word*2; } } }

void delay(unsigned int x) {

unsigned char j; while(x--)

{for (j=0;j<125;j++);} }

22. 用汇编语言编程设计一个8051双机通信系统,将A机的片内RAM中30H~3FH的数据块通过串行口传送到B机的片内RAM的40H~4FH中,并画出电路图。

解:线路连接如图所示。

8051 RXD 甲机 TXD GND 8051 TXD 乙机 RXD GND

分析:甲、乙两机都选择方式1即8位异步通信方式,最高位用作奇偶校验,波特率为1200bps,甲机发送,乙机接收,因此甲机的串口控制字为40H,乙机的串口控制字为50H。

由于选择的是方式1,波特率由定时/计数器T1的溢出率和电源控制寄存器PCON中的SMOD位决定,则需对定时/计数器T1初始化。

设SMOD=0,甲、乙两机的振荡频率为12MHz,由于波特率为1200bps。定时/计数器T1选择为方式2,则初值如下。

初值=256 - fosc×2SMOD /(12×波特率×32) =256-12000000/(12×1200×32)≈230=E6H

根据要求,定时/计数器T1的方式控制字为20H。 甲机的发送程序:

TSTART: MOV TMOD,#20H MOV TL1,#0E6H MOV TH1,#0E6H MOV PCON,#00H MOV SCON,#40H MOV R0,#30H MOV R7,#10H SETB TR1 LOOP: MOV A,@R0 MOV C,P MOV ACC.7,C MOV SBUF,A WAIT: JNB TI,WAIT CLR TI INC R0 DJNZ R7,LOOP RET

乙机的接收程序:

RSTART: MOV TMOD,#20H MOV TL1,#0E6H MOV TH1,#0E6H MOV PCON,#00H MOV R0,#40H MOV R7,#10H SETB TR1

LOOP: MOV SCON,#50H WAIT: JNB RI,WAIT MOV A,SBUF MOV C,P JC ERROR ANL A,#7FH MOV @R0,A INC R0

DJNZ R7,LOOP RET

第七章

1. 什么是MCS-51单片机的最小系统?

答:所谓最小系统,是指一个真正可用的单片机的最小配置系统。对于单

片机内部资源已能够满足系统需要的,可直接采用最小系统。

2. 简述存储器扩展的一般方法。

答:存储器芯片与单片机扩展连接具有共同的规律。即不论何种存储器芯片,其引脚都呈三总线结构,与单片机连接都是三总线对接。另外,电源线接电源线,地线接地线。

3. 什么是部分译码法?什么是全译码法?它们各有什么特点?用于形成什么信号?

答:部分译码就是存储器芯片的地址线与单片机系统的地址线顺次相接后,剩余的高位地址线仅用一部分参加译码。部分译码使存储器芯片的地址空间有重叠,造成系统存储器空间的浪费。全译码就是存储器芯片的地址线与单片机系统的地址线顺次相接后,剩余的高位地址线全部参加译码。这种译码方法中存储器芯片的地址空间是唯一确定的,但译码电路要相对复杂。译码形成存储器芯片的片选信号线CE。

4. 采用部分译码为什么会出现地址重叠情况,它对存储器容量有何影响? 答:部分译码就是存储器芯片的地址线与单片机系统的地址线顺次相接后,剩余的高位地址线仅用一部分参加译码。参加译码的地址线对于选中某一存储器芯片有一个确定的状态,而与不参加译码的地址线无关。也可以说,只要参加译码的地址线处于对某一存储器芯片的选中状态,不参加译码的地址线的任意状态都可以选中该芯片。正因为如此,部分译码使存储器芯片的地址空间有重叠,造成系统存储器空间减少。

5. 存储器芯片的地址引脚与容量有什么关系? 答:容量(Q)与地址线数目(N)满足关系式:Q=2N。 6. MCS-51单片机的外部设备是通过什么方式访问的?

答:MCS-51单片机扩展的外部设备与片外数据存储器统一编址,即外部设备占用片外数据存储器的地址空间。按片外数据存储器的访问方式访问。

7. 何为键抖动?键抖动对键位识别有什么影响?怎样消除键抖动? 答:按键时,无论按下键位还是放开键位都会产生抖动,如果对抖动不作处理,必然会出现按一次键而输入多次,为确保按一次键只确认一次,必须消除按键抖动。消除按键抖动通常有硬件消抖和软件消抖两种方法。

8. 矩阵键盘有几种编码方式?怎样编码? 答:通常有以下两种方法进行编码;(1) 组合进行编码。(2) 顺序排列编码。

9. 简述对矩阵键盘的扫描过程。

答:矩阵式键盘的工作过程可分为两步:第一步是CPU首先检测键盘上是否有键按下;第二步是识别哪一个键按下。

(1) 检测键盘上是否有键按下的处理方法是:将列线送入全扫描字,读入行线的状态来判别。

(2) 识别键盘中哪一个键按下的处理方法是:将列线逐列置成低电平,检查行输入状态,称为逐列扫描。

10.

共阴极数码管与共阳极数码管有何区别?

用连接键盘的I/O线的二进制

答:共阴极结构,8段发光二极管的阴极端连接在一起,阳极端分开控制,使用时公共端接地,要使哪根发光二极管亮,则对应的阳极端接高电平;共阳极结构,8段发光二极管的阳极端连接在一起,阴极端分开控制,使用时公共端接电源,要使哪根发光二极管亮,则对应的阴极端接地。

11.

简述LED数码管显示的译码方式。

答:所谓译码方式是指由显示字符转换得到对应的字段码的方式。对于LED数码管显示器,通常的译码方式有硬件译码方式和软件译码方式两种。

12.

简述LED动态显示过程。

答:LED动态显示是将所有的数码管的段选线并接在一起,用一个I/O接口控制,公共端不是直接接地(共阴极)或电源(共阳极),而是通过相应的I/O接口线控制,工作过程为:第一步使右边第一个数码管的公共端D0为1,其余的数码管的公共端为0,同时在I/O(1)上发送右边第一个数码管的字段码,这时,只有右边第一个数码管显示,其余不显示;第二步使右边第二个数码管

的公共端D1为1,其余的数码管的公共端为0,同时在I/O(1)上发送右边第二个数码管的字段码,这时,只有右边第二个数码管显示,其余不显示,依此类推,直到最后一个,这样4个数码管轮流显示相应的信息,一次循环完毕后,下一次循环又这样轮流显示,从计算机的角度看是一个一个地显示,但由于人的视觉暂留效应,只要循环的周期足够快,则看起来所有的数码管就都是一起显示的了,这就是动态显示的原理。

13. 使用2764(8KB?8)芯片通过部分译码法扩展24KB程序存储器,画出硬件连接图,指明各芯片的地址空间范围。

答:使用2764(8K?8)芯片通过部分译码法扩展24KB程序存储器,须要3块。采用线译码,P2.5与第一片2764的CE相连,P2.6与第二片2764的CE相连,P2.7与第三片2764的CE相连,硬件连接如下:

P2.7 P2.6 P2.5 P2.4~P2.0 5 ALE 8 8031 G 74LS 373 OE 8 5 5 5 8 8 A0~A7 CE CE A0~A7 CE A0~A7 A8~A12 A8~A12 A8~A12 2764(1) D0~D7 OE 2764(2) OE D0~D7 8 2764(3) OE D0~D7 8 P0 EA PSEN 8 8

地址空间如下: 第一片:

1100 0000 0000 0000~1101 1111 1111 1111;即C000H~DFFFH; 第二片:

1010 0000 0000 0000~1011 1111 1111 1111;即A000H~BFFFH; 第三片:

0110 0000 0000 0000~0111 1111 1111 1111;即6000H~7FFFH;

14. 使用6264(8KB?8)芯片通过全译码法扩展24KB数据存储器,画出硬件连接图,指明各芯片的地址空间范围。

答:使用6264(8K?8)芯片通过全译码法扩展24KB程序存储器,须要3块。采用138译码器译码,硬件连接如下:

Vcc 74LS138 G1 G G2G2Y3 Y2 C Y1 B A Y0 G 74LS 8 8031 373 OE P2.7 P2.6 P2.5 P2.4~P2.0 5 ALE 8 5 5 5 8 8 A0~A7 CE CE A0~A7 CE A0~A7 A8~A12 A8~A12 A8~A12 6264(1) D0~D7 OE 6264(2) OE D0~D7 8 6264(3) OE D0~D7 8 P0 8 EA PSEN 8 地址空间如下: 第一片:

0000 0000 0000 0000~0001 1111 1111 1111;即0000H~1FFFH; 第二片:

0010 0000 0000 0000~0011 1111 1111 1111;即2000H~3FFFH; 第三片:

0100 0000 0000 0000~0101 1111 1111 1111;即3000H~5FFFH;

15. 试用一片74LS373扩展一个并行输入口,画出硬件连接图,指出相应的控制命令。

答:硬件电路图如下:74LS373的输入端为扩展的输入口,输出端接8051的数据总路线P0口,控制端接高电平,输出允许由片外数据存储器读信号RD和

P2.0控制。当片外数据存储器读信号RD和P2.0同为低平时从74LS373中读入输入的数据。

P0.0 P0.1 P0.2 P0.3 P0.4 P0.5 P0.6 P0.7 + RD P2.0 Q0 Q1 74LS Q2 Q3 373 Q4 Q5 Q6 Q7 OE D0 D1 D2 D3 D4 D5 D6 D7 G +5V 8051 输入数据的命令如下: MOV DPTR,#0FE00H MOVX A,@DPTR

16. 用8255A扩展并行I/O,实现把8个开关的状态通过8个二极管显示出来,画出硬件连接图,用汇编语言和C语言分别编写相应的程序。 答:硬件电路图如下:8051与8255的连接略,设8255的A,B,C和控制控口的地址为7F00H,7F01H,7F02H,7F03H。8255的A口接8个开关,B口接8个发光二极管。

+5V K0 PA0 PA1 PA2 PA3 PA4 系统总线 PA5 PA6 PA7 8255A PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 8051 L0 K7 L7 +5V

程序如下: 汇编程序

ORG 0000H LJMP MAIN ORG 0100H

MAIN:MOV DPTR,#7F03H

MOV A,#90H MOVX @DPTR,A

LOOP:MOV DPTR,#7F00H

MOVX A,@DPTR MOV DPTR,#7F01H MOVX @DPTR,A SJMP LOOP SJMP $ END

C语言程序: #include #include main() {

unsigned char i; XBYTE[0x7f03]=0x90; while(1) {

i=XBYTE[0x7f00]; XBYTE[0x7f01]=i;

} } } 17.

用汇编语言编写出定时扫描方式下矩阵键盘的处理程序。

该程序放于定时器的中断服务程序中。定时器每10ms中断一次,执行一次中断服务程序。F1和F2标志位用片内RAM的50H和51H单元。 ACALL KS1 JNZ LK1 MOV 50H,#0 ;无键按下,F1的F0标志清0结束 MOV 51H,#0 SJMP OUT

LK1: CJNE 50H,#1,OUT1 ;有键按下检查F1标志是否为1,不为1置1结束。

CJNE 51H,#01,OUT ;再检查F2标志是否为1,为1说明已处理按键则结束。

LK2: MOV R2,#0FEH ;扫描查询键码 MOV R4,#00H LK4: MOV DPTR,#7F00H MOV A,R2 MOVX @DPTR,A INC DPTR INC DPTR

MOVX A,@DPTR JB ACC.0,LONE MOV A,#00H AJMP LKP LONE: JB ACC.1,LTWO MOV A,#08H AJMP LKP LTWO:JB ACC.2,LTHR MOV A,#10H AJMP LKP LTHR: JB ACC.3,NEXT MOV A,#18H LKP: ADD A,R4 ;求键码放累加大器A, MOV 51H,#1 ;F2标志置1,结束 SJMP OUT

NEXT: INC R4 MOV A,R2 JNB ACC.7,KEND RL A MOV R2,A

SJMP LK4

KEND:SJMP OUT ;扫描完结束 KS1: MOV DPTR,#7F00H ;检查有无按键 MOV A,#00H MOVX @DPTR,A INC DPTR INC DPTR

MOVX A,@DPTR CPL A ANL A,#0FH RET OUT1:MOV 50H,#1 OUT: 18.

用C语言编写出定时扫描方式下矩阵键盘的处理程序。

F1和F2标志已在主函数前定义。

//************检测有无键按下函数************

uchar checkkey() //检测有无键按下函数,有返回0xff,无返回0

{uchar i;

XBYTE[0x7f00]=0x00; i=XBYTE[0x7f02]; i=i&0x0f;

if (i= =0x0f) return(0); else return(0xff); }

//************键盘扫描函数************

uchar keyscan()//键盘扫描函数,如果有键按下,则返回该键的编码,如果无键按下,则返回0xff {uchar scancode; //定义列扫描码变量

uchar codevalue; //定义返回的编码变量

uchar m; //定义行首编码变量

uchar k; //定义行检测码 uchar i,j;

if (checkkey()= =0) return(0xff); //检测有无键按下,无返回0xff else

{delay(200); //延时 if(checkkey()= =0) return(0xff); //检测有无键按下,无返回0xff

else {

scancode=0xfe;m=0x00; //列扫描码,行首码赋初值

for (i=0;i<8;i++) {k=0x01;

XBYTE[0x7f00]=scancode; //送列扫描码 for (j=0;j<4;j++)

{if ((XBYTE[0x7f02]&k)= =0) //检测当前行是否有键按下 {codevalue=m+j; //按下,求编码 while(checkkey()! =0); //等待键位释放 return(codevalue); //返回编码 m=m+8; //计算下一行的行首编码

}

else k=k<<1; //行检测码左移一位 }

scancode=scancode<<1; //列扫描码左移一位,扫描下一列 }

} } } 19. 20.

根据图7.12,编制一个在两个数码管上显示1和2的显示程序。 试编制4?4的键盘扫描程序。

答:图见书图7.12 程序:

MOV P1,#11100001B ;在第一个数码管显示1 MOV P1,#11010010B ;在第二个数码管显示2

21. 根据图7.13,用汇编语言编制一个在8个数码管上轮流显示1~8的程序。

答:图见书图7.13

程序如下:显示子程序DISPLAY见书P183,在字段码表最后放不显示的编码00H,显示缓冲区50H~57H;显示效果:在第一个数码管上显示1后,第一个数码管不显示,然后在第二个数码管上显示2,依此类推,直到在第八个上显示8。然后重复。

MOV R1,#50H MOV R4,#08H

MOV A,#10H

LOOP:

MOV @R1,A ;初始化为全部不显示。 INC R1 DJNZ R4,LOOP

START: MOV R2,#01H MOV R4,#08H

MOV R1,#50H

LOOP2: MOV A,R2 MOV @R1,A MOV R5,#0FFH LOOP1: LCALL DISPLAY DJNZ R5,LOOP1 INC R1 INC R2 DJNZ R4,LOOP2 SJMP START END

第八章

1. 简述逐次逼近型A/D转换器的工作过程。

答:逐次逼近型A/D转换器由比较器、D/A转换器、寄存器及控制电路组成。与计数型相同,也要进行比较以得到转换的数字量,但逐次逼近型A/D转换器是用一个寄存器从高位到低位依次开始逐位试探比较的。转换过程如下:开始时寄存器各位清0,转换时,先将最高位置1,送D/A转换器转换,转换结果与输入的模拟量比较,如果转换的模拟量比输入的模拟量小,则1保留,如果转换的模拟量比输入的模拟量大,则1不保留,然后从第二位依次重复上述过程直至最低位,最后寄存器中的内容就是输入模拟量对应的数字量。一个n位的逐次逼近型A/D转换器转换只需要比较n次,转换时间只取决于位数和时钟周期。逐次逼近型A/D转换器转换速度快,在实际中被广泛使用。

2. 简述ADC0809的工作过程。 答:ADC0809的工作过程如下:

(1) 输入3位地址,并使ALE=1,将地址存入地址锁存器中,经地址译码器译码从8路模拟通道中选通一路模拟量送到比较器。

(2) 送START一高脉冲,START的上升沿使逐次逼近寄存器复位,下降沿启动A/D转换,并使EOC信号为低电平。

(3) 当转换结束时,转换的结果送入到输出三态锁存器中,并使EOC信号回到高电平,通知CPU已转换结束。

(4) 当CPU执行一读数据指令时,使OE为高电平,则从输出端D0~D1读出数据。

3. 设计8路模拟量输入的巡回检测系统,使用查询的方法采样数据,采样的数据存放在片内RAM的8个单元中,分别用汇编语言和C语言编程实现。

答:硬件线路如下:

P0.0 P0.1 P0.2 P0.3 P0.4 P0.5 P0.6 P0.7 ALE 8051 WR P2.7 RD P1.0 分 频 器 D0 D1 D2 D3 D4 D5 D6 D7 ADDA ADDB ADDC CLK ALE START OE EOC IN0 IN1 IN2 IN3 IN4 IN5 IN6 IN7 VREF+ VREF- ADC0809 +5V GND + + 只把EOC信号改成连接到单片机P1.0上,其余与中断方式相同。 汇编语言编程: ADC: LOOP:

#include

ORG 0100H MOV R0,#30H ;设立数据存储区指针 MOV R2,#08H ;设置8路采样计数值 MOV DPTR,#0000H ;送入口地址并指向IN0

MOVX @DPTR,A ;启动A/D转换,A的值无意义 JNB P1.0,$ MOVX A,@DPTR ;读取转换后的数字量 MOV @R0,A ;存入片内RAM单元 INC DPTR ;指向下一模拟通道

INC R0 ;指向下一个数据存储单元 DJNZ R2,LOOP ;8路未转换完,则继续 RET ;返回

C语言编程: