通过前面4位计算机的结构、指令和程序,我们对计算机这一事物有了比较深入的理解,但这个4位机结构简单、指令集不丰富、运算速度慢、不支持高级语言编程,基本没有多少实际应用价值,仅能用来理解计算机工作原理。

这一章我们将对Intel公司出品的8051架构单片微型计算机进行讲解,并在后续章节中陆续设计出基于8051单片机的个人计算机,并且为其开发一款简单的操作系统,最终此8051计算机可以运行SD上的应用程序,可以在8051计算机上完成BASIC程序的编辑和运行。这台个人计算机将具备硬件、操作系统和应用软件的层次架构。

下面我们从结构、指令和程序三个方面来理解8051单片机。

5.1 8051单片机体系结构

8051单片机仍然符合冯诺依曼计算机设计方案。

l 二进制表示指令和数据;

l 存储程序,自动运行;

l 运算器、控制器、存储器、输入设备和输出设备。

5.1.1 8051片上资源

l 面向控制的8位CPU;

l 布尔量处理能力;

l 64KB程序地址空间;

l 64KB数据地址空间;

l 4KB片上程序存储器;

l 128字节片上数据存储器;

l 32路I/O通道;

l 2路16位定时器/计数器;

l 1个全双工串行通信口;

l 5个中断源。

5.1.2 8051结构方框图

8051单片机的功能方框图如图5-1所示,8051单片机也包括CPU(运算器和控制器)、数据存储器、程序存储器和输入/输输出5大部分。

图5-1 8051单片机功能框图

前面我们自己设计的4位计算机,每一部分都能精确到用三极管怎样实现,8051单片机具体的硬件细节无从得知,除非Intel公司完全披露,好在我们不是设计或实现8051单片机,只是大体弄明白它的硬件结构和工作原理。

图5-2 8051单片机引脚图

8051单片机常见的产品外观就是DIP40双列直插封装形式,示意图如图5-2所所示。把整个单片微型计算机封装在一个芯片内,所以简称单片机。P00~P07、P10~P17、P20~P27、P30~P37为四个8位并行的输入/输出口,其中P0、P2、P3为双功能口。P0、P2口也可用于扩展外部程序和数据存储器使用,当用于外部扩展存储器使用时,ALE、PSEN、EA、WR、RD为系统扩展的控制线。XTAL2和XTAL1为时钟输入线。RESET为复位线。Vcc为电源、Vss为地。

5.1.3 中央处理器(CPU)

中央处理器包括运算器和控制器。运算器主要功能:

l 加、减、乘、除算数运算;

l 与、或、非等逻辑运算;

l 数据传送操作;

l 位操作;

l 十进制数调整;

l 自加1、自减1运算。

控制器主要作用是协调单片机各功能部件的动作,包括取指令、指令译码、发出微操作信号、控制存储器地址/数据传送等功能。

5.1.4 程序存储器

8051单片机的程序计数器是16位的,所以可访问的程序存储器最大为64KB,地址范围为0000H到FFFFH。实际的8051芯片片内不一定有64KB ROM,可能只有4KB、8KB等,如果需要更大的程序存储器,可以扩展片外程序存储器。如图5-3所示,8051内部有4KB ROM,外扩了60KB外部ROM。当引脚EA=1时,8051先访问片内的4KB ROM,超出4KB地址范围则访问外部ROM芯片;当EA=0时,直接忽略内部ROM,完全访问外部ROM。

图5-3 8051存储器结构图

外部程序存储器的扩展方法如图5-4所示,当访问外部程序存储器时,P0自动输出低8位的地址信息到锁存器,ALE引脚输出锁存信号,低8位地址被锁存,P2口再输出高8位地址,和锁存器的低8位地址共同构成外部ROM的地址,PSEN引脚输出读信号,ROM数据通过P0口输入8051单片机,完成外部程序存储器的读。

图5-4 8051扩展外部程序存储器

5.1.5 数据存储器

指令要对数据进行操作,指令给出参与运算数据的方式称为寻址方式,8051单片机支持的寻址方式有:寄存器寻址、直接寻址、寄存器间接寻址、立即寻址和基址寄存器加变址寄存器间接寻址。

l MOV A,#20H  把20H数据直接送入累加器A,立即寻址;

l MOV A,20H  把20H地址单元里存的数据送入累加器A,直接寻址;

l MOV A,@R0  把R0寄存器里存的地址指向内存单元里的数据送入累加器A,寄存器间接寻址;

l MOV A,R0  把R0里存的数据送入累加器A,寄存器寻址;

l MOVC A,@A+DPTR  把DPTR寄存器里的值加上累加器A里的值作为新的地址,此地址指向的存储单元里的数据送入累加器,基址寄存器加变址寄存器间接寻址。

