资讯详情

51单片机回顾【基本汇编语言】

数据传输指令html

以累加器为目的的编程指令

MOV A,Rnspa

MOV A,direct设计

MOV A,@Ri指针

MOV A,#datahtm

第一条指令中,Rn表明的是R0-R7.在第二条指令中,direct它指的是直接地址,我们刚才在第三第三个指令。第四条指令是立即计算data送到A中

让我们通过一些例子来解释:blog

MOV A,R1 ;工作寄存器R1中的值送入A,R1中值保持不变。

MOV A,30H ;将内存30H单元中的值送入A,30H单元中的值保持不变。ci

MOV A,@R1 ;先看R1中的值是什么?以此值为地址,并将该地址单元中的值发送到A中。如执行命令前R1中的值为20H,则是将20H单元中的值送 入A中。

MOV A,#34H ;将当即数34H执行本条指令后,送入A,A中的值是34H。

以寄存器Rn为目的操作指令

MOV Rn,A

MOV Rn,direct

MOV Rn,#data

这组指令功能是将源地址单元中的内容送入工作寄存器,源操作数不变。

以直接地址为目的操作指令数

MOV direct,A 例: MOV 20H,A

MOV direct,Rn MOV 20H,R1

MOV direct1,direct2 MOV 20H,30H

MOV direct,@Ri MOV 20H,@R1

MOV direct,#data MOV 20H,#34H

以间接地址为目的操作指令数

MOV @Ri,A 例:MOV @R0,A

MOV @Ri,direct MOV @R1,20H

MOV @Ri,#data MOV @R0,#34H

传递十六位数的指令

MOV DPTR,#data16

8051是一种8位机,是唯一一个16位立即数传输指令,其功能是将16位立即数传输到DPTR中去。高8位送入DPH(083H),低8位送入DPL(082H)。例:MOV DPTR,#1234H,执行完成后DPH中的值为12H,DPL中的值为34H。相反,如果我们分别朝向DPH,DPL送数,结果也一样。若有以下两个指令:MOV DPH,#35H,MOV DPL,#12H。至于执行MOV DPTR,#3512H。

累加器A和片外RAM数据传递指令之间的数据传递

MOVX A,@Ri

MOVX @Ri,A

MOVX #9; A,@DPTR

MOVX @DPTR,A

说明:

1)与外部存储器在51中RAM只能是A累加器处理。一切都必须送到外面RAM数据必须通过发送,所有外部数据必须读取RAM数据也必须通过A读入。在这里,我们可以看到内外内外内部RAM区别,内部RAM数据可以直接传数据,而外部不能。例如,它需要外部RAM一个单元(0100H单元数据)送到另一个单元(0200H单元)也必须先将01000H读入单元内容A,而后再送到0200H单元中去。

2)读或写外部RAM,当然须知道RAM在后两个指令中,地址直接放置在DPTR中的。前两个指令,因为Ri(即R0或R1)只是一个8位的寄存器,所以只提供低8位的地址。因为外部有时会扩展RAM如果数量少于或等于256,只需提供8个地址即可。

3)使用时,应首先将要读或写的地址发送到DPTR或Ri中,而后再用读写命令。

例:将外部RAM中100H单元内容送到外部RAM中200H单元中。

MOV DPTR,#0100H

MOVX A,@DPTR

MOV DPTR,#0200H

MOVX @DPTR,A

程序存储器向累加器A传送指令

MOVC A,@A DPTR

本指令是将ROM数字发送到A中。这个指令也叫查表指令,经常用这个指令来查一个已经做好了ROM表格(C语言中相似的指针)

说明:

本指令引出了一种新的寻址方法:变址寻址。本指令是ROM在地址单元中找到数据,显然必须知道该单元的地址,该单元的地址是肯定的:在执行本指令的立足点DPTR有一个数字,A有一个数字,执行指令时,将A和DPTR数字加起来,就成了要找的单位的地址。

1)发现的结果放在A中,因此,本指令的执行顺序,A中的值不必定相同。

例子:有一个数字R在0中,需要用查表的方法来确定其平方值(此数的取值范围为0-5)

