
任务一 点亮一个LED灯
任务描述
编写一个单片机程序,让P1口发光二极管全灭,然后点亮P1.0的发光二极管,并下载到实验板运行。
实验板上发光二极管的连接图如图1-1所示,实验板上的发光二极管通过电阻直接连接到单片机P1端口,当引脚输出高电平时发光二极管导通发光,当引脚输出低电平时发光二极管熄灭。
针对目前的单片机这种连接方法可以实现发光二极管点亮,但是发光亮度较低,因此工程上一般用发光二极管的负极接入单片机引脚,如图1-2所示,单片机吸收电流点亮发光二极管,这时单片机基本能具备使发光二极管正常发光的驱动电流,此时单片机输出低电平发光二极管点亮,输出高电平则发光二极管熄灭。
任务分析
本任务的目的是学会:①如何使用单片机控制发光二极管;②学习汇编编写惯例格图1-1 实验板上发光二极管的连接图


图1-2 发光二极管的一种连接图
式;③学习几个常见汇编指令;④编写一个程序控制单片机点亮发光二极管。
任务实施
一、认识单片机
(一)单片机的内部资源
单片机芯片如图13所示,把编写的程序下载到芯片中就能实现对其的控制。实际上主要控制芯片的输入/输出引脚的电平,即我们要求哪个引脚的电平在什么时刻变高/变低,这个引脚的电平就会在那个时刻变高/变低。
那么,程序在哪里写?怎么写?写完后怎么下载到单片机里去?下载进去后,什么条件才能工作?我们可以用单片机做什么?这些问题就是本课程的学习内容。
首先,单片机由中央处理器(CPU)、数据存
储器(RAM)、程序存储器(ROM)、定时器、通

信口、输入/输出接口组成。类似于PC机,CPU负责运算、控制,加、减、乘、除、与、或、非等运算,读、写、输入、输出等控制,都是用复
图1-3 单片机芯片
杂的数字电路实现;RAM相当于内存条,CPU在运算过程中总会要临时存放一些中间数据,RAM提供了这些数据的存放空间,所以又称为数据存储器,断电后数据丢失;ROM相当于硬盘,编写好的程序最后放在ROM中,所以又称为程序存储器,断电后数据不丢失;接口简单地看就是引脚,通过引脚,单片机可以输出电平,也可检测这个引脚当前连接的电平状态,通过电平输入输出来实现键盘、显示器、通信等设备的控制。
单片机内部可供用户使用的三大资源:
(1)ROM。其特点是可重复擦写程序、容量大、价格低。
(2)RAM。其特点是读写速度快、理论上寿命无限(程序运行的每时每刻都在读写中间数据)。
(3)SFR(特殊功能寄存器)。单片机有很多功能,通过对SFR的读写来实现这些功能。
单片机内部资源的3个主要部分清楚后,选择AT89C51单片机来进行详细学习。AT89C51单片机是Atmel公司出品的一款51内核的单片机,具有标准的51体系结构和全部的51 标准功能,程序下载方式简单,方便学习。它的ROM程序空间是4K 字节
(1K=1024 字节,1 字节=8 位),RAM 数据空间是128 字节,SFR在后边将会逐一提
到并应用。
(二)单片机最小系统
单片机最小系统,也称为单片机最小应用系统,是指用最少的元件组成的能工作的单片机系统。单片机最小系统的三要素是电源、晶振和复位电路,最小系统电路如图1-4所示。
1.电源
电子设备都需要供电,主流单片机的电源有5V和3.3V两个标准,还有一些对电压要求更低的单片机系统。从图1-4可以看到,供电电路在40 脚和20脚的位置上,40脚接UCC,代表电源的正极,20脚接GND,代表电源的负极。一般情况下,这种双列直插封装的芯片,左上角是1脚,逆时针旋转引脚号依次增加,一直到右上角是最大脚位。现在选用的单片机一共40 个引脚,因此右上角就是40,单片机引脚图如图1-5所示。

图1-4 单片机最小系统电路