8051数据存储器空间可分成4部分:外部64KB地址空间、内部低128字节数据存储区、内部高128字节特殊功能寄存器区、内部高128字节数据存储区,数据存储区结构如图5-5所示。

图5-5 8051单片机数据存储区结构

其中内部低128字节数据存储区可以直接地址访问,内存高128字节数据存储区只能寄存器间接访问,内部高128字节特殊功能寄存器区可以直接地址访问,外部64KB存储区使用寄存器间接访问。

8051内部有一个低128字节的直接地址访问的数据存储区和一个高128字节直接地址访问的特殊功能寄存器区,更详细的划分如图5-6所示。

图5-6 8051内部直接地址访问存储区结构

1. 工作寄存器区

内部数据存储区的00H~0FH区域为四组工作寄存器区,每组有8个寄存器,用R0~R7表示,R0~R7具体位于哪一组工作寄存器区,通过PSW程序状态寄存器的第4位(RS1)和第3位(RS0)的组合指定,如果RS1RS0=“01”,则R0~R7位于第一组工作寄存器区,即R0的地址是08H,R7的地址是0FH。一旦设定好R0~R7位于的工作寄存器区的哪一组,那么剩下的其它地址单元就可以当普通RAM使用。

2. 位寻址区

内部数据存储区的20H~2FH共16字节的存储区,除了有字节地址外,还有位地址,位地址的范围是00H~7FH。8051单片机可以用字节地址访问这段内存,也可以使用位地址访问这段内存。

比如说学生宿舍楼,每个房间都有一个房间编号,假设一个房间有8个床位,我们给床位再编一个床位号,100房间床位号是00H~07H,101房间床位号就是07H~0FH,其它房间以此类推。这样编完号后,每个床位可以用两种方式表示,一种是房间号加上第几个床位,另一种是直接的床位号,房间号好比字节地址,床位号好比位地址,表示方式不同,但访问的是同一个地方。

3. 堆栈

8051单片机在中断、子程序调用、传递参数等实际应用中,通常会用到一种称之为“栈”的数据存储结构。“栈”其实就是数据存储器中的一段内存,这段内存通过一个称为“栈指针”的特殊寄存器SP记录地址,当往“栈”里写入数据时,先把SP加1,然后把数据写入SP指向的内存单元,当从“栈”里读出数据时,把SP指向的内存单元数据读出,然后SP减1。8051单片机复位时,SP指向07H地址单元,用户可根据实际情况设置SP的指向。

片内数据存储区的低128字节除了工作寄存器区和堆栈区外,其它区域都可以作为普通的内存使用。

4. 外部RAM和IO口

8051可以扩展64KB外部数据存储器或者I/O口,其中00H~FFH范围可以用R0、R1寄存器间接寻址,0000H~FFFFH范围可以使用16 位DPTR寄存器访问。8051单片机只管访问片外地址空间,至于访问是数据存储器还是外扩的I/O设备,由用户自己设计的硬件电路决定。

5. 特殊功能寄存器

8051内部的CPU寄存器、I/O端口锁存器、串口寄存器、定时器寄存器、中断控制寄存器等特殊功能寄存器字节地址编号范围是80H~FFH,地址分配如表5-1所示。

表5-1 8051特殊功能寄存器表

累加器ACC用于存放算数逻辑运算操作中的输入数和保存运算结果。

寄存器B在乘法和除法运算中作为辅助的寄存器使用,因为两个8位数相乘结果可能是16位数,只有累加器A存不下,所以使用B寄存器配合。

PSW程序状态寄存器,主要用于存储加法/减法的进位/借位信息,指定R0~R7位于哪一组工作寄存器区,存储溢出标志位和奇偶校验位等。

IP和IE都是和中断相关的寄存器,中断机制在后面讲解。

SBUF和SCON是串口通信相关寄存器,串口也在后面讲解。

TH1、TH0、TL1、TL0、TMOD和TCON是计数器寄存器,计数器后面讲解。

DPH和DPL组合到一起就是16位的DPTR寄存器,访问片外程序存储器和片外数据存储器时,DPTR用于存储地址信息。

SP是堆栈指针,用于指示栈顶的地址。

P0、P1、P2、P3是通用I/O的寄存器,可以输出数据和读入数据。

带星花的特殊功能寄存器除了可以字节寻址外,还可以位寻址,也就是说它们还有一个位地址,位地址编号为80H~FFH,与前面可位寻址的RAM共同构成00H~FFH的256个位寻址空间。

6. 外部数据存储器的扩展

