单片机的40个引脚大致可分为4类:电源、时钟、控制和I/O引脚。
⒈ 电源:
⑴ VCC - 芯片电源,接+5V;
⑵ VSS - 接地端;
⒉ 时钟:XTAL1、XTAL2 - 晶体振荡电路反相输入端和输出端。
⒊ 控制线:控制线共有4根,
⑴ ALE/PROG:地址锁存允许/片内EPROM编程脉冲
① ALE功能:用来锁存P0口送出的低8位地址
② PROG功能:片内有EPROM的芯片,在EPROM编程期间,此引脚输入编程脉冲。
⑵ PSEN:外ROM读选通信号。
⑶ RST/VPD:复位/备用电源。
① RST(Reset)功能:复位信号输入端。
② VPD功能:在Vcc掉电情况下,接备用电源。
⑷ EA/Vpp:内外ROM选择/片内EPROM编程电源。
① EA功能:内外ROM选择端。
② Vpp功能:片内有EPROM的芯片,在EPROM编程期间,施加编程电源Vpp。
⒋ I/O线
80C51共有4个8位并行I/O端口:P0、P1、P2、P3口,共32个引脚。P3口还具有第二功能,用于特殊信号输入输出和控制信号(属控制总线)。
拿到一块芯片,想要使用它,首先必须要知道怎样连线,我们用的一块称之为89C51的芯片,下面我们就看一下如何给它连线。
1、 电源:这当然是必不可少的了。单片机使用的是5V电源,其中正极接40管脚,负极(地)接20管脚。
2、 振蒎电路:单片机是一种时序电路,必须供给脉冲信号才能正常工作,在单片机内部已集成了振荡器,使用晶体振荡器,接18、19脚。只要买来晶体震荡器,电容,连上就能了,按图1接上即可。
3、 复位管脚:按图1中画法连好,至于复位是何含义及为何需要复要复位,在单片机功能中介绍。
4、 EA管脚:EA管脚接到正电源端。 至此,一个单片机就接好,通上电,单片机就开始工作了。
PROM,称之为可编程存储器。这就象我们的练习本,买来的时候是空白的,能写东西上去,可一旦写上去,就擦不掉了,所以它只能用写一次,要是写错了,就报销了。(现在已经被淘汰)
EPROM,称之为紫外线擦除的可编程只读存储器。它里面的内容写上去之后,如果觉得不满意,能用一种特殊的办法去掉后重写,这就是用紫外线照射,紫外线就象“消字灵”,能把字去掉,然后再重写。当然消的次数多了,也就不灵光了,所以这种芯片能擦除的次数也是有限的——几百次吧。(现在已经被淘汰)
EEPROM,也叫 E2PROM称之为电可擦可编程只读存储器,它和EEPROM类似,写上去的东西也能擦掉重写,但它要方便一些,不需要光照了,只要用电就能擦除或者重新改写数据,所以就方便许多,而且寿命也很长(几万到几十万次不等)。
FLASH,称之为闪速存储器,属于EEPROM的改进产品,它的最大特点是必须按块(Block)擦除(每个区块的大小不定,不同厂家的产品有不同的规格), 而EEPROM则可以一次只擦除一个字节(Byte)。FLASH现在常用于大容量存储,比如u盘
;主程序:
LOOP: SETB P1.0 ;(1)熄灭灯
LCALL DELAY ;(2)延时一段时间
CLR P1.0 ;(3)点亮灯
LCALL DELAY ;(4)延时一段时间
AJMP LOOP ;(5)跳转到第一句LOOP处
;以下子程序
DELAY: MOV R7,#250 ;(6)
D1: MOV R6,#250 ;(7)
D2: DJNZ R6,D2 ;(8)
DJNZ R7,D1 ;(9)
RET ;(10)
END ;(11)
MOV:这是一条指令,意思是传递数据。说到传递,我们都很清楚,传东西要从一本人的手上传到另一本人的手上,也就是说要有一个接受者,一个传递者和一样东西。从指令MOV R7,#250中来分析,R7是一个接受者,250是被传递的数,传递者在这条指令中被省略了(注意:并不是每一条传递指令都会省的,事实上大部份数据传递指令都会有传递者)。它的意义也很明显:将数据250送到R7中去,因此执行完这条指令后,R7单元中的值就应当是250。在250前面有个#号,这又是什么意思呢?这个#就是用来说明250就是一个被传递的东西本身,而不是传递者。那么MOV R6,#250是什么意思,应当不用分析了吧。
DJNZ:这是另一条指令,我们来看一下这条指令后面跟着的两个东西,一个是R6,一个是D2,R6我们当然已知是什么了,查一下D2是什么。D2在本行的前面,我们已学过,这称之为标号。标号的用途是什么呢?就是给本行起一个名字。DJNZ指令的执行过程是这样的,它将其后面的第一个参数中的值减1,然后看一下,这个值是否等于0,如果等于0,就往下执行,如果不等于0,就转移,转到什么地方去呢?可能大家已猜到了,转到第二个参数所指定的地方去(请大家用自已的话讲一下这条语句是怎样执行的)。本条指令的最终执行结果就是,在原地转圈250次。
执行完了DJNZ R6,D2之后(也就是R6的值等于0之后),就会去执行下面一行,也就是DJNZ R7,D1,请大家自行分析一下这句话执行的结果。(转去执行MOV R6,#250,同时R7中的值减1),最终DJNZ R6,D2这句话将被执行250*250=62500次,执行这么多次同一条指令干吗?就是为了延时。
一个机器周期包括12个时钟周期。下面让我们算一下一个机器周期是多长时间吧。设一个单片机工作于12M晶体震荡器,它的时钟周期是1/12(微秒)。它的一个机器周期是12*(1/12)也就是1微秒。(请计算一个工作于6M晶体震荡器的单片机,它的机器周期是多少)。
首先必须要知道晶体震荡器的频率,我们设所用晶体震荡器为12M,则一个机器周期就是1微秒。而DJNZ指令是双周期指令,所以执行一次要2个微秒。一共执行62500次,正好125000微秒,也就是125毫秒。
相对应
#include <at89x52.h>
void DELAY() //延时函数
{ unsigned char i,j;
for(i=0;i<250;i++)
{
for(j=0;j<200;j++);
}
}
void main() //程序从这里开始执行
{
while(1) //这句的作用就是反复的执行下面这个{}中包含的4句
{
P1_0=1; //(1)熄灭灯
DELAY(); //(2)延时一段时间
P1_0=0; //(3)点亮灯
DELAY(); //(4)延时一段时间
}
}
这种复位电路的工作原理是:通电时,电容两端相当于是短路,于是RST管脚上为高电平,然后电源通过电阻对电容充电,RST端电压慢慢下降,降到一定程序,即为低电平,单片机开始正常工作。
MAIN: MOV P1,#0FFH
LCALL DELAY
MOV P1,#00H
LCALL DELAY
LJMP MAIN
DELAY:MOV R7,#250
D1: MOV R6,#250
D2: DJNZ R6,D2
DJNZ R7,D1
RET
END
程序分析:这段程序和前面做过的程序比较,只有两处不一样:
第一句:原来是SETB P1.0,现在改为MOV P1,#0FFH,
第三句:原来是CLR P1.0,现在改为MOV P1,#00H。
从中能看出,P1是P1.0->P1.7的全体的代表,一个P1就表示了所有的这八个管脚了。
当然用的指令也不一样了,是用MOV指令。为什么用这条指令?
看图2,我们把P1作为一个整体,就把它当作是一个存储器的单元,对一个单元送进一个数能用MOV指令。
先看P1口的一位的结构示意图(只画出了输出部份):从图中能看出,开关的打开和合上代表了管脚输出的高和低,如果开关合上了,则管脚输出就是低,如果开关打开了,则输出高电平,这个开关是由一根线来控制的,这根数据总线是出自于CPU,让我们回想一下,数据总线是一根大家公用的线,很多的器件和它连在一起,在不一样的时候,不一样的器件当然需要不一样的信号,如某一时刻我们让这个管脚输出高电平,并要求保持若干时间,在这段时间里,计算机当然在忙个不停,在与其它器件进行联络,这根控制线上的电平未必能保持原来的值不变,输出就会发生变化了。怎么解决这个问题呢?我们在存储器一节中学过,存储器中是能存放电荷的,我们不妨也加一个小的存储器的单元,并在它的前面加一个开关,要让这一位输出时,就把开关打开,信号就进入存储器的单元,然后马上关闭开关,这样这一位的状态就被保存下来,直到下一次命令让它把开关再打开为止。这样就能使这一位的状态与别的器件无关了,这么一个小单元,我们给它一个很形象的名字,称之为“锁存器”。
这是并行口的一位的输出结构示意图,再看,除了输出之外,还有两根线,一根从外部管脚接入,另一根从锁存器的输出接出,分别标明读管脚和读锁存器。这两根线是用于从外部接收信号的,为什么要两根呢?原来,在51单片机中输入有两种方式,分别称为‘读管脚’和‘读锁存器’,第一种方式是将管脚作为输入,那是真正地从外部管脚读进输入的值,第二种方式是该管脚处于输出状态时,有时需要改变这一位的状态,则并不需要真正地读管脚状态,而只是读入锁存器的状态,然后作某种变换后再输出。
请注意输入结构图,如果将这一根引线作为输入口使用,我们并不能保证在任何时刻都能得到正确的结果(为什么?)参考图2输入示意图。接在外部的开关如果打开,则应当是输入1,而如果闭合开关,则输入0,但是,如果单片机内部的开关是闭合的,那么不管外部的开关是开还是闭,单片机接受到的数据都是0。可见,要让这一端口作为输入使用,要先做一个‘准备工作’,就是先让内部的开关断开,也就是让端口输出‘1’才行。正因为要先做这么一个准备工作,所以我们称之为“准双向I/O口”。
在单片机中有一些独立的存储单元是用来控制这些器件的,被称之为特殊功能寄存器(SFR)。事实上,我们已接触过P1这个特殊功能寄存器了,还有哪些呢?看下表1
符号 | 地址 | 功能介绍 |
B | F0H | B寄存器 |
ACC | E0H | 累加器 |
PSW | D0H | 程序状态字 |
IP | B8H | 中断优先级控制寄存器 |
P3 | B0H | P3口锁存器 |
IE | A8H | 中断允许控制寄存器 |
P2 | A0H | P2口锁存器 |
SBUF | 99H | 串行口锁存器 |
SCON | 98H | 串行口控制寄存器 |
P1 | 90H | P1口锁存器 |
TH1 | 8DH | 定时器/计数器1(高8位) |
TL1 | 8CH | 定时器/计数器1(低8位) |
TH0 | 8BH | 定时器/计数器0(高8位) |
TL0 | 8AH | 定时器/计数器0(低8位) |
TMOD | 89A | 定时器/计数器方式控制寄存器 |
TCON | 88H | 定时器/计数器控制寄存器 |
DPH | 83H | 数据地址指针(高8位) |
DPL | 82H | 数据地址指针(低8位) |
SP | 81H | 堆栈指针 |
P0 | 80H | P0口锁存器 |
PCON | 87H | 电源控制寄存器 |
1、ACC:累加器,常常用A表示。这是个什么东西,可不能从名字上理解,它是一个寄存器,而不是一个做加法的东西,为什么给它这么一个名字呢?或许是因为在运算器做运算时其中一个数一定是在ACC中的缘故吧。它的名字特殊,身份也特殊,稍后我们将学到指令,能发现,所有的运算类指令都离不开它。
2、B:一个寄存器。在做乘、除法时放乘数或除数,不做乘除法时,随你怎么用。
3、PSW:程序状态字。这是一个很重要的东西,里面放了CPU工作时的很多状态,借此,我们能了解CPU的当前状态,并作出对应的处理。它的各位功能请看表2
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
CY | AC | F0 | RS1 | RS0 | OV | P | |
表2
PSW也称为标志寄存器,了解这个对于了解单片机原理非常的重要,存放各有关标志。其结构和定义如下:
下面我们逐一介绍sfr各位的用途
(1)CY:进位标志。用于表示Acc.7有否向更高位进位。8051中的运算器是一种8位的运算器,我们知道,8位运算器只能表示到0-255,如果做加法的话,两数相加可能会超过255,这样最高位就会丢失,造成运算的错误,怎么办?最高位就进到这里来。这样就没事了。
例:78H+97H(01111000+10010111)
(2)AC:辅助进位标志也叫半进位标志。 用于表示Acc.3有否向Acc.4进位
例:57H+3AH(01010111+00111010)
(3)F0:用户标志位,由我们(编程人员)决定什么时候用,什么时候不用。
(4)RS1、RS0:工作寄存器组选择位。这个我们已知了。
RS1、RS0 = 00 —— 0区(00H~07H)
RS1、RS0 = 01 —— 1区(08H~0FH)
RS1、RS0 = 10 —— 2区(10H~17H)
RS1、RS0 = 11 —— 3区(18H~1FH)
(5)0V:溢出标志位。 表示Acc在有符号数算术运算中的溢出,什么是溢出我们稍后再谈吧。
(6)P:奇偶校验位:它用来表示ALU运算结果中二进制数位“1”的个数的奇偶性。若为奇数,则P=1,不然为0。
例:某运算结果是78H(01111000),显然1的个数为偶数,所以P=0。
4、DPTR(DPH、DPL):数据指针,能用它来访问外部数据存储器中的任一单元,如果不用,也能作为通用寄存器来用,由我们自已决定如何使用。16位,由两个8位寄存器DPH、DPL组成。主要用于存放一个16位地址,作为访问外部存储器(外RAM和ROM)的地址指针。
5、P0、P1、P2、P3:这个我们已经知道,是四个并行输入/输出口的寄存器。它里面的内容对应着管脚的输出。
6、SP:堆栈指针。(专用于指出堆栈顶部数据的地址。)
堆栈介绍:日常生活中,我们都注意到过这样的现象,家里洗的碗,一只一只摞起来,最晚放上去的放在最上面,而最早放上去的则放在最下面,在取的时候正好相反,先从最上面取,这种现象我们用一句话来概括:“先进后出,后进先出”。请大家想想,还有什么地方有这种现象?其实比比皆是,建筑工地上堆放的砖头、材料,仓库里放的货物,都是“先进后出,后进先出”,这实际是一种存取物品的规则,我们称之为“堆栈”。
在单片机中,我们也能在RAM中构造这样一个区域,用来存放数据,这个区域存放数据的规则就是“先进后出,后进先出”,我们称之为“堆栈”。为什么需要这样来存放数据呢?存储器本身不是能按地址来存放数据吗?对,知道了地址的确就能知道里面的内容,但如果我们需要存放的是一批数据,每一个数据都需要知道地址那不是麻烦吗?如果我们让数据一个接一个地放置,那么我们只要知道第一个数据所在地址单元就能了(看图2)如果第一个数据在27H,那么第二、三个就在28H、29H了。所以利用堆栈这种办法来放数据能简化操作
那么51中堆栈什么地方呢?单片机中能存放数据的区域有限,我们不能够专门分配一块地方做堆栈,所以就在内存(RAM)中开辟一块地方,用于堆栈,但是用内存的哪一块呢?还是不好定,因为51是一种通用的单片机,各人的实际需求各不相同,有人需要多一些堆栈,而有人则不需要那么多,所以怎么分配都不合适,怎样来解决这个问题?分不好干脆就不分了,把分的权利给用户(编程者),根据自已的需要去定吧,所以51单片机中堆栈的位置是能变化的。而这种变化就体现在SP中值的变化,看图2,SP中的值等于27H不就相当于是一个指针指向27H单元吗?当然在真正的51机中,开始指针所指的位置并非就是数据存放的位置,而是数据存放的前一个位置,比如一开始指针是指向27H单元的,那么第一个数据的位置是28H单元,而不是27H单元,为什么会这样,我们在学堆栈命令时再说明。其它的SFR,我们在用到时再介绍。
MOV R7,#20
MOV R0,#30H
LOOP:MOV A,@R0
INC R0
DJNZ R7,LOOP
这个例程中大部份指令我们是能看懂的,第一句,是将立即数20送到R7中,执行完后R7中的值应当是20。第二句是将立即数30H送入R0工作寄存器中,所以执行完后,R0单元中的值是30H,第三句,这是看一下R0单元中是什么值,把这个值作为地址,取这个地址单元的内容送入A中,此时,执行这条指令的结果就相当于MOV A,30H。第四句,没学过,就是把R0中的值加1,因此执行完后,R0中的值就是31H,第五句,学过,将R7中的值减1,看是否等于0,不等于0,则转到标号LOOP处继续执行,因此,执行完这句后,将转去执行MOV A,@R0这句话,此时相当于执行了MOV A,31H(因为此时的R0中的值已是31H了),如此,直到R7中的值逐次相减等于0,也就是循环20次为止,就实现了我们的要求:从30H单元开始将20个数据送入A中。
音乐程序汇编代码代码1 -------------Voice.asm--------------------------
ORG 0000H
LJMP START
ORG 000BH
INC 20H ;中断服务,中断计数器加1
MOV TH0,#0D8H
MOV TL0,#0EFH ;12M晶振,形成10毫秒中断
RETI
START:
MOV SP,#50H
MOV TH0,#0D8H
MOV TL0,#0EFH
MOV TMOD,#01H
MOV IE,#82H
MUSIC0:
NOP
MOV DPTR,#DAT ;表头地址送DPTR
MOV 20H,#00H ;中断计数器清0
MOV B,#00H ;表序号清0
MUSIC1:
NOP
CLR A
MOVC A,@A+DPTR ;查表取代码
JZ END0 ;是00H,则结束
CJNE A,#0FFH,MUSIC5
LJMP MUSIC3
MUSIC5:
NOP
MOV R6,A
INC DPTR
MOV A,B
MOVC A,@A+DPTR ;取节拍代码送R7
MOV R7,A
SETB TR0 ;启动计数
MUSIC2:
NOP
CPL P1.0
MOV A,R6
MOV R3,A
LCALL DEL
MOV A,R7
CJNE A,20H,MUSIC2 ;中断计数器(20H)=R7否?
;不等,则继续循环
MOV 20H,#00H ;等于,则取下一代码
INC DPTR
; INC B
LJMP MUSIC1
MUSIC3:
NOP
CLR TR0 ;休止100毫秒
MOV R2,#0DH
MUSIC4:
NOP
MOV R3,#0FFH
LCALL DEL
DJNZ R2,MUSIC4
INC DPTR
LJMP MUSIC1
END0:
NOP
MOV R2,#64H ;歌曲结束,延时1秒后继续
MUSIC6:
MOV R3,#00H
LCALL DEL
DJNZ R2,MUSIC6
LJMP MUSIC0
DEL:
NOP
DEL3:
MOV R4,#02H
DEL4:
NOP
DJNZ R4,DEL4
NOP
DJNZ R3,DEL3
RET
NOP
DAT:
db 26h,20h,20h,20h,20h,20h,26h,10h,20h,10h,20h,80h,26h,20h,30h,20h
db 30h,20h,39h,10h,30h,10h,30h,80h,26h,20h,20h,20h,20h,20h,1ch,20h
db 20h,80h,2bh,20h,26h,20h,20h,20h,2bh,10h,26h,10h,2bh,80h,26h,20h
db 30h,20h,30h,20h,39h,10h,26h,10h,26h,60h,40h,10h,39h,10h,26h,20h
db 30h,20h,30h,20h,39h,10h,26h,10h,26h,80h,26h,20h,2bh,10h,2bh,10h
db 2bh,20h,30h,10h,39h,10h,26h,10h,2bh,10h,2bh,20h,2bh,40h,40h,20h
db 20h,10h,20h,10h,2bh,10h,26h,30h,30h,80h,18h,20h,18h,20h,26h,20h
db 20h,20h,20h,40h,26h,20h,2bh,20h,30h,20h,30h,20h,1ch,20h,20h,20h
db 20h,80h,1ch,20h,1ch,20h,1ch,20h,30h,20h,30h,60h,39h,10h,30h,10h
db 20h,20h,2bh,10h,26h,10h,2bh,10h,26h,10h,26h,10h,2bh,10h,2bh,80h
db 18h,20h,18h,20h,26h,20h,20h,20h,20h,60h,26h,10h,2bh,20h,30h,20h
db 30h,20h,1ch,20h,20h,20h,20h,80h,26h,20h,30h,10h,30h,10h,30h,20h
db 39h,20h,26h,10h,2bh,10h,2bh,20h,2bh,40h,40h,10h,40h,10h,20h,10h
db 20h,10h,2bh,10h,26h,30h,30h,80h,00H
END
助记符 | 指令说明 | 字节数 | 周期数 | |
(数据传递类指令) | ||||
MOV A,Rn | 寄存器传送到累加器 | 1 | 1 | |
MOV A,direct | 直接地址传送到累加器 | 2 | 1 | |
MOV A,@Ri | 累加器传送到外部RAM(8 地址) | 1 | 1 | |
MOV A,#data | 立即数传送到累加器 | 2 | 1 | |
MOV Rn,A | 累加器传送到寄存器 | 1 | 1 | |
MOV Rn,direct | 直接地址传送到寄存器 | 2 | 2 | |
MOV Rn,#data | 累加器传送到直接地址 | 2 | 1 | |
MOV direct,Rn | 寄存器传送到直接地址 | 2 | 1 | |
MOV direct,direct | 直接地址传送到直接地址 | 3 | 2 | |
MOV direct,A | 累加器传送到直接地址 | 2 | 1 | |
MOV direct,@Ri | 间接RAM 传送到直接地址 | 2 | 2 | |
MOV direct,#data | 立即数传送到直接地址 | 3 | 2 | |
MOV @Ri,A | 直接地址传送到直接地址 | 1 | 2 | |
MOV @Ri,direct | 直接地址传送到间接RAM | 2 | 1 | |
MOV @Ri,#data | 立即数传送到间接RAM | 2 | 2 | |
MOV DPTR,#data16 | 16 位常数加载到数据指针 | 3 | 1 | |
MOVC A,@A+DPTR | 代码字节传送到累加器 | 1 | 2 | |
MOVC A,@A+PC | 代码字节传送到累加器 | 1 | 2 | |
MOVX A,@Ri | 外部RAM(8 地址)传送到累加器 | 1 | 2 | |
MOVX A,@DPTR | 外部RAM(16 地址)传送到累加器 | 1 | 2 | |
MOVX @Ri,A | 累加器传送到外部RAM(8 地址) | 1 | 2 | |
MOVX @DPTR,A | 累加器传送到外部RAM(16 地址) | 1 | 2 | |
PUSH direct | 直接地址压入堆栈 | 2 | 2 | |
POP direct | 直接地址弹出堆栈 | 2 | 2 | |
XCH A,Rn | 寄存器和累加器交换 | 1 | 1 | |
XCH A, direct | 直接地址和累加器交换 | 2 | 1 | |
XCH A, @Ri | 间接RAM 和累加器交换 | 1 | 1 | |
XCHD A, @Ri | 间接RAM 和累加器交换低4 位字节 | 1 | 1 | |
(算术运算类指令) | ||||
INC A | 累加器加1 | 1 | 1 | |
INC Rn | 寄存器加1 | 1 | 1 | |
INC direct | 直接地址加1 | 2 | 1 | |
INC @Ri | 间接RAM 加1 | 1 | 1 | |
INC DPTR | 数据指针加1 | 1 | 2 | |
DEC A | 累加器减1 | 1 | 1 | |
DEC Rn | 寄存器减1 | 1 | 1 | |
DEC direct | 直接地址减1 | 2 | 2 | |
DEC @Ri | 间接RAM 减1 | 1 | 1 | |
MUL AB | 累加器和B 寄存器相乘 | 1 | 4 | |
DIV AB | 累加器除以B 寄存器 | 1 | 4 | |
DA A | 累加器十进制调整 | 1 | 1 | |
ADD | A,Rn | 寄存器与累加器求和 | 1 | 1 |
ADD A,direct | 直接地址与累加器求和 | 2 | 1 | |
ADD A,@Ri | 间接RAM 与累加器求和 | 1 | 1 | |
ADD A,#data | 立即数与累加器求和 | 2 | 1 | |
ADDC A,Rn | 寄存器与累加器求和(带进位) | 1 | 1 | |
ADDC A,direct | 直接地址与累加器求和(带进位) | 2 | 1 | |
ADDC A,@Ri | 间接RAM 与累加器求和(带进位) | 1 | 1 | |
ADDC A,#data | 立即数与累加器求和(带进位) | 2 | 1 | |
SUBB A,Rn | 累加器减去寄存器(带借位) | 1 | 1 | |
SUBB A,direct | 累加器减去直接地址(带借位) | 2 | 1 | |
SUBB A,@Ri | 累加器减去间接RAM(带借位) | 1 | 1 | |
SUBB A,#data | 累加器减去立即数(带借位) | 2 | 1 | |
(逻辑运算类指令) | ||||
ANL A,Rn | 寄存器“与”到累加器 | 1 | 1 | |
ANL A,direct | 直接地址“与”到累加器 | 2 | 1 | |
ANL A,@Ri | 间接RAM“与”到累加器\1 | 1 | ||
ANL A,#data | 立即数“与”到累加器 | 2 | 1 | |
ANL direct,A | 累加器“与”到直接地址 | 2 | 1 | |
ANL direct, #data | 立即数“与”到直接地址 | 3 | 2 | |
ORL A,Rn | 寄存器“或”到累加器 | 1 | 2 | |
ORL A,direct | 直接地址“或”到累加器 | 2 | 1 | |
ORL A,@Ri | 间接RAM“或”到累加器 | 1 | 1 | |
ORL A,#data | 立即数“或”到累加器 | 2 | 1 | |
ORL direct,A | 累加器“或”到直接地址 | 2 | 1 | |
ORL direct, #data | 立即数“或”到直接地址 | 3 | 1 | |
XRL A,Rn | 寄存器“异或”到累加器 | 1 | 2 | |
XRL A,direct | 直接地址“异或”到累加器 | 2 | 1 | |
XRL A,@Ri | 间接RAM“异或”到累加器 | 1 | 1 | |
XRL A,#data | 立即数“异或”到累加器 | 2 | 1 | |
XRL direct,A | 累加器“异或”到直接地址 | 2 | 1 | |
XRL direct, #data | 立即数“异或”到直接地址 | 3 | 1 | |
CLR A | 累加器清零 | 1 | 2 | |
CPL A | 累加器求反 | 1 | 1 | |
RL A | 累加器循环左移 | 1 | 1 | |
RLC A | 带进位累加器循环左移 | 1 | 1 | |
RR A | 累加器循环右移 | 1 | 1 | |
RRC A | 带进位累加器循环右移 | 1 | 1 | |
SWAP A | 累加器高、低4 位交换 | 1 | 1 | |
(控制转移类指令) | ||||
JMP @A+DPTR | 相对DPTR 的无条件间接转移 | 1 | 2 | |
JZ rel | 累加器为0 则转移 | 2 | 2 | |
JNZ rel | 累加器为1 则转移 | 2 | 2 | |
CJNE A,direct,rel | 比较直接地址和累加器,不相等转移 | 3 | 2 | |
CJNE A,#data,rel | 比较立即数和累加器,不相等转移 | 3 | 2 | |
CJNE Rn,#data,rel | 比较寄存器和立即数,不相等转移 | 2 | 2 | |
CJNE @Ri,#data,rel | 比较立即数和间接RAM,不相等转移 | 3 | 2 | |
DJNZ Rn,rel | 寄存器减1,不为0 则转移 | 3 | 2 | |
DJNZ direct,rel | 直接地址减1,不为0 则转移 | 3 | 2 | |
NOP | 空操作,用于短暂延时 | 1 | 1 | |
ACALL add11 | 绝对调用子程序 | 2 | 2 | |
LCALL add16 | 长调用子程序 | 3 | 2 | |
RET | 从子程序返回 | 1 | 2 | |
RETI | 从中断服务子程序返回 | 1 | 2 | |
AJMP add11 | 无条件绝对转移 | 2 | 2 | |
LJMP add16 | 无条件长转移 | 3 | 2 | |
SJMP rel | 无条件相对转移 | 2 | 2 | |
(布尔指令) | ||||
CLR C | 清进位位 | 1 | 1 | |
CLR bit | 清直接寻址位 | 2 | 1 | |
SETB C | 置位进位位 | 1 | 1 | |
SETB bit | 置位直接寻址位 | 2 | 1 | |
CPL C | 取反进位位 | 1 | 1 | |
CPL bit | 取反直接寻址位 | 2 | 1 | |
ANL C,bit | 直接寻址位“与”到进位位 | 2 | 2 | |
ANL C,/bit | 直接寻址位的反码“与”到进位位 | 2 | 2 | |
ORL C,bit | 直接寻址位“或”到进位位 | 2 | 2 | |
ORL C,/bit | 直接寻址位的反码“或”到进位位 | 2 | 2 | |
MOV C,bit | 直接寻址位传送到进位位 | 2 | 1 | |
MOV bit, C | 进位位位传送到直接寻址 | 2 | 2 | |
JC rel | 如果进位位为1 则转移 | 2 | 2 | |
JNC rel | 如果进位位为0 则转移 | 2 | 2 | |
JB bit,rel | 如果直接寻址位为1 则转移 | 3 | 2 | |
JNB bit,rel | 如果直接寻址位为0 则转移 | 3 | 2 | |
JBC bit,rel | 直接寻址位为1 则转移并清除该位 | 2 | 2 | |
(伪指令) | ||||
ORG | 指明程序的开始位置 | |||
DB | 定义数据表 | |||
DW | 定义16 位的地址表 | |||
EQU | 给一个表达式或一个字符串起名 | |||
DATA | 给一个8 位的内部RAM 起名 | |||
XDATA | 给一个8 位的外部RAM 起名 | |||
BIT | 给一个可位寻址的位单元起名 | |||
END | 指出源程序到此为止 | |||
(指令中的符号标识) | ||||
Rn | 工作寄存器R0-R7 | |||
Ri | 工作寄存器R0 和R1 | |||
@Ri | 间接寻址的8 位RAM 单元地址(00H-FFH) | |||
#data8 | 8 位常数 | |||
#data16 | 16 位常数 | |||
addr16 | 16 位目标地址,能转移或调用到64KROM 的任何地方 | |||
addr11 | 11 位目标地址,在下条指令的2K 范围内转移或调用 | |||
Rel | 8 位偏移量,用于SJMP 和所有条件转移指令,范围-128~+127 | |||
Bit | 片内RAM 中的可寻址位和SFR 的可寻址位 | |||
Direct | 直接地址,范围片内RAM 单元(00H-7FH)和80H-FFH | |||
$ | 指本条指令的起始位置 |