MOV DPTR,#TABLE

MOV A,R0

MOVC A,@A DPTR

TABLE: DB 0,1,4,9,16,25

设R0中的值为2,送入A中,而DPTR中的值则为TABLE,最后肯定ROM单元地址是TABLE 2.也就是说,去这个单元取数,取4,显然是2平方米。其他数据也可以类比。

标签的真实含义:从这个地方也可以看到另一个问题,我们用标签代替具体的单元地址。事实上,标号的真正含义是地址值。在这里,它0、1、4、9、16、25的数据ROM存储在中间的起点。我们以前学到的就像LCALL DELAY指令中,DELAY 则表明了以DELAY标签的程序在ROM存储在中间的起始地址。事实上,CPU这个程序是通过这个地址找到的。

我们可以通过以下例子来看看标号的含义:

MOV DPTR,#100H

MOV A,R0

MOVC A,@A DPTR

ORG 0100H.

DB 0,1,4,9,16,25

若是R0中的值为2,则最终地址为100H 2为102H,到102H在单位中找到的是4。这个能理解吗?

那为什么不这样写程序,用标号呢?不是增长疑惑吗?

答:如果我们这样写程序,我们在写程序的时候一定要肯定这个表格在ROM如果写完程序后想在这个程序之前插入一个程序,那么表格的位置就会再次改变。ORG 100H这句话,我们经常要修改程序,那么麻烦,所以用标签代替,只要编译程序,位置就会自动改变,让我们把这个麻烦交给计算机指指指PC机去作了。

堆栈操做

PUSH direct

POP #9; direct

第一条指令称为推进,即direct将内容送入堆栈,第二条指令称为弹出,即将堆栈内容送回堆栈direct中间。推入指令的执行过程是,首先将SP加1中值,然后把它拿走SP中中值视为地址direct中值送进去SP中值为地址RAM单元中。

MOV SP,#5FH

MOV A,#100

MOV B,#20

PUSH ACC

PUSH B

第一条执行PUSH ACC指令是这样的:将SP中值加1,即60H,然后将A中的值送到60H因此,在单位中执行本条指令后, 内存60H单元值为100,同样,执行PUSH B时,是将SP 1,即变为61H,然后将B中的值送到61H本条指令执行后,单位中的61H单元中的值变为20。

POP指令的执行是这样的,首先是SP中间值作为地址,并将地址中的数字发送到POP指示后面的direct中,而后SP减1。

接上例:

POP B

POP ACC

执行过程是:将SP中值(现在是61H)取61作为地址H单元中的值(现在是20),送到B中,所以本指令执行后B中的值为20,然后SP因此,本条指令执行后,SP的值变为60H,而后执行POP ACC,将SP中的值(60H)作为地址,从地址中取数(现在是100)并发送到ACC中,因此,执行本条指令后,ACC中的值是100。

这有什么意义?ACC中值原本是100,B值原本是20,是的,在这种情况下,确实没有意义,但在实际工作中,在PUSH B之后,每次都要执行其他指令,这些指令会使A中的值,B因此,在程序结束时,如果我们想删除A和B这些指令在恢复原值时很有意义。

还有一个问题,如果我不需要堆栈,比如说PUSH ACC指令处用MOV 60H,A,在PUSH B处用指令MOV 61H,B,而后用MOV A,60H,MOV B,61H来替代两条POP指令不也一样吗?是的,结果是一样的,但过程是不同的,PUSH和POP指令都是单字节,单周期指令,而MOV指令是双字节,双周期指令。更重要的是,堆栈不止这些,所以通常在计算机上有堆栈,当我们编写子程序时,我们通常不使用以下方法,而是使用堆栈方法。

例:写下下列程序的操作结果

MOV 30H,#12

MOV 31H,#23

PUSH 30H

PUSH 31H

POP 30H

POP 31H

结果是30H中值为23,而31H中间值变为12。两者之间的数据交换。从这个例子可以看出,在使用堆栈时,进出堆栈的书写顺序必须相反,以确保数据被送回原位,否则就会出错。

算术操作指令

1.没有进位的加法指令

ADD A,#DATA ;例:ADD A,#10H