当需要外部扩展数据存储器时,接口可参考图5-7所示。P0输出低8位地址,ALE输出锁存信号,锁存器锁存低8位地址,然后P2口输出的高地址和锁存器里的低8位地址组成外部RAM的地址,如果是写入RAM数据,那么P0口输出待写入数据,WR引脚输出写信号,数据写入RAM相应地址单元,如果是读出数据,那么RD引脚输出读信号,RAM读出的数据通过P0口输入8051单片机。

图5-7 外部数据存储器的扩展结构

5.1.6 中断

CPU正在按顺序一条条执行指令的时候,有紧急事件发生了,CPU被迫中断当前正在执行的程序,转而去处理紧急事件,处理完紧急事件后再返回中断处继续执行,这种机制就叫中断,能够请求CPU中断的来源称为中断源,8051单片机中断源及入口地址如表5-2所示。

表5-2 8051单片机中断源和中断入口

中断源

中断入口

外中断0

0003H

定时器0

000BH

外中断1

0013H

定时器1

001BH

串口中断

0023H

以定时器0溢出产生中断为例,当定时器0记数达到最大值溢出后,会产生一个中断标志,CPU硬件会在每一个机器周期(标准8051的机器周期是12个时钟周期)末尾检查是否有中断需要处理,如果有中断到来,就把当前执行到的程序地址压入堆栈保存,然后把定时器0对应的中断入口000BH输入到程序计数器PC,也就是CPU跳转到000BH处执行,000BH处往往安排一条跳转指令,直接跳转到定时器0的中断处理子程序并执行,在子程序末尾会安排一条中断返回指令,中断返回指令会把压入栈的地址弹出到程序计数器PC中,也就是返回到中断前程序处继续执行。

5.1.7 外围设备

8051单片机一般都有并行输入/输出口、定时器和串行通信口等几种常见的外围设备,一般外围设备都是由寄存器和功能部件构成,寄存器都有地址,往寄存器里写入/读出数据,寄存器再和功能部件产生电路上联系,最终通过控制寄存器就行控制这种外围设备。

1. P口

8051单片机有P0、P1、P2和P3共32个通用输入/输出口,输入输出口的功能,可以理解为:往P1特殊功能寄存器里写入数据,数据会通过芯片P1口的8个引脚输出,读取P1特殊功能寄存器里的数据(MOV A,P1),就相当于把P1口的8个引脚上的高低电平读入计算机。P1、P2和P3都具有第二功能,比如外扩程序和数据存储器时用到的地址和数据功能,只有P1口是纯粹的输入输出口,P1口的结构如图5-8所示。

图5-8 P1口结构图

由图5-8可见,当把数据写入特殊功能寄存器时,实际上就是写入到了图中的D触发器中,如果写入1,Q—输出0,再经过一个反相器后,引脚上正好输出一个1。如果用MOV A,P1指令,则只是读取数据,会读引脚数据;如用OR P1,#0FFH等指令,则是读出-运算-写回,会读取寄存器里数据。

另外需要注意,P0口是开漏输出,做I/O口输出1时,实际输出的是高阻态,必须接上拉电阻后才能有效输出1的功能;P1、P2、P3内部都有一个比较大的上拉电阻,也就意味着当输出1时,实际是串联了一个大电阻再输出的,所以驱动电流比较小。如果要驱动较大功率的器件,可以使用“灌电流”的方式,也就是引脚输出0,外部器件接高电平,让电流流进引脚,形成灌电流;也可以在引脚外再用一个小电阻与片内的上拉电阻并联,并联后再接外部器件,因为并联后总电阻小于外接的小电阻,所以电流驱动能力也比较大。

2. 定时器

定时器配合定时器中断,可以实现类似闹钟提醒的功能。定时器包括一个记数时钟和一个计数器,可以给计数器设置一个初始值,记数时钟频率也可选择,这样在记数时钟驱动下,计数器从初始值开始累加,当记数到最大值后发生溢出,并会产生一个定时器中断,定时器中断的间隔可以通过记数时钟频率和计数器初始值计算得出,有了定时器就可以实现定时处理事情了,比如定时扫描键盘、输出设定占空比的脉冲信号等功能。

3. 串口

不同计算机之间往往需要传递信息或传输数据,那么就需要通信,串口可以实现串行通信,并口(前面提到的P口)可以实现并行通信。一般串行通信速率较慢,但连线少,并行通信则相反。

8051单片机最简单的串口通信只需一根地线,一根数据接收线,一根数据发送线。通信双方设置好发送和接收数据的波特率,发送方把待发送的字节数据写入发送寄存器SBUF,串口设备把SBUF里数据转换成8个脉冲信号,并且添加上起始位和停止位发送出去,接收方再把收到的脉冲信号还原成字节,并存入接收方的SBUF接收寄存器,接收单片机通过读取SBUF寄存器接收数据。异步串行通信的一种帧格式如图5-8所示。