图1-5 单片机引脚图
图1-6 单片机系统典型晶振电路
2.晶振
晶振又叫晶体振荡器,为单片机系统提供基准时钟信号,单片机控制都是以这个时钟信号为基准。图1-5所示这种双列直插封装的单片机的18脚和19脚是晶振的引脚,通
常接一个11.0592M的晶振(震荡11,059,200次/s),晶振两端接两个谐振电容,一般
大小为20~30pF左右,谐振电容过大晶振不容易振荡,过小则晶振不稳定。典型晶振电路如图1-6所示。
3.复位电路
图1-4左侧是一个复位电路,接在单片机的9脚RST(Reset)复位引脚上,只要RST一定时间内保持高电平,单片机复位,所有程序重新开始执行。单片机复位一般有上电复位、手动复位和程序自动复位3种情况。
(1)上电复位。当程序还没运行完突然停电了,单片机内部有些区域的中间数据会丢失,有些区域的中间数据保存了下来,当再次打开设备(上电)时,希望单片机能正常运行,所以上电后单片机要进行一个内部的初始化过程,这个过程即为上电复位。上电复位保证单片机每次启动都从一个固定的相同的状态开始工作。
(2)手动复位。当单片机死机或程序跑飞时,按下复位按键,使程序重新初始化并重新运行,这个过程就叫手动复位。
(3)程序自动复位。单片机往往有一套自动复位机制,例如看门狗,如果程序长时间失去响应,单片机看门狗模块会自动复位重启单片机。
单片机具备电源、晶振、复位3个条件就可以运行下载的程序,通过程序就能控制连接在单片机I/O口的外部设备,如LED灯、数码管、液晶显示器等设备。
这里再补充一点输入/输出端口(I/O口)的知识,如图1-4所示,单片机共有P0、
P1、P2、P3 4个输入/输出端口。P0口占用8个引脚P0.0~P0.7,P0.7是高位,P0口
为一个8位漏级开路双向I/O口,这决定了P0口作为固定电平输出时需要接上拉电阻。P1、P2、P3口这三大端口也各占用8个引脚,每个引脚内部提供上拉电阻,是一个8位双向I/O口。这些端口作为输入时需要在端口写入“1”,被内部上拉为高电平,即先输出高电平一次才可用作输入。P3口也可作为一些特殊功能口,见表1-1。
表1-1
P3口特殊功能