DD A,direct ;例:ADD A,10H

ADD A,Rn ;例:ADD A,R7

ADD A,@Ri ;例:ADD A,@R0

用途:将A中的值与其后面的值相加,最终结果否是回到A中。

例:

MOV A,#30H

ADD A,#10H

则执行完本条指令后,A中的值为40H。

2.带进位位的加法指令

ADDC A,Rn

ADDC A,direct

ADDC A,@Ri

ADDC A,#data

用途:将A中的值和其后面的值相加,而且加上进位位C中的值。

说明:因为51单片机是一种8位机,因此只能作8位的数学运算,但8位运算的范围只有0-255,这在实际工做中是不够的,所以就要进行扩展,通常是将2个8位的数学运算合起来,成为一个16位的运算,这样,能够表达的数的范围就能够达到0-65535。如何合并呢?其实很简单,让咱们看一个10进制数的例子:

66+78。

这两个数相加,咱们根本不在乎这的过程,但事实上咱们是这样作的:先作6+8(低位),而后再作6+7,这是高位。作了两次加法,只是咱们作的时候并无刻意分红两次加法来作罢了,或者说咱们并无意识到咱们作了两次加法。之因此要分红两次来作,是由于这两个数超过了一位数所能表达的范置(0-9)。

在作低位时产生了进位,咱们作的时候是在适当的位置点一下,而后在作高位加法是将这一点加进去。那么计算机中作16位加法时一样如此,先作低8位的,若是两数相加产生了进位,也要“点一下”作个标记,这个标记就是进位位C,在PSW中。在进行高位加法是将这个C加进去。例:1067H+10A0H,先作67H+A0H=107H,而107H显然超过了0FFH,所以最终保存在A中的是7,而1则到了PSW中的CY位了,换言之,CY就至关因而100H。而后再作10H+10H+CY,结果是21H,因此最终的结果是2107H。

3.带借位的减法指令

SUBB A,Rn

SUBB A,direct

SUBB A,@Ri

SUBB A,#data