图5-8 异步串行通信帧格式

从异步串行通信的帧格式可以看出,一个数据帧通常包括1位起始位、8位二进制数据位、1位停止位。一秒钟能传输的二进制位的个数称为波特率,波特率确定了两个二进制位之间的时间间隔,接收双方只有相同的波特率才能通信成功。两个数据帧之间的时间间隔没有要求,一个数据帧除了数据位还包括起始位等无效数据,所以最终的有效数据传输速率肯定小于波特率。

常用的波特率有9600、19200、38400、57600、115200等,波特率可以通过设置8051单片机的相关寄存器进行设定。

5.2 8051指令集

二进制的指令编码方便记忆,所以设计了助记符与二进制编码对应,助记符也就是汇编语言,8051单片机总共有111条汇编指令。按指令编码字节数分类,有49条单字节指令、45条双字节指令和17条3字节指令;按指令执行周期分类,有64条单周期指令、45条双周期指令和2条4周期指令;按照指令完成的功能分类,有数据传送类、算术运算类、逻辑运算类、位操作类和控制转移类指令。

1. 8051指令集介绍

8051指令的16进制编码、助记符和功能解释如表5-3所示,其中:

l Rn 表示寄存器 R0-R7;

l Ri 表示 R0、R1;

l addr 表示直接8位地址;

l addr 11 表示 11 位地址,addr 16 表示 16 位地;

l #data 表示8位立即数,#data16表示16位立即数;

l bit 表示位地址;

l rel 表示相对地址,范围是-128到127;

l @表示间接寻址;

l ->表示数据传送;

l <->表示数据交换

l (R0)表示R0里的数据;

l (addr)表示addr地址指向的内存单元里的数据;

l ((R0))表示R0里存储的地址指向的内存单元里的数据;

l data7~0表示data的第0位到第7位。

表5-3 8051指令集表

助记符

指令编码

说明

第1字节

第2字节

第3字节

MOV A,Rn

E8~EF

(Rn)->A

MOV A,addr

E5

(addr)->A

MOV A,@Ri

E6、E7

((Ri))->A

MOV A,#data

74

data->A

MOV Rn,A

F8~FF

(A)->Rn

MOV Rn,addr

A8~AF

(addr)->Rn

MOV Rn,#data

78~7F

data->Rn

MOV addr,A

F5

addr

(A)->addr

MOV addr,Rn

88~8F

addr

(Rn)->addr

MOV addr2,addr1

85

addr1

addr2

(addr1)->addr2

MOV addr,#data

75

addr

data

data->addr

MOV addr,@Ri

86,87

addr

((Ri))->addr

MOV @Ri,A

F6,F7

(A)->(Ri)

MOV @Ri,addr

A6,A7

addr

(addr)->(Ri)

MOV @Ri,#data

76,77

data

data->(Ri)

MOV DPTR,#data16

90

data1615~8

data167~0

data1615~8->DPH

data167~0->DPL

PUSH addr

C0

addr

(SP)+1->SP

(addr)->(SP)

POP addr

D0

addr

((SP))->addr

(SP)-1->SP

XCH A,Rn

C8~CF

(A)<->(Rn)

XCH A,addr

C5

addr

(A)<->(addr)

XCH A,@Ri

C6,C7

(A)<->((Ri))

XCHD A,@Ri

D6,D7

(A)3~0<->((Ri))3~0

MOVX A,@DPTR

E0

((DPTR))->A

MOVX A,@Ri

E2,E3

((Ri))->A

MOVX @DPTR,A

F0

(A)->(DPTR)

MOVX @Ri,A

F2,F3

(A)->(Ri)

MOVC A,@A+PC

83

((A)+(PC))->A,

访问的是程序存储器

MOVC A,@A+DPTR

93

((A)+(DPTR))->A,

访问的是程序存储器

ADD A,Rn

28~2F

(Rn)+(A)->A

进位->CY

ADD A,addr

25

addr

(addr)+(A)->A

进位->CY

ADD A,@Ri

26,27

((Ri))+(A)->A

进位->CY

ADD A,#data

24

data

data+(A)->A

进位->CY

ADDC A,Rn

38~3F

(CY)+(Rn)+(A)->A

进位->CY

ADDC A,addr

35

addr

(CY)+(addr)+(A)->A

进位->CY

ADDC A,@Ri

36,37

(CY)+((Ri))+(A)->A

进位->CY

ADDC A,#data

34

data

(CY)+data+(A)->A

进位->CY

INC A

04

(A)+1->A

INC Rn

08~0F

(Rn)+1->Rn

INC addr

05

addr

(addr)+1->addr

INC @Ri

06,07

((Ri))+1->(Ri)