多功能口并不局限于P3口,一些单片机几乎每个引脚都是多功能的,编程使用时根据需要使用一种功能。
二、指令系统
51单片机的指令集包括数据传送指令、算术运算指令、逻辑运算指令、位运算指令和控制转移指令五大类共111条指令,这111条指令的集合即为51单片机的指令系统,每条指令都有一个唯一的名称,即助记符,便于记忆与书写。除位运算以外,指令都是以字节为单位,因此也统称为字节运算指令。根据指令的长短可分为单字节指令、双字节指令和三字节指令,根据执行的时间来分可分为单周期指令、双周期指令和四周期指令。(一)汇编语言寻址方式
一条指令通常由操作码和地址码两部分组成。操作码指明CPU要完成何种类型和性质的操作,如数据转移、加法、取反等。地址码指明操作对象所在单元地址,通过地址码找到操作数的方法称为寻址方式,51单片机支持6种不同的寻址方式。由于51单片机运算器的特有结构,CPU所有的字节运算都有A寄存器的参与,因此每条字节运算指令的地址码中不会再包含A寄存器的地址。
1.直接寻址方式
直接寻址是在指令中直接给出操作数所在的单元地址,指令执行时,直接在RAM中的该单元地址读取操作数据,例如“MOV A,12H”是将RAM中12H存储单元的值赋予A。直接寻址仅限于内部RAM(包括特殊功能寄存器)进行寻址,对于具有高128字节与特殊功能寄存器地址重复的存储区间,只能使用间接方式寻址。
2.寄存器寻址方式
寄存器寻址是在指令中给出操作数所在的寄存器,范围是从R0~R7,他们在RAM
中的地址是由PSW中RS1、RS0两个位决定。例如“MOV A,R1”当RS1RS0=00时,“MOV A,R1”与“MOV A,01H”的运行结果是一样的,即R0当前指向地址为01H
的存储单元。
3.立即寻址方式
立即寻址是在指令中直接给出操作数,一般把这个操作数称为立即数。例如“MOV A,#2BH”表示将2BH这个立即数赋予A。因为立即数不会凭空出现,所以2BH是存放于ROM中的常量。显然,这里的寻址“寻”的不是RAM,而是ROM。51单片机指令系统中还有一条16位立即寻址指令“MOV DPTR,#data16”,其功能是将16位立即数赋予数据指针DPTR。
4.间接寻址方式
间接寻址是将寄存器的内容作为单元地址,再通过该单元地址去找操作数的寻址方式,这里的寄存器称为间接寻址寄存器,只能用R0或R1。例如指令“MOVA,@R0”,其功能就是将R0的内容所指向的存储单元的数据赋予A。例如R0=12H,(12H)=
34H,那么指令“MOV A,12H”或“MOV A,#34H”与上面的指令执行后的结果一
样,A都为34H。另外,间接寻址还用于高128字节空间(80H~FFH)的寻址任务。
5.变址寻址方式
变址寻址与间接寻址有点类似,变址寻址是以DPTR或PC为基址寄存器,以A为变址寄存器,将两者相加后的16位数结果作为操作数所在单元地址。变址寻址只能对程
序存储器ROM使用,寻址范围为64K(0000H~FFFFH)。例如“MOVC A,@A+
DPTR”该指令功能是将A与DPTR的内容相加,把结果作为程序存储器的单元地址,
再将该单元的内容赋予A。如A=12H、DPTR=1A2BH,那么将A与DPTR相加后的值为A+DPTR=12H+1A2BH=1A3DH,而例如ROM的1A3DH存储单元存放的数据
为2FH,那么执行完上面的指令后A的结果为2FH。
6.位寻址方式
51单片机具有完善的位处理功能,因此具有相应的位寻址方式,用于内部可寻址位的寻址操作。在RAM中位于20H~2FH区间内的16个存储单元以及部分特殊功能寄存器可进行位寻址操作,寻址区间00H~D7H,详见RAM地址映像表。在位寻址指令中,如“MOV C,12H”表示将位地址为12H的内容赋予C累加位。
实际上,上面所讲的6种寻址方式的相应指令举例中,有许多是包含了两种寻址方式的,如指令“MOV12H,#34H”就包含了直接寻址与立即寻址两种方式,其功能是将34H这个立即数赋给地址为12H的存储单元,指令执行完后,12H地址单元中的内容为34H。
(二)汇编语言伪指令
汇编语言伪指令用于告诉编译程序汇编信息的指令,它不会被汇编成单片机可执行的机器代码,汇编结束后它们就消失了。下面仅对常用的几个伪指令进行介绍。
1.程序的定位结束伪指令
◆ ORG addr16
说明:将ORG伪指令后的指令内容存放于程序存储器addr16开始的单元中。例如:
ORG 1234H
MOV A,#56H…
表示将“MOV A,#56H”这条指令开始的一段代码存放在以1234H地址单元开始的程序存储器中,MOV指令的起始ROM地址刚好为1234H。
◆ END
说明:汇编程序结束指令,后面不跟操作数。表示汇编源程序的结束,编译程序以END作为程序源代码终止标志。通常将其放置于源程序最后,当编译程序执行到END指令时,随即结束汇编过程。
2.常量定义伪指令EQU指令格式为:
符号名 EQU 常量
说明:用于定义常量,经过EQU指定的常量,可在程序中直接用其符号名来代替。例如:
MIN EQU 12
使用MIN代替十进制数12。严格来说EQU不算是常量定义,因为在编译器执行时是不会给常量分配存储空间的,在编译时直接将符号名替换成数字量,例如:
TMP EQU 34H
MOV TMP,#TMP
上面第二条指令中,第一个TMP代表的是地址,第二个TMP代表的是数据,在编
译时编译器将TMP替换成34H,结果变成“MOV34H,#34H”,即将立即数34H赋给
RAM地址为34H的存储单元。
用法:当程序中有多条指令使用到同一个数字量时,便可使用EQU进行常量定义,在后续源码中使用其符号名代替,方便后期维护,因为只要在定义指令中对常量进行修改,就可以实现对所有涉及常量的指令进行修改。
3.数据池定义DB指令格式:
DB 表达式
说明:用于在ROM中定义一个连续的存储区间,区间长度根据DB指令的参数决定。表达式可以为数值(二进制、八进制、十进制或十六进制)、字符或字符串。多个表达式用英文逗号隔开。表达式为数值则每个表达式占用一个存储单元,超出第8位部分将被舍弃;如为字符则为该字符的ASCII码,同样占用一个存储单元;如为字符串则根据字符串的字符数依次分配存储单元,每个字符占一个字节。例如:
DB 123,456,‘0’,12H,“AB”
上面的指令中将在ROM中开辟出6个字节的存储单元。依次为123(7BH)、456(十
六进制为1CBH,将超出第8位的“1”舍弃,最终为0CBH)、30H、12H、65(41H)、66(42H)。
在DB指令前加标签可表示第一个存储单元的地址。(三)汇编语言数据传送指令
数据传送指令的功能是将源操作数的数据复制到目标操作数中,或者按要求交换指定操作数的内容。8051的数据传送指令共有28条,可分为5类。
1.数据复制指令
数据复制指令中具有两个操作数,第一操作数称为目标操作数,第二操作数称为源操作数,数据复制指令格式见表1-2。
表1-2
数据复制指令格式