设(每一个H,(R2)=55H,CY=1,执行指令SUBB A,R2以后,A中的值为73H。

说明:没有不带借位的减法指令,若是须要作不带位的减法指令(在作第一次相减时),只要将CY清零便可。

4.乘法指令

MUL AB

此指令的功能是将A和B中的两个8位无符号数相乘,两数相乘结果通常比较大,所以最终结果用1个16位数来表达,其中高8位放在B中,低8位放在A中。在乘积大于FFFFFH(65535)时,0V置1(溢出),不然OV为0,而CY老是0。

例:(A)=4EH,(B)=5DH,执行指令

MUL AB后,乘积是1C56H,因此在B中放的是1CH,而A中放的则是56H。

5.除法指令

DIV AB

此指令的功能是将A中的8位无符号数除以B中的8位无符号数(A/B)。除法通常会出现小数,但计算机中可无法直接表达小数,它用的是咱们小学生还没接触到小数时用的商和余数的概念,如13/5,其商是2,余数是3。除了之后,商放在A中,余数放在B中。CY和OV都是0。若是在作除法前B中的值是00H,也就是除数为0,那么0V=1。

6.加1指令

INC A

INC Rn

INC direct

INC @Ri

INC DPTR

用途很简单,就是将后面目标中的值加1。例:(A)=12H,(R0)=33H,(21H)=32H,(34H)=22H,DPTR=1234H。执行下面的指令:

INC A (A)=13H

INC R2 (R0)=34H

INC 21H (21H)=33H

INC @R0 (34H)=23H

INC DPTR 9; ( DPTR)=1235H

结果如上所示。

说明:从结果上看INC A和ADD A,#1差很少,但INC A是单字节,单周期指令,而ADD #1则是双字节,双周期指令,并且INC A不会影响PSW位,如(A)=0FFH,INC A后(A)=00H,而CY依然保持不变。若是是ADD A ,#1,则(A)=00H,而CY必定是1。所以加1指令并不适合作加法,事实上它主要是用来作计数、地址增长等用途。另外,加法类指令都是以A为核心的其中一个数必须放在A中,而运算结果也必须放在A中,而加1类指令的对象则普遍得多,能够是寄存器、内存地址、间址寻址的地址等等。

7.减1指令

DEC A

DEC RN

DEC direct

DEC @Ri

与加1指令相似,就很少说了。

逻辑运算类指令:

1. 对累加器A的逻辑操做:

CLR A ;将A中的值清0,单周期单字节指令,与MOV A,#00H效果相同。

CPL A ;将A中的值按位取反

RL A ;将A中的值逻辑左移

RLC A ;将A中的值加上进位位进行逻辑左移

RR A ;将A中的值进行逻辑右移

RRC A ;将A中的值加上进位位进行逻辑右移

SWAP A ;将A中的值高、低4位交换。

例:(A)=73H,则执行CPL A,这样进行:

73H化为二进制为01110011,

逐位取反即为 10001100,也就是8CH。

RL A是将(A)中的值的第7位送到第0位,第0位送1位,依次类推。

例:A中的值为68H,执行RL A。68H化为二进制为01101000,按上图进行移动。01101000化为11010000,即D0H。

RLC A,是将(A)中的值带上进位位(C)进行移位。

例:A中的值为68H,C中的值为1,则执行RLC A

1 01101000后,结果是0 11010001,也就是C进位位的值变成了0,而(A)则变成了D1H。

RR A和RRC A就很少谈了,请你们参考上面两个例子自行练习吧。

SWAP A,是将A中的值的高、低4位进行交换。

例:(A)=39H,则执行SWAP A以后,A中的值就是93H。怎么正好是这么先后交换呢?由于这是一个16进制数,每1个16进位数字表明4个二进位。注意,若是是这样的:(A)=39,后面没H,执行SWAP A以后,可不是(A)=93。要将它化成二进制再算:39化为二进制是10111,也就是0001,0111高4位是0001,低4位是0111,交换后是01110001,也就是71H,即113。

2.逻辑与指令

ANL              A,Rn        ;A与Rn中的值按位'与',结果送入A中

ANL              A,direct ;A与direct中的值按位'与',结果送入A中

ANL              A,@Ri ;A与间址寻址单元@Ri中的值按位'与',结果送入A中

ANL              A,#data ;A与当即数data按位'与',结果送入A中

ANL              direct,A ;direct中值与A中的值按位'与',结果送入direct中

ANL              direct,#data ;direct中的值与当即数data按位'与',结果送入direct中。

这几条指令的关键是知道什么是逻辑与。这里的逻辑与是指按位与

例:71H和56H相与则将两数写成二进制形式:

(71H) 01110001

(56H) 00100110

结果 00100000 即20H,从上面的式子能够看出,两个参与运算的值只要其中有一个位上是0,则这位的结果就是0,两个同是1,结果才是1。

理解了逻辑与的运算规则,结果天然就出来了。看每条指令后面的注释

下面再举一些例子来看。

MOV              A,#45H ;(A)=45H

MOV              R1,#25H ;(R1)=25H

MOV              25H,#79H ;(25H)=79H

ANL              A,@R1 ;45H与79H按位与,结果送入A中为 41H (A)=41H

ANL              25H,#15H ;25H中的值(79H)与15H相与结果为(25H)=11H)

ANL              25H,A ;25H中的值(11H)与A中的值(41H)相与,结果为(25H)=11H

在知道了逻辑与指令的功能后,逻辑或和逻辑异或的功能就很简单了。逻辑或是按位“或”,即有“1”为1,全“0”为0。例:

10011000

或 01100001

结果 11111001

而异或则是按位“异或”,相同为“0”,相异为“1”。例:

10011000

异或 01100001

结果 11111001

而全部的或指令,就是将与指令中的ANL 换成ORL,而异或指令则是将ANL       换成XRL。

3..逻辑或指令:

ORL              A,Rn        ;A和Rn中的值按位'或',结果送入A中

ORL              A,direct ;A和与间址寻址单元@Ri中的值按位'或',结果送入A中

ORL              A,#data ;A和立direct中的值按位'或',结果送入A中

ORL              A,@Ri ;A和即数data按位'或',结果送入A中

ORL              direct,A ;direct中值和A中的值按位'或',结果送入direct中

ORL              direct,#data ;direct中的值和当即数data按位'或',结果送入direct中。

4.逻辑异或指令:

XRL              A,Rn        ;A和Rn中的值按位'异或',结果送入A中

XRL              A,direct ;A和direct中的值按位'异或',结果送入A中

XRL              A,@Ri ;A和间址寻址单元@Ri中的值按位'异或',结果送入A中

XRL              A,#data ;A和当即数data按位'异或',结果送入A中

XRL              direct,A ;direct中值和A中的值按位'异或',结果送入direct中

XRL              direct,#data ;direct中的值和当即数data按位'异或',结果送入direct中。

控制转移类指令

1、无条件转移类指令

1.短转移类指令

AJMP       addr11

2.长转移类指令

LJMP       addr16

3.相对转移指令

SJMP       rel

上面的三条指令,若是要仔细分析的话,区别较大,但初学时,可不理会这么多,通通理解成:JMP标号,也就是跳转到一个标号处。事实上,LJMP标号,在前面的例程中咱们已接触过,而且也知道如何来使用了。而AJMP和SJMP也是同样。那么他们的区别何在呢?在于跳转的范围不同。比如跳远,LJMP一下就能跳64K这么远(固然近了更不要紧了)。而AJMP最多只能跳2K距离,而SJMP则最多只能跳256这么远。原则上,全部用SJMP或AJMP的地方均可以用LJMP来替代。所以在初学时,须要跳转时能够全用LJMP,除了一个场合。什么场合呢?先了解一下AJMP,AJMP是一条双字节指令,也就说这条指令自己占用存储器(ROM)的两个单元。而LJMP则是三字节指令,即这条指令占用存储器(ROM)的三个单元。下面是第四条跳转指令。

2、间接转移指令

JMP         @A+DPTR

这条指令的用途也是跳转,转到什么地方去呢?这可不能由标号简单地决定了。让咱们从一个实际的例子入手吧。

MOV    DPTR,#TAB       ;将TAB所表明的地址送入DPTR

MOV    A,R0                  ;从R0中取数(详见下面说明)

MOV    B,#2

MUL    A,B           ;A中的值乘2(详见下面的说明)

JMP    A,@A+DPTR      ;跳转

TAB:      AJMP     S1          ;跳转表格

AJMP     S2

AJMP     S3

应用背景介绍:在单片机开发中,常常要用到键盘,见上面的9个按键的键盘。咱们的要求是:当按下功能键A………..G时去完成不一样的功能。这用程序设计的语言来表达的话,就是:按下不一样的键去执行不一样的程序段,以完成不一样的功能。怎么样来实现呢?

前面的程序读入的是按键的值,如按下'A'键后得到的键值是0,按下'B'键后得到的值是'1'等等,而后根据不一样的值进行跳转,如键值为0就转到S1执行,为1就转到S2执行。。。。如何来实现这一功能呢?

先从程序的下面看起,是若干个AJMP语句,这若干个AJMP语句最后在存储器中是这样存放的,也就是每一个AJMP语句都占用了两个存储器的空间,而且是连续存放的。而AJMP S1存放的地址是TAB,到底TAB等于多少,咱们不须要知道,把它留给汇编程序来算好了。

下面咱们来看这段程序的执行过程:第一句MOV DPTR,#TAB执行完了以后,DPTR中的值就是TAB,第二句是MOV A,R0,咱们假设R0是由按键处理程序得到的键值,好比按下A键,R0中的值是0,按下B键,R0中的值是1,以此类推,如今咱们假设按下的是B键,则执行完第二条指令后,A中的值就是1。而且按咱们的分析,按下B后应当执行S2这段程序,让咱们来看一看是不是这样呢?第三条、第四条指令是将A中的值乘2,即执行完第4条指令后A中的值是2。下面就执行JMP @A+DPTR了,如今DPTR中的值是TAB,而A+DPTR后就是TAB+2,所以,执行此句程序后,将会跳到TAB+2这个地址继续执行。看一看在TAB+2这个地址里面放的是什么?就是AJMP    S2这条指令。所以,立刻又执行AJMP              S2指令,程序将跳到S2处往下执行,这与咱们的要求相符合。

请你们自行分析按下键“A”、“C”、“D”……以后的状况。

这样咱们用JMP     @A+DPTR就实现了按下一键跳到相应的程序段去执行的这样一个要求。再问你们一个问题,为何取得键值后要乘2?若是例程下面的全部指令换成LJMP,即:

LJMP      S1,LJMP        S2……这段程序还能正确地执行吗?若是不能,应该怎么改?

3、条件转移指令:

条件转移指令是指在知足必定条件时进行相对转移。

1..判A内容是否为0转移指令

JZ rel

JNZ rel

第一指令的功能是:若是(A)=0,则转移,不然顺序执行(执行本指令的下一条指令)。转移到什么地方去呢?若是按照传统的方法,就要算偏移量,很麻烦,好在如今咱们能够借助于机器汇编了。所以这第指令咱们能够这样理解:JZ 标号。即转移到标号处。下面举一例说明:

MOV A,R0

JZ L1

MOV R1,#00H

AJMP L2

L1: MOV R1,#0FFH

L2: SJMP L2

END

在执行上面这段程序前若是R0中的值是0的话,就转移到L1执行,所以最终的执行结果是R1中的值为0FFH。而若是R0中的值不等于0,则顺序执行,也就是执行 MOV R1,#00H指令。最终的执行结果是R1中的值等于0。

第一条指令的功能清楚了,第二条固然就好理解了,若是A中的值不等于0,就转移。把上面的那个例子中的JZ改为JNZ试试吧,看看程序执行的结果是什么?

2.比较转移指令

CJNE A,#data,rel

CJNE A,direct,rel

CJNE Rn,#data,rel

CJNE @Ri,#data,rel

第一条指令的功能是将A中的值和当即数data比较,若是二者相等,就顺序执行(执行本指令的下一条指令),若是不相等,就转移,一样地,咱们能够将rel理解成标号,即:CJNE A,#data,标号。这样利用这条指令,咱们就能够判断两数是否相等,这在不少场合是很是有用的。但有时还想得知两数比较以后哪一个大,哪一个小,本条指令也具备这样的功能,若是两数不相等,则CPU还会反映出哪一个数大,哪一个数小,这是用CY(进位位)来实现的。若是前面的数(A中的)大,则CY=0,不然CY=1,所以在程序转移后再次利用CY就可判断出A中的数比data大仍是小了。

例:

MOV A,R0

CJNE A,#10H,L1

MOV R1,#0FFH

AJMP L3

L1: JC L2

MOV R1,#0AAH

AJMP L3

L2: MOV R1,#0FFH

L3: SJMP L3

上面的程序中有一条指令咱们还没学过,即JC,这条指令的原型是JC rel,做用和上面的JZ相似,可是它是判CY是0,仍是1进行转移,若是CY=1,则转移到JC后面的标号处执行,若是CY=0则顺序执行(执行它的下面一条指令)。

分析一下上面的程序,若是(A)=10H,则顺序执行,即R1=0。若是(A)不等于10H,则转到L1处继续执行,在L1处,再次进行判断,若是(A)>10H,则CY=1,将顺序执行,即执行MOV R1,#0AAH指令,而若是(A)<10H,则将转移到L2处指行,即执行MOV R1,#0FFH指令。所以最终结果是:本程序执行前,若是(R0)=10H,则(R1)=00H,若是(R0)>10H,则(R1)=0AAH,若是(R0)<10H,则(R1)=0FFH。

弄懂了这条指令,其它的几条就相似了,第二条是把A当中的值和直接地址中的值比较,第三条则是将直接地址中的值和当即数比较,第四条是将间址寻址获得的数和当即数比较,这里就不详谈了,下面给出几个相应的例子。

CJNE A,10H ;把A中的值和10H中的值比较(注意和上题的区别)

CJNE 10H,#35H ;把10H中的值和35H中的值比较

CJNE @R0,#35H ;把R0中的值做为地址,今后地址中取数并和35H比较

3.循环转移指令

DJNZ Rn,rel

DJNZ direct,rel

第一条指令在前面的例子中有详细的分析,这里就很少谈了。第二条指令,只是将Rn改为直接地址,其它同样,也很少说了,给一个例子。

DJNZ 10H,LOOP

调用与返回指令

(1)主程序与子程序 在前面的灯的实验中,咱们已用到过了子程序,只是咱们并无明确地介绍。子程序是干什么用的,为何要用子程序技术呢?举个例子,咱们数据老师布置了10道算术题,通过观察,每一道题中都包含一个(3*5+2)*3的运算,咱们能够有两种选择,第一种,每作一道题,都把这个算式算一遍,第二种选择,咱们能够先把这个结果算出来,也就是51,放在一边,而后要用到这个算式时就将51代进去。这两种方法哪一种更好呢?没必要多言。设计程序时也是这样,有时一个功能会在程序的不一样地方反复使用,咱们就能够把这个功能作成一段程序,每次须要用到这个功能时就“调用”一下。

(2)调用及回过程:主程序调用了子程序,子程序执行完以后必须再回到主程序继续执行,不能“一去不回头”,那么回到什么地方呢?是回到调用子程序的下面一条指令继续执行(固然啦,要是还回到这条指令,不又要再调用子程序了吗?那可就没完没了了……)。

位及位操做指令

经过前面那些流水灯的例子,咱们已经习惯了“位”一位就是一盏灯的亮和灭,而咱们学的指令却全都是用“字节”来介绍的:字节的移动、加法、减法、逻辑运算、移位等等。用字节来处理一些数学问题,好比说:控制冰箱的温度、电视的音量等等很直观,能够直接用数值来表在。但是若是用它来控制一些开关的打开和合上,灯的亮和灭,就有些不直接了,记得咱们上次课上的流水灯的例子吗?咱们知道送往P1口的数值后并不能立刻知道哪一个灯亮和来灭,而是要化成二进制才知道。工业中有不少场合须要处理这类开关输出,继电器吸合,用字节来处理就显示有些麻烦,因此在8031单片机中特地引入一个位处理机制。

1、.位寻址区

在8031中,有一部份RAM和一部份SFR是具备位寻址功能的,也就是说这些RAM的每个位都有自已的地址,能够直接用这个地址来对此进行操做。

字节地址

位地址

2FH

7FH

78H

2EH

77H

70

2DH

6FH

68H

2CH

67H

60H

2BH

5FH

58H

2AH

57H

50H

29H

4FH

48H

28H

47H

40H

27H

3FH

38H

26H

37H

30H

25H

2FH

28H

24H

27H

20H

23H

1FH

18H

22H

17H

10H

21H

0FH

08H

20H

07H

06H

05H

04H

03H

02H

01H

00H

图1

内部RAM的20H-2FH这16个字节,就是8031的位寻址区。看图1。可见这里面的每个RAM中的每一个位咱们均可能直接用位地址来找到它们,而没必要用字节地址,而后再用逻辑指令的方式。

2、能够位寻址的特殊功能寄存器

8031中有一些SFR是能够进行位寻址的,这些SFR的特色是其字节地址都可被8整除,如A累加器,B寄存器、PSW、IP(中断优先级控制寄存器)、IE(中断容许控制寄存器)、SCON(串行口控制寄存器)、TCON(定时器/计数器控制寄存器)、P0-P3(I/O端口存器)。以上的一些SFR咱们还不熟,等咱们讲解相关内容时再做详细解释。

3、位操做指令

MCS-51单片机的硬件结构中,有一个位处理器(又称布尔处理器),它有一套位变量处理的指令集。在进行位处理时,CY(就是咱们前面讲的进位位)称“位累加器”。有自已的位RAM,也就是咱们刚讲的内部RAM的20H-2FH这16个字节单元即128个位单元,还有自已的位I/O空间(即P0.0…..P0.7,P1.0…….P1.7,P2.0……..P2.7,P3.0……..P3.7)。固然在物理实体上它们与原来的以字节寻址用的RAM,及端口是彻底相同的,或者说这些RAM及端口均可以有两种用法。

1..位传送指令

MOV C,BIT

MOV BIT,C

这组指令的功能是实现位累加器(CY)和其它位地址之间的数据传递。

例:MOV P1.0,CY ;将CY中的状态送到P1.0引脚上去(若是是作算术运算,咱们就能够经过观察知道如今CY是多少啦)。

MOV P1.0,CY ;将P1.0的状态送给CY。

2..位修正指令

位清0指令

CLR C ;使CY=0

CLR bit ;使指令的位地址等于0。例:CLR P1.0 ;即便P1.0变为0

位置1指令

SETB C ;使CY=1

SETB bit ;使指定的位地址等于1。例:SETB P1.0 ;使P.0变为1

位取反指令

CPL C ;使CY等于原来的相反的值,由1变为0,由0变为1。

CPL bit ;使指定的位的值等于原来相反的值,由0变为1,由1变为0。

例:CPL P1.0

以咱们作过的实验为例,若是原来灯是亮的,则执行本指令后灯灭,反之原来灯是灭的,执行本指令后灯亮。

4、位逻辑运算指令

1..位与指令

ANL C,bit ;CY与指定的位地址的值相与,结果送回CY

ANL C,/bit ;先将指定的位地址中的值取出后取反,再和CY相与,结果送回CY,但注意,指定的位地址中的值自己并不发生变化。

例:ANL C,/P1.0

设执行本指令前,CY=1,P1.0等于1(灯灭),则执行完本指令后CY=0,而P1.0也是等于1。

可用下列程序验证:

ORG 0000H

AJMP START

ORG 30H

START: MOV SP,#5FH

MOV P1,#0FFH

SETB C

ANL C,/P1.0

MOV P1.1,C ;将作完的结果送P1.1,结果应当是P1.1上的灯亮,而P1.0上的灯仍是不亮。

2..位或指令

ORL C,bit

ORL C,/bit

这个的功能你们自行分析吧,而后对照上面的例程,编一个验证程序,看看你相得对吗?

5、位条件转移指令

1..判CY转移指令

JC rel

JNC rel

第一条指令的功能是若是CY等于1就转移,若是不等于1就顺序执行。那么转移到什么地方去呢?咱们能够这样理解:JC 标号,若是等于1就转到标号处执行。这条指令咱们在上节课中已讲到,再也不重复。

第二条指令则和第一条指令相反,即若是CY=0就转移,不等于0就顺序执行,固然,咱们也一样理解: JNC 标号

2..判位变量转移指令

JB bit,rel

JNB bit,rel

第一条指令是若是指定的bit位中的值是1,则转移,不然顺序执行。一样,咱们能够这样理解这条指令:JB bit,标号

第二条指令请你们先自行分析

下面咱们举个例子说明:

ORG 0000H

LJMP START

ORG 30H

START:MOV SP,#5FH

MOV P1,#0FFH

MOV P3,#0FFH

L1: JNB P3.2,L2 ;P3.2上接有一只按键,它按下时,P3.2=0

JNB P3.3,L3 ;P3.3上接有一只按键,它按下时,P3.3=0

LJM P L1

L2: MOV P1,#00H

LJMP L1

L3: MOV P1,#0FFH

LJMP L1

END

把上面的例子写入片子,看看有什么现象………

按下接在P3.2上的按键,P1口的灯全亮了,松开或再按,灯并不熄灭,而后按下接在P3.3上的按键,灯就全灭了。这像什么?这不就是工业现场常常用到的“启动”、“中止”的功能吗?

怎么作到的呢?一开始,将0FFH送入P3口,这样,P3的全部引线都处于高电平,而后执行L1,若是P3.2是高电平(键没有按下),则顺序执行JNB P3.3,L3语句,一样,若是P3.3是高电平(键没有按下),则顺序执行LJMP L1语句。这样就不停地检测P3.二、P3.3,若是有一次P3.2上的按键按下去了,则转移到L2,执行MOV P1,#00H,使灯全亮,而后又转去L1,再次循环,直到检测到P3.3为0,则转L3,执行MOV P1,#0FFH,例灯全灭,再转去L1,如此循环不已。

标签: 107h胆电容

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台