INC DPTR

A3

(DPTR)+1->DPTR

DA A

D4

(A)BCD调整->A

SUBB A,Rn

98~9F

(A)-(Rn)-(CY)->A

借位->CY

SUBB A,addr

95

addr

(A)-(addr)-(CY)->A

借位->CY

SUBB A,@Ri

96,97

(A)-((Ri))-(CY)->A

借位->CY

SUBB A,#data

94

data

(A)-data-(CY)->A

借位->CY

DEC A

14

(A)-1->A

DEC Rn

18~1F

(Rn)-1->A

DEC addr

15

addr

(addr)-1->addr

DEC @Ri

16,17

((Ri))-1->(Ri)

MUL AB

A4

(A)乘以(B),积的高字节送入A,低字节送入B

DIV AB

84

(A) 除以(B),商送入A,

余数送入B

CLR A

E4

0->A

CPL A

F4

(A)按位取反->A

RL A

23

左环移1位,第7位移入第0位

RLC A

33

左环移1位,第7位移入CY,(CY)移入第0位

RR A

03

右环移1位,第0位移入第7位

RRC A

13

右环移1位,第0位移入CY,(CY)移入第7位

SWAP A

C4

(A)3~0<->(A)7~4

ANL A,Rn

58~5F

(A)与(Rn)->A

ANL A,addr

55

addr

(A)与(addr)->A

ANL A,@Ri

56,57

(A)与((Ri))->A

ANL A,#data

54

data

(A)与data->A

ANL addr,A

52

addr

(addr)与(A)->addr

ANL addr,#data

53

addr

data

(addr)与data->addr

ORL A,Rn

48~4F

(A)或(Rn)->A

ORL A,addr

45

addr

(A)或(addr)->A

ORL A,@Ri

46,47

(A)或((Ri))->A

ORL A,#data

44

data

(A)或data->A

ORL addr,A

42

addr

(addr)或(A)->addr

ORL addr,#data

43

addr

data

(addr)或data->addr

XRL A,Rn

68~6F

(A)异或(Rn)->A

XRL A,addr

65

addr

(A)异或(addr)->A

XRL A,@Ri

66,67

(A)异或((Ri))->A

XRL A,#data

64

data

(A)异或data->A

XRL addr,A

62

addr

(addr)异或(A)->addr

XRL addr,#data

63

addr

data

(addr)异或data->addr

MOV C,bit

A2

Bit

(bit)->CY

MOV bit,C

92

Bit

(CY)->bit

CLR C

C3

0->CY

CLR bit

C2

Bit

0->bit

CPL C

B3

(CY)取反->CY

CPL bit

B2

Bit

(bit)取反->bit

SETB C

D3

1->CY

SETB bit

D2

Bit

1->bit

ANL C,bit

82

Bit

(CY)与(bit)->CY

ANL C,/bit

B0

Bit

(bit)先取反,然后与(CY)->CY

ORL C,bit

72

bit

(CY)或(bit)->CY

ORL C,/bit

A0

bit

(bit)先反,然后或(CY)->CY

AJMP addr11

a10a9a80 0001

a7a6a5a4

a3a2a1a0

(PC)+2->PC

addr1110~0->PC10~0

SJMP rel

80

rel

(PC)+2->PC,(PC)+rel->PC

LJMP addr16

02

addr1615~8

addr167~0

addr16->PC

JMP @A+DPTR

73

(A)+(DPTR)->PC

JZ rel

60

rel

(PC)+2->PC

如果(A)=0,则(PC)+rel->PC;

否则执行下一条指令

JNZ rel

70

rel

(PC)+2->PC

如果(A)不为0,则(PC)+rel->PC;

否则执行下一条指令

JC rel

40

rel

(PC)+2->PC

如果(CY)=0,则(PC)+rel->PC;

否则执行下一条指令

JNC rel

50

rel

(PC)+2->PC

如果(CY)不为0,则(PC)+rel->PC;

否则执行下一条指令

JB bit,rel

20

bit

rel

(PC)+3->PC

如果(bit)=1,则(PC)+rel->PC;

否则执行下一条指令

JNB bit,rel

30

bit

rel

(PC)+3->PC

如果(bit)=0,则(PC)+rel->PC;

否则执行下一条指令

JBC bit,rel

10

bit

rel

(PC)+3->PC

如果(bit)=1,则(PC)+rel->PC,

0->bit;否则执行下一条指令

CJNE A,addr,rel

B5

addr

rel

(PC)+3->(PC)

如果(A)不等于(addr),

则(PC)+rel->(PC);

否则执行下一条指令

CJNE A,#data,rel

B4

data

rel

(PC)+3->(PC)

如果(A)不等于data,

则(PC)+rel->(PC);