目标操作数可以为RAM地址direct(直接寻址)、寄存器A、工作寄存器Rn、以间址寄存器Ri的内容为地址(@Ri)的RAM单元和数据指针DPTR;源操作数可以为RAM地址direct里的内容、寄存器ACC的值、工作寄存器Rn的内容、以间址寄存器Ri
的内容为地址(@Ri)的RAM单元内容、8位立即数(#data)和16(#data16)位立
即数。
关于下面指令说明中不带括号和带括号的区别,例如R0、(R0)、((R0))。R0代表
当前工作寄存器R0的RAM地址,假设RS1RS0=01B,运行时代表08H地址;(R0)表
示当前工作寄存器R0里所存的内容,是一个实际的8位二进制数;((R0))表示以R0单元的内容为地址的存储单元的内容,在运行期间也是一个8位数据。
◆ MOV A,direct
功能:将RAM地址为direct的单元内容复制到 ACC寄存器中,即(direct)→10
(ACC)
例如:MOV A,12H
执行前,(A)=8BH,存储器地址为12H的单元内容为34H,即(12H)=34H执行后,(A)=34H,(12H)=34H
◆ MOV A,Rn
功能:将工作寄存器Rn的内容复制到ACC中,即(Rn)→(ACC)例如:MOV A,R2
执行前,(A)=8BH,(R2)=34H执行后,(A)=34H,(R2)=34H◆ MOV A,#data
功能:将8位立即数data复制到ACC中,即data→(ACC)例如:MOV A,#34H
执行前,(A)=8BH执行后,(A)=34H
◆ MOV A,@Ri(i=0或1且只能取0或1)
功能:将以间接寻址工作寄存器Ri的内容为地址的存储单元内容复制到ACC中,即
((Ri))→(ACC)
例如:MOV A,@R0
执行前,(A)=8BH,(R0)=12H,(12H)=34H执行后,(A)=34H,(R0)=12H,(12H)=34H◆ MOVRn,direct
功能:将RAM地址为direct的单元内容复制到Rn中,即(direct)→(Rn)例如:MOVR5,12H
执行前,(R5)=8BH,(12)=34H执行后,(R5)=34H,(12)=34H◆ MOV Rn,A
功能:将ACC的内容复制到Rn中,即(A)→(Rn)例如:MOV R6,AH
执行前,(R6)=8BH,(A)=56H执行后,(R6)=56H,(A)=56H◆ MOV Rn,#data
功能:将8位立即数data复制到Rn中,即data→(Rn)例如:MOV R7,#3FH
执行前,(R7)=78H执行后,(R7)=3FH◆ MOV direct,A
功能:将ACC寄存器中的内容复制到RAM地址为direct的单元中,即(A)→
(direct)
例如:MOV 2FH,A
执行前,(2FH)=3DH,(A)=17H执行后,(2FH)=17H,(A)=17H◆ MOVdirect,#data
功能:将8位立即数data复制到RAM地址为direct的单元中,即data→(direct)例如:MOV2FH,#9AH
执行前,(2FH)=1EH执行后,(2FH)=9AH◆ MOV direct,Rn
功能:将工作寄存器Rn中的内容复制到RAM地址为direct的单元中,即(Rn)→
(direct)
例如:MOV 2CH,R4
执行前,(2CH)=4EH,(R4)=23H执行后,(2CH)=23H,(R4)=23H◆ MOVdirect,@Ri
功能:将以间接寻址寄存器Ri的内容为地址的RAM单元内容复制到RAM地址为
direct的单元中,即((Ri))→(direct)
例如:MOV 2AH,@R0
执行前,(2AH)=3BH,(R0)=20H,(20H)=78H执行后,(2AH)=78H,(R0)=20H,(20H)=78H◆ MOVdirect1,direct2
功能:将RAM地址为direct2的单元的内容复制到RAM地址为direct1的单元中,
即(direct2)→(direct1)
例如:MOV 12H,34H
执行前,(12H)=30H,(34H)=20H执行后,(12H)=20H,(34H)=20H◆ MOV@Ri,A
功能:将ACC的内容复制到以间接寻址寄存器Ri的内容为地址的RAM单元中,即
(A)→((Ri))
例如:MOV@R0,A
执行前,(R0)=7FH,(7FH)=2CH,(A)=FCH执行后,(R0)=7FH,(7FH)=FCH,(A)=FCH◆ MOV@Ri,direct
功能:将RAM地址为direct的单元内容复制到以间接寻址寄存器Ri的内容为地址
的RAM单元中,即(direct)→((Ri))
例如:MOV@R0,3CH
执行前,(R0)=7FH,(7FH)=2CH,(3CH)=FCH执行后,(R0)=7FH,(7FH)=FCH,(3CH)=FCH
◆ MOV@Ri,#data
功能:将立即数data复制到以间接寻址寄存器Ri的内容为地址的RAM单元中,即
data→((Ri))
例如:MOV@R0,#7AH
执行前,(R0)=3CH,(3CH)=FCH执行后,(R0)=3CH,(3CH)=7AH◆ MOV DPTR,#data16
功能:将16位立即数data16的内容复制到数据指针DPTR中,即data16→(DPTR)
例如:MOV DPTR,#3456H执行前,DPTR=2000H
执行后,DPTR=3456H
2.查表指令
功能:对存放在ROM中的数据表里的数据进行查找,以DPTR或PC为基址,A为变址寄存器,以基址与变址的和为地址,将该地址的内容取出来送到A寄存器中,查表指令格式见表1-3。查表指令只有两条。
表1-3
查表指令格式

基址寄存器为16的数据指针DPTR或者程序指针PC,变址寄存器只能为A寄存器,可寻址范围64KB。读取存放在ROM中的数据,只能用助记符MOVC。
◆ MOVC A,@A+DPTR
功能:将在ROM中地址为A+DPTR的存储单元的内容读取到A寄存器中,即
((A+DPTR))→(A)。
例如:MOVC A,@A+DPTR
执行前,(A)=12H,(DPTR)=1F23H,(1F23H)=B8H,(1F35H)=56H执行后,(A)=56H,(DPTR)=1F23H,(1F23H)=B8H,(1F35H)=56H◆ MOVCA,@A+PC
功能:将ROM地址为A+PC的存储单元的内容读取到A寄存器中,即((A+PC))
→(A)
例如:MOVC A,@A+DPTR
执行前,(A)=34H,(PC)=2C00H,(2C00H)=7AH,(2C34H)=36H执行后,(A)=36H,(PC)=2C00H,(2C00H)=7AH,(2C34H)=36H
3.堆栈指令
功能:对堆栈区进行数据的存入和读出操作,其操作数是包括特殊存储器在内的所有RAM地址单元。堆栈的入栈过程是先将堆栈指针SP加1,再将数据存入,因此实际栈底
单元为SP+1。
◆ PUSH direct
功能:先将SP加1,再将RAM地址为direct单元的内容复制到SP所指向的单元
中,即SP+1→SP,(direct)→((SP))
例如:PUSH A
执行前,(A)=2DH,(SP)=65H,(65H)=2AH,(66H)=71H执行后,(A)=2DH,(SP)=66H,(65H)=2AH,(66H)=2DH◆ POPdirect
功能:先将SP所指向的存储单元内容复制到RAM地址为direct的存储单元中,再
将SP减1,即((SP))→(direct),SP-1→SP
例如:POP A
指行前,(A)=2DH,(SP)=65H,(65H)=2AH,(64H)=71H执行后,(A)=2AH,(SP)=64H,(65H)=2AH,(64H)=71H
除了上面所讲的3类数据传送指令外,还有外部RAM访问指令、数据交换指令两类,由于使用频率较低,故不作详解。外部RAM访问指令助记符只能用MOVX,共有4
条。数据交换指令助记符有XCH、XHCD、SWAP 3个共5条。
4.外部数据存储器访问指令
◆ MOVX A,@DPTR
;((DPTR))→(A)
◆ MOVX@DPTR,A
;(A)→((DPTR))
◆ MOVX A,@Ri
;((Ri))→(A)
◆ MOVX@Ri,A
;(A)→((Ri))
5.数据交换指令
◆ XCH A,Rn
;(A)↔(Rn)
◆ XCHA,@Ri
;(A)↔((Rn))
◆ XCHA,direct
;(A)↔(direct)
◆ XCHDA,@Ri
;(A)30↔(Rn)30
功能:将A寄存器内容的低4位与((Ri))内容的低4位交换
◆ SWAPA
;(A)30↔(A)74
功能:将A寄存器内容的低4位与高4位交换(四)汇编语言位操作指令
位操作指令可分为传送指令、位运算指令和置位复位指令3类,其操作数为可位寻址存储区或特殊功能寄存器中的某个位。
1.位数据复制指令
位传送指令有两条,用于将源操作位的值复制到目标操作位中。
◆ MOV C,bit
功能:将可寻址位bit的值复制到位累加器C中,即(bit)→(C)
例如:MOVC,P1.2 14
执行前,(C)=0,(P1.2)=1执行后,(C)=1,(P1.2)=1◆ MOVbit,C
功能:将位累加器C中的值复制到可寻址位bit中,即(C)→(bit)
例如:MOV 6EH,CH
执行前,(6EH)=0,(C)=1执行后,(6EH)=1,(C)=1
位操作指令中没有两个可寻址位之间的复制指令,必须使用C作为中介来实现。例如要将37H位的值传送到73H位中:
MOVC,37H MOV73H,C
2.位运算指令
位运算是指与、或、非运算,共有6条指令。
◆ ANL C,bit
功能:将C与bit位的值进行与运算后存入C中,即(C)∧(bit)→(C)例如:ANLC,P1.0
执行前,(C)=1,(P1.0)=0执行后,(C)=0,(P1.0)=0◆ ANLC,/bit
功能:将C与bit位取反后的值进行与运算后存入C中,即(C)∧(/bit)→(C)例如:ANLC,P1.0
执行前,(C)=1,(P1.0)=0执行后,(C)=1,(P1.0)=0◆ ORLC,bit
功能:将C与bit位的值进行或运算后存于C中,即(C)∨(bit)→(C)例如:ORLC,P1.2
执行前,(C)=0,(P1.2)=1执行后,(C)=1,(P1.2)=1◆ ORLC,/bit
功能:将C与bit位取反后的值进行或运算后存入C中,即(C)∨(/bit)→(C)例如:ORLC,P1.3
执行前,(C)=0,(P1.3)=1执行后,(C)=0,(P1.3)=1◆ CPLC
功能:将C位的值取反后存回C中,即(/C)→(C)
◆ CPL bit
功能:将bit位取反后赋予存回bit位中,即(/bit)→(bit)例如:CPLP1.3
执行前,(P1.3)=1执行后,(P1.3)=0
3.置位复位指令
置位复位指令是将目标位置1或清零,共4条指令。
◆ SETB C
功能:无论之前位状态如何,将C位置1,即“1”→(C)
◆ SETB bit
功能:无论之前位状态如何,将bit位置1,即“1”→(bit)◆ CLRC
功能:无论之前位状态如何,将C位的状态清零,即“0”→(C)
◆ CLR bit
功能:无论之前位状态如何,将bit位的状态清零,即“0”→(bit)
前面学习了部分汇编语言指令,通过编写控制单片机引脚电平的程序来控制P0、P1、P2、P3 4个端口的输出,见表1-4,就可以控制LED灯的点亮和熄灭了。
表1-4
电平对应表

编写控制单片机引脚电平的基本方法如下。对某个引脚电平单独控制的指令:
输出高电平:SETB PX.X
例如:让P1.3输出为高电平的指令是:SETBP1.3输出低电平:CLRPX.X
例如:让P3.2输出为低电平的指令是:CLR P3.2
对某个端口输出集体控制的指令:
输出某个数:MOV PX,#XXH
例如:让P1输出5CH的指令是:MOVP1,#5CH
三、编程实现P1.0的LED灯点亮(一)单片机的开发环境
在51系列单片机的源代码开发工具中,目前使用最广泛的是Keil开发套件,同时支持汇编语言与C语言,包含了编译器、宏汇编、连接器、库管理和仿真调试器等在内的
完整开发方案。目前使用较为普遍的有μVision2、μVision3、μVision4 3个版本,本书采用Keil μVision3进行学习开发。
对于一个开发目标,Keil是以project(工程、项目)的概念来管理的,里面包括了项目的配置、源码、说明、连接的库等信息。因此,在使用Keil时先建立一个工程,首先打开Keil图标进入软件主界面。Keil软件界面如图1-7所示。

图1-7 Keil软件界面
主界面中包括菜单栏、工具栏、编辑窗口、工程窗口与信息栏。Keil是美国公司开发的,因此图形界面为英文。
(二)建立一个工程项目
(1)单击“Project”菜单,在弹出的下拉菜单中选中“New Project”选项。窗口如
图1-8所示。

图1-8 Keil新建项目

(2)在弹出的窗口中选择要保存的路径,输入工程文件的名字,例如保存到“F:\单片机学习”目录里,工程文件的名字为“LED”,然后单击保存,保存窗口如图19所示。
(3)这时会弹出一个对话框,要求选择单片机的型号。Keil几乎支持所有51内核的单片机,这里选择 Atmel公司的
图1-9 新建LED.uv2项目
AT89C51,选择单片机型号窗口如图110
所示,右栏是对该单片机的基本说明,然后单击确定。

图1-10 选择合适的单片机型号
(4)然后弹出一个对话框,问是否将8051的标准启动库添加到新建的工程里,这个库文件对目前使用的汇编工程暂不需要,这里选择“否”即可,窗口如图1-11所示。

图1-11 确认是否拷贝8051起始代码
(5)单击否之后,新建工程就完成了,但这只是一个空的工程,还需要添加必需的源代码或其他可选说明文件。单击“File”下拉菜单的“New”选项或直接单击工具栏的
“Create a new file”按钮创建文件,创建文件窗口如图1-12所示。

图1-12 新建文件
(6)文件创建之后,编辑栏会弹出一个Test1窗口,这里可编写指令代码,但是Text1文件还只是在内存中的自由文件,需要先保存到硬盘并添加到工程中。单击工具栏
的

按钮弹出保存路径,通常保存于工程目录下,文件后缀名必须为“.asm”,例如命名为“LED.asm”,单击保存,如图1 13所示。18

图1-13 保存新创建的文件
(7)单击工程窗口里的“+”展开“Target 1”,然后右击“Source Group 1”选择“Add Files to Group‘Source Group 1’”黑体字选项,如图1-14所示。

图1-14 添加新创建的文件
(8)在弹出的窗口中,文件类型选择“All files(*.*)”,然后选中刚保存的
LED.ASM文件,单击“Add”将其添加到工程中,如图1-15所示。
(9)单击Close关闭对话框,然后单击“Source Group 1”前的“+”展开“Source Group 1”,可以看到LED.ASM文件出现在工程窗口的“Source Group 1”的下面,界面
如图1-16所示,接下来就是程序的编写和编译了。
(三)编写程序源代码
在编辑栏的LED文件窗口中输入以下内容:


图1-15 添加新建的文件LED.ASM

图1-16 编程界面
该程序功能是先使P1端口输出低电平,然后P1.0输出高电平。(四)编译
在编译前要对工程进行配置,单击菜单栏的“Project”选择“Option for Target
‘Target1’”选项或直接单击工具栏的按钮,在弹出的对话框中选择Output选项卡,

勾选“Create HEX file.”复选框,然后单击确定,如图1-17所示。
选中该复选框使编译器编译源程序后能生成用于下载到单片机ROM的十六进制
.hex文件。在菜单栏中选择“Project”选项中的“Build all target file”或直接单击工具
栏的按钮编译程序,在信息栏可以看到编译过程和信息,如图1-18所示。

如果程序没有问题编译后信息栏会显示“0Error(s),0 Warning(s).”的字样,另外20

图1-17 设置输出HEX文件

图1-18 输出LED.hex文件
还可以看到程序使用的存储资源,例如图1 18中第4行信息“ProgramSize:data=8.0 xdata=0code=5”表示该程序使用了8字节RAM,0字节外部RAM和5字节ROM。
将上面所产生的HEX文件通过LWZAUSB软件下载到单片机内,就能达到预期效果。例子中所讲的程序非常简洁,但一般不会这样写,因为ROM的前几十个字节中还有其他特殊的用途,所以不能直接将HEX文件存入ROM的前几十个字节中。
实际编程如下,程序前面有一些内容格式一样,可以暂时照写。

能力检测
(1)理解单片机最小系统和单片机外围电路的概念。
(2)了解Keil 的基本用法和单片机编程的基本流程,能够独立完成编程下载等基本操作。