否则执行下一条指令

CJNE Rn,#data,rel

B8~BF

data

rel

(PC)+3->(PC)

如果(Rn)不等于data,

则(PC)+rel->(PC);

否则执行下一条指令

CJNE @Ri,#data,rel

B6,B7

data

rel

(PC)+3->(PC)

如果((Ri))不等于data,

则(PC)+rel->(PC);

否则执行下一条指令

DJNZ Rn,rel

D8~DF

rel

(PC)+2->PC,(Rn)-1->Rn

如果(Rn)不等于0,

则(PC)+rel->(PC);

否则执行下一条指令

DJNZ addr,rel

D5

addr

rel

(PC)+2->PC,(addr)-1->addr

如果(addr)不等于0,

则(PC)+rel->(PC);

否则执行下一条指令

ACALL addr11

a10a9a81

0001

a7a6a5a4

a3a2a1a0

(PC)+2->PC

(PC)->SP

addr1110~0->PC10~0

LCALL addr16

12

addr1615~8

addr167~0

(PC)+3->PC

(PC)->SP

addr16->PC

RET

22

(SP)->PC,调用返回

RETI

32

(SP)->PC,中断返回

NOP

00

空操作

2. 调用与转移

调用指令(LCALL)和转移(LJMP)指令都会带来程序的跳转,但调用指令会把当前地址压入堆栈保存,所以调用指令通过RET指令可以返回,但转移指令则不行。

3. 调用与中断

调用和中断都把当前地址压入堆栈保存,都可以返回。调用是软件行为,而中断是硬件行为,并且中断还要清除中断标志、设置中断优先级状态寄存器等操作。调用用RET返回,中断用RETI返回,RETI指令除了把保存的地址弹出到PC外,还要清除中断响应时所置位的中断优先级状态寄存器。

4. 时钟周期、机器周期、指令周期

时钟周期就是最基本的晶振周期;8051单片机的1个机器周期包括12个时钟周期,完成指令的取指、译码、读操作数、执行、写结果等流程;指令周期就是一条指令的执行需要几个机器周期,比如乘除法需要4个机器周期,其它指令都是1到2个机器周期完成。

5. 汇编伪指令

在讲解简单的4位计算机时,汇编代码是通过手工翻译成机器码的,耗时费力且容易出错,8051这里将用汇编器完成汇编语言的翻译工作。8051汇编器除了能翻译汇编指令为机器码外,还定义了很多伪指令,伪指令是用户想要传给汇编器的信息,通常不对应专门的机器码,伪指令主要有:

l ORG addr:指出后面的代码从程序存储器的addr地址处开始放置;

l DB d0,d1,d2,……,dn:把d0~dn字节数存入程序存储器,地址不确定;

l LABEL:一段汇编程序的标号,汇编器会计算出来LABEL后第一条指令的地址,代码中就可以使用LABEL,如LJMP LABEL;

l P0 EQU 80H:P0符号等价于80H,汇编器会把P0自动替换成80H;

l LED bit 87H:LED标号等价于位地址87H,汇编器把LED替换成87H;

l END:汇编代码结束,后面即使还有程序也不会再处理;

l 注释:一行汇编指令后面用“;”注释,汇编器不处理分号后内容。

5.3 汇编小程序

5.3.1 终端命令控制LED灯

通过串口终端发送命令控制两个LED的亮灭,Proteus仿真原理图如图5-9所示。

图5-9 命令控制LED灯仿真原理图

1. 程序原理

无论是写汇编程序,还是高级语言程序,基本思路都是化繁为简。在主函数中把复杂问题化为较简单的若干模块,在子函数中实现每个模块,如果模块仍然复杂,那么就进一步简化,总之就是简化、简化,一直简化到能实现为止。

比如我们这个汇编小程序,可以在主函数中分成串口初始化和接收命令,在子函数中实现命令处理,直接处理命令不好解决,那么再写一个字符串比较子函数,一步步细化到好实现为止。

主程序流程图,命令处理子程序流程图、字符串比较子程序流程图如图所示。。。。。。

2. 源代码及注释

LED1 BIT 90H

LED2 BIT 91H

;*******主程序开始*************************

ORG 0

MAIN:

;串口初始化

MOV TMOD,#20H ;选择定时器1,处于定时器工作方式2

MOV TL1,#0FDH ;根据计算公式,初始值为FDFDH时,波特率是9600

MOV TH1,#0FDH

MOV SCON,#50H ;串口工作方式1,即1-8-1,允许接收数据

MOV PCON,#00H ;波特率不加倍

SETB TR1     ;允许定时器1开始计数

;先关闭LED灯

CLR 90H

CLR 91H

;接收命令并回显,保存命令至RAM 70~7F

RCMD: MOV R0,#70H

WAIT1: JNB RI,WAIT1 ;等待接收命令

CLR RI

MOV A,SBUF

MOV @R0,A ;保存接收到的一个字符

INC R0 ;指向下一个地址

MOV SBUF,A ;发送回显

WAIT2: JNB TI,WAIT2 ;如果发送没有完成,则等待发送完

CLR TI

CJNE A,#0DH,WAIT1 ;如果没有接收到回车符,那么继续接收下一个字符

LCALL PCMD ;如果接收到回车符,认为收到了一条完整的命令,处理命令

LJMP RCMD ;重新接收新命令

;**********主程序结束**************************************************

;********命令处理子程序开始****************

PCMD: MOV R0,#60H

MOV R1,#0H

RON1: MOV A,R1 ;把on 1字符串读取到到RAM 60H处

MOV DPTR,#ON1

MOVC A,@A+DPTR

MOV @R0,A

INC R0

INC R1

CJNE A,#0DH,RON1 ;字符串以回车结尾,没回车则继续读取

LCALL CMPCMD ;命令比较,返回值存入R3,字符串相等,则R3=0

MOV A,R3

JNZ CMPON2 ;如果不是on 1,则继续比较是不是其它命令

SETB LED1 ;是on 1,则开LED1

RET ;返回,继续接收新命令

CMPON2: MOV R0,#60H

MOV R1,#0H

RON2: MOV A,R1 ;判断是不是on 2命令

MOV DPTR,#ON2

MOVC A,@A+DPTR

MOV @R0,A

INC R0

INC R1

CJNE A,#0DH,RON2

LCALL CMPCMD

MOV A,R3

JNZ CMPOF1

SETB LED2

RET

CMPOF1: MOV R0,#60H

MOV R1,#0H

ROFF1: MOV A,R1 ;判断是不是off 1命令

MOV DPTR,#OFF1

MOVC A,@A+DPTR

MOV @R0,A

INC R0

INC R1

CJNE A,#0DH,ROFF1

LCALL CMPCMD

MOV A,R3

JNZ CMPOF2

CLR LED1

RET

CMPOF2: MOV R0,#60H

MOV R1,#0H

ROFF2: MOV A,R1 ;判断是不是off 2命令

MOV DPTR,#OFF2

MOVC A,@A+DPTR

MOV @R0,A

INC R0

INC R1

CJNE A,#0DH,ROFF2

LCALL CMPCMD

MOV A,R3

JNZ CMDERR

CLR LED2

RET

CMDERR: MOV R0,#0 ;如果哪个命令都不是,那就是命令错误

SENT: MOV A,R0

MOV DPTR,#ERROR

MOVC A,@A+DPTR

JNZ PRINT

RET ;返回重新接收新命令

PRINT: MOV SBUF,A

WAIT: JNB TI,WAIT ;如果发送没有完成,则等待发送完

CLR TI

INC R0

LJMP SENT

;**************命令处理程序结束**********************

;*******字符串比较函数****************************

;70H和60H开始挨个做差,差存入R3,遇到回车返回,

;差不为0也返回,R3=0为相等,否则不等

CMPCMD: MOV R3,#0H

MOV R0,#70H

MOV R1,#60H

LOOP: MOV A,@R0

SUBB A,@R1

MOV R3,A

CJNE @R0,#0DH,CON ;回车表示比较完成

RET

CON: INC R0

INC R1

JZ LOOP ;字符相等,则比较下一个字符

RET ;只要遇到不相等,则比较完成

;***********预存入ROM中的数据************

ON1: DB 'on 1'

DB 0DH

ON2: DB 'on 2'

DB 0DH

OFF1: DB 'off 1'

DB 0DH

OFF2: DB 'off 2'

DB 0DH

ERROR: DB 'cmd error'

DB 0DH

END

3. 仿真步骤

l 新建proteus工程,并绘制如图所示原理图;

l 在新建工程目录下创建code目录,code目录里创建led.asm文件文件,把汇编源代码录入led.asm;

l Proteus->source->add/remove source files里添加源文件led.asm,并选择ASEM51,然后build all;

l 仿真原理图中双击80c51单片机,并选择程序led.hex,执行仿真;

l 通过终端输入led开关的命令,查看程序执行的情况;

l 可以任意时刻暂停仿真,单片机上右键,选择查看特殊功能寄存器、内存单元里的内容,也可以调试汇编代码。

第5章 8051单片机工作原理相关推荐

  1. 串口 单片机 文件_通俗易懂的单片机工作原理

    单片机工作原理: 1.主要器件cpu(负责运算与控制).存储器(程序存储在ROM存储器中,临时变量存放在RAM存储器中).IO(输入.输出),三者相互配合实现单片机的运行. 2.同步:多个独立的部分按 ...

  2. 《Android开发艺术探索》读书笔记 (4) 第4章 View的工作原理

    本节和<Android群英传>中的第3章Android控件架构与自定义控件详解有关系,建议先阅读该章的总结 第4章 View的工作原理 4.1 初始ViewRoot和DecorView ( ...

  3. 第五章 路由器的工作原理及其配置

    第五章 路由器的工作原理及其配置 5.1 广域网服务 WAN连接的目的是在两个远离的网络之间尽可能高效率传递数据.连接的效率越高,到最终用户的连接就越透明.WAN连接通常比L A N连接要慢.例如,一 ...

  4. 【hadoop权威指南第四版】第六章MR的工作原理【笔记+代码】

    6.1 运行MR作业 工作原理 四大模块: 客户端,提交MR作业. jobtracker,协调作业的运行.jobtracker 是一个java应用程序,主类是Jobtracker. tasktrack ...

  5. 第3章 直流电机的工作原理及特性 学习笔记(一)

    本周主要学习了直流电机的基本结构及工作原理,需要复习到的知识主要有电磁感应定律和电磁力定律,即安培定律.法拉第定律.洛伦兹定律. 一.基本结构 根据工作原理,直流电机的组成可分为定子.转子和换向器三部 ...

  6. 第一章 仿真器的工作原理

    用过Keil的小伙伴们肯定对Ulink很熟悉.在日常的程序开发中,我们往往需要利用Debug的模式对程序进行调试以找到Bug的位置或者是程序运行到某一步的状态.在软件开发,特别是前端的开发过程中,可以 ...

  7. 第16章 以太网交换机工作原理(H3CNE)

    在局域网中,交换机是非常重要的网络设备,负责在主机之间快速转发数据帧.交换机与集线器的不同之处在于,交换机工作在数据链路层,能够根据数据帧中的MAC地址进行转发.本文重点讲述了交换机进行MAC地址学习 ...

  8. 第三章 Switch的工作原理

    Switch的工作原理 一.协议是什么,为什么要有协议,LAN协议有哪些,WAN协议有哪些? 协议 Protocol 局域网协议(LAN)Ethernet协议,规定了数据收发的规则,Token Rin ...

  9. 全干货,一篇文章明白电机工作原理

    为什么要了解电机的工作原理 在我们生活场景中,电机的应用非常广泛,电风扇.洗衣机驱动电机.冰箱散热风扇.玩具车驱动电机.电脑散热风扇.抽油烟机风扇等,几乎所有的家用电器都会用到电机,可以说没有了电机, ...

最新文章

  1. [转][android深入学习]android窗口管理机制
  2. 运维如何逆袭?月薪30K的牛逼运维需要的知识,全在这里了
  3. boost::hana::reverse_fold用法的测试程序
  4. 起点低,是彪悍的最好证明!
  5. 红帽峰会2015所需的JBoss BPM内容指南
  6. 【转】如何让ucgui支持24位色(24bpp)
  7. word2vector数据集样式_这样做数据可视化驾驶舱,高端大气,一目了然,领导不点赞都难...
  8. python读取大文件内容_python读取大文件
  9. kylin: build cube Hbase: Region Server 意外退出
  10. Python+OpenCV:基于分水岭算法的图像分割(Image Segmentation with Watershed Algorithm)
  11. 15个优秀的第三方 Web 技术集成
  12. 宿主机172连接容器mysql_开发时从宿主机连接容器中的MySQL
  13. 启用RHEL5.6的VNC,使Windows可图形远程控制
  14. RRC 常用名词解释
  15. 微信小程序路线规划导航,选择起点和终点路线规划
  16. 命里有时终须有,命里无时莫强求
  17. 计算机左侧没有桌面菜单栏,教您电脑菜单栏不见了
  18. 文件关联注册表项都有哪些?
  19. Cursor的使用和下载
  20. Sigma Designs SMP8910媒体处理器的3DTV、蓝光和OTT体验

热门文章

  1. 什么是数据库?数据库的作用想学数据库必看 (1)
  2. Java工作4年来应聘要16K最后没要,细节如下。。。
  3. 关于C语言文件的读写
  4. 今日运势 酷q_《意大利grand老妇人》电影_意大利grand老妇人老版国语字幕-内蒙古呼和浩特铁路预防职务犯协会...
  5. 在python中请求百度easyDL
  6. onCreate()方法
  7. 论文笔记 | 基于深度学习的乳腺转移瘤识别(Deep Learning for Identifying Metastatic Breast Cancer)
  8. 家庭观念算老几?(转)
  9. UTXO:未使用的交易输出
  10. 【浙江大学C小程week1整理】