单片机经典教程 - 图文(3)

2019-07-13 16:05

(6) P:奇偶检验位

每次运算结束后若A 中二进制数“1”的个数为奇数,则P=1 ,否则P=0 。例:某运算结果是58H (01011000),显然“1”的个数为奇数,所以P=1。

4.DPTR(DPH,DPL):数据指针

数据指针是一个16 位的寄存器,我们可以用它来访问外部RAM ,也可以访问外部ROM 中的表格,具体应用以后再讲。 5.SP:堆栈指针:

让我们先来理解一下堆栈是什么意思?你在家洗碗吗?我们洗好碗之后,是怎么放的呢?一般总是先洗的放在下面,晚洗的放在上面,然后用的时候呢,总是晚放上去的先用,先放上去的后用;如果你不洗碗不要紧,知道码头上仓库里堆的货物吗?一般也是先进去的后出来,而后进去的先出来,这种符合“先进后出,后进先出”存放规则的现象我们就把它叫做“堆栈”。(其实栈在中文中的意思就是码头)。 在单片机中,我们可以在内部RAM 中构造出(注意?:是可以构造)这样一个区域,这个区域存放数据的规则就符合堆栈中“先进后出,后进先出”的原则。为什么要有这样一个区域呢?存储器本身不也同样可以存放数据吗?是的,知道了存储器地址确实可以读出它里面的内容,但如果我们要读出的是一批数据,每一个数据都要给出一个地址就会很麻烦,为了简化操作就可以利用堆栈的存放方法来读取数据,具体的应用我们将在十五课中结合具体实验来讲,这里只是让大家先了解一下。那么堆栈在单片机的什么地方?也就是说把RAM 空间的哪一块区域作为堆栈呢?这就不好定了,因为51 系列单片机是一种通用的单片机,每个人的实际需要各不相同,有人需要多一些堆栈,而有人则不需要那么多堆栈,所以INTEL 公司就干脆不分了,把分的权利让给用户(编程者),也就是说我们可以根据自已的需要来决定,所以单片机中堆栈的位置是可以变化的,而这种变化就体现在SP 中值的变化,看下面的图,SP 中的值等于27H 不就相当于是一个指针指向27H 单元吗?这就是堆栈指针的由来。

当然在MCS-51 单片机中,指针开始所指的位置并非就是数据存放的位置,而是数据存放的前一个位置。例如一开始堆栈指针是指向27H 单元的,那么第一个数据的存放位置就在28H 单元中,而不是27H 单元中,这一点请大家注意。 6.电源控制寄存器PCON

单片机在以电池供电的系统中,有时为了节电,我们需要让它尽量降低电源的消耗,所以单片机就有多种的工作方式,其中一种就是低功耗方式,PCON 寄存器就是用来控制单片机进入低功耗方式的。 单片机经典教程9 单片机的工作方式

单片机共有复位、程序执行、低功耗和编程与加密四种工作方式,下面分别加以介绍。 1.复位方式 (1)为什么要复位

大家知道,单片机执行程序时总是从地址0000H 开始的,所以在进入系统时必须对CPU 进行复位,也叫初始化;另外由于程序运行中的错误或操作失误使系统处于死锁状态时,为了摆脱这种状态,也需要进行复位,就象电脑死机了要重新启动一样。 (2)复位的原理

单片机复位的方法其实很简单,只要在RST 引脚(9 脚)上加一个持续时间为24 个振荡周期(即两个机器周期)的高电平就可以了。如果晶振为12M,计算一下这个持续脉冲需要多长时间? (3)如何进行复位

复位操作有上电自动复位、按键复位和外部脉冲复位3 种方法,上电自动复位是通过外部复位电路的电容充电来实现的,当电源刚接通时电容C 对下拉电阻开始充电,由于电容两边的电压不能突变,所以RTS 端维持高电平,只要这个充电时间不超过1ms,就可以实现对单片机的自动上电复位,即接通电源就完成了系统的初始化,在实际的工程应用中,如果没有特殊要求,一般都采用这种复位方式;按键复位的电路如图2 所示,它其实就是在上电复位的基础上加了R2 和SA,这种电路一般用在需要经常复位的系统中;外部脉冲复位的电路如图3 所示,外部复位通常用于要求比较高的系统,比如希望系统死锁后能自动复位。外部复位是由专门的集成电路来实现的,也就是我们通常俗称的“看门狗”电路,这种电路有很多,它们不但能完成对单片机的自动复位功能,而且还有管理电源、用作外部存储器等功能,比如X25045,MAX813L 等等就是比较常用的此类芯片,

现在让我们先来看看单片机复位后,它的内部会有些什么变化呢?看下面的表: (4)复位后的状态

这就是单片机复位后内部系统的状。 2.程序执行方式

程序执行是单片机的基本工作方式,由于复位后PC=0000 ,所以程序就从地址0000H 开始执行,此时单片机就根据指令的要求完成一系列的操作控制,比如前面讲的让LED 灯闪烁起来,不过在实际使用中,程序并不会从0000H 开始执行,而总是安排一条跳转指令,比如LJMP START ,为什么要这样安排,我们讲到中断时再来解释。 3. 低功耗操作方式

在以电池供电的系统中,有时为了降低电池的功耗,在程序不运行时就要采用低功耗方式,低功耗方式有两种—待机方式和掉电方式。 低功耗方式是由电源控制寄存器PCON (上一课我们提到过的)来控制的。电源控制寄存器是一个逐位定义的8 位寄存器,其格式如下, 其中:SMOD 为波特率倍增位,在串行通讯时用;GF1 为通用标志位1;GF0 为通用标志位0;PD 为掉电方式位,PD=1,进入掉电方式;IDL 为待机方式位,IDL=1 ,进入待机方式。也就是说只要执行一条指令让PD 位或IDL 位为1 就可以了。那么单片机是如何进入或退出掉电工作方式和待机工作方式的。

1 .待机方式 2 .进入待机方式

当使用指令使PCON 寄存器的IDL=1 ,则进入待机工作方式。此时CPU 停止工作,但时钟信号仍提供给RAM,定时器,中断系统和串行口;同时堆栈指针SP,程序计数器PC,程序状态字PSW,累加器ACC 以及全部的通用寄存器都被冻结起来;单片机的消耗电流从24mA 降为3.7mA,这样就可以节省电源的消耗。 ② 退出待机方式

退出待机方式可以采用引入中断的方法,在中断程序中安排一条RETI 的指令就可以了,什么是中断,我们现在还不知道,当然这没关系。其实待机方式和我们使用电脑时的睡眠方式有异曲同工之妙。 (2)掉电方式 ①进入待机方式

当使用指令使PCON 寄存器的PD=1 ,则进入掉电工作方式,此时单片机的一切工作都停止,只有内部RAM 的数据被保持下来;掉电方式下电源可以降到2V,耗电仅50uA 。此时就相当于把显示器和硬盘也关闭了。 ② 退出待机方式

退出掉电工作方式的唯一方法是复位,不过应在电源电压恢复到正常值后再进行复位,复位时间要大于10mS ,在进入掉电方式前,电源电压是不能降下来的,因此可靠的单片机电路最好要有电源检测电路。显然掉电方式和待机方式是两种不同的低功耗工作方式,前者可以在无外部事件触发时降低电源的消耗,而后者则在程序停止运行时才使用。关于单片机的低功耗的方式就简单的讲这些,更详细的内容也留到下册再讲解,因为那都是大虾们的作品。 4. 编程和加密方式

单片机的编程与加密是由专门的设备来完成的,这种设备称为编程器或烧录器,类似的产品有很多,功能也不尽相同。本站的XL2000是集烧录、试验、编程、仿真一体化的产品

单片机经典教程10 什么是单片机的寻址?单片机有几种寻址方式? 什么是单片机的寻址?单片机有几种寻址方式?

我们已经知道,单片机的工作过程就是一条一条地从ROM 存储器中取出指令然后执行相关的操作,那么一条指令究竟有哪几部分组成?它又包括哪些内容?一般来说一条指令总是有操作码字段和操作数字段两部分组成,看下面两条指令,MOV R7,#250;MOV P1,#0FFH ,这是我们以前学过的指令,在这两条指令中MOV 就是操作码字段,R7 和P1 就是操作数地址字段,而#0FFH 我们称为常数(也就是立即数),单片机执行指令时就根据指令中给出的地址寻找实际的操作数,不能理解,没关系,继续往下看。 一.单片机的寻址 先来看下面的实验:

程序一就是我们以前做过的LED 灯闪烁的实验,我们已经知道每次调用延时程序的时间都是相同的(125mS) ,如果现在提出这样的要求:灯亮后延时时间为125mS 灯灭,灯灭后又延时100mS 秒灯亮,如此循环,这样的程序还能满足要求吗?显然不能,怎么办?我们可以把它改成程序二,也就是先把一个数送入30H ,在子程序中R7 中的值并不固定,而是根据30H 单元中传过来的数来确定,这样就可以满足要求,大家自行分析一下这个程序。

从这里我们可以得出结论,在数据传递中要找到被传递的数,很多时候,这个数并不能直接给出,而是需要变化,这就引出了一个概念:如何寻找操作数,我们把寻找操作数所在单元地址的过程称之为寻址。在实验一中,我们直接使用数所在单元的地址找到了操作数,所以称之为直接寻址。而在实验二中,我们是把数先放在工作寄存器中,从工作寄存器中寻找数据,这种方式则称之为寄存器寻址。例如:MOV R7,30H,就是把工作寄存器30H 单元中的数送到R7 中,这就是寄存器寻址。

接下来提一个问题:我们知道,工作寄存器就是内存单元的一部份,如果我们选择工作寄存器组0,则R0 就是RAM 的00H 单元,那么这样一来,MOV A,00H ,和MOV A,R0 不就没什么区别了吗?为什么要加以区分呢?的确,这两条指令执行的结果是完全相同的,都是将00H 单元中的内容送到A 中去,但是执行的过程不同,执行第1 条指令需要2 个周期;而执行第2 条则只需要1 个周期,第1 条指令变成最终的目标码要两个字节(E5H 00H),而第2 条则只要一个字节(E8h)就可以了。也许有朋友会问,不就差了一个周期吗,为什么怎么斤斤计较!如果是12M 晶振的话,也就1 个微秒,一个字节又能有多少呢?当然如果这条指令只执行一次,也许无所谓,但一条指令如果执行上1000 次,就是1 毫秒,如果要执行1000000 次,就是1S 的差别,这就很可观了,单片机要做的就是实时控制,所以必须如此“斤斤计较”。再来看另一个问题,现在我们已经知道,寻找操作数可以通过直接给的方式(立即寻址)和直接给出数所在单元地址的方式(直接寻址),这就够了吗?看下面的问题,要求从30H 单元开始,取20 个数,分别送入累加器A 中。就我们目前掌握的办法,要从30H 单元取数,就用MOV A,30H ,那么下一个数呢?是31H 单元的,怎么取呢?还是只能用MOV A,31H ,那么20 个数,不是得20 条指令才能写完吗?这里只有20 个数,如果要送200 个或2000 个数,那岂不要写上200 条或2000 条命令?这未免太笨了吧。为什么会出现这样的状况?因为我们只会把地址写在指令中,所以就没办法了,如果我们不是把地址直接写在指令中,而是把地址放在另外一个寄存器单元中,根据这个寄存器单元中的数值决定该到哪个单元中取数。比如,当前这个寄存器中的值是30H ,那么就到30H 单元中去取,如果是31H 就到31H 单元中去取,就可以解决这个问题了。怎么个解决法呢?既然看的是寄存器中的值,那么我们就可以通过一定的方法让这里面的值发生变化,比如取完一个数后,将这个寄存器单元中的值加1,还是执行同一条指令,可是取数的对象却不一样了。看下面的例子:

MOV R7,#20 ;(1) MOV R0,#30H ;(2)LOOP:MOV A,@R0 ;(3) INC R0 ;(4) DJNZ R7,LOOP ;(5)

这个例子中的大部份指令我们是能看懂的,第1 条,是将立即数20 送到R7 中,执行完后R7 中的值应当是20;第2 条是将立即数30H 送入R0 工作寄存器中,所以执行完后,R0 单元中的值是30H;第3 条,是看一下R0 单元中是什么值,把这个值作为地址,取这个地址单元的内容送入A 中,此时,执行这条指令的结果就相当于执行MOV A,30H ;第4 条,没学过,就是把R0 中的值加1,因此执行完后,R0 中的值就是31H 了;第5 条,学过,将R7 中的值减1,看是否等于“0”,不等于“0”,则转到标号LOOP 处继续执行,因此,执行完这句后,将转去执行MOV A,@R0 这一条,此时相当于执行了MOV A,31H (因为此时的R0 中的值已是31H 了);如此,直到R7 中的值逐次相减等于“0”,也就是循环20 次为止,就实现了我们的要求:从30H 单元开始将20 个数据送入A 中。这是另一种寻找数据的方法,由于数据是间接被找到的,所以把这种寻址方式称之为寄存器间址寻址。(注意?,在间址寻址中,只能用R0 或R1 来存放等待寻找的数据)。

除了以上几种寻址方法外,单片机还有变址寻址,相对寻址和位寻址共七种寻址方式。这些您暂时可以不去深究它,我们以后会结合具体的实验再来详细介绍,这里只是为了归类,所以才把它们例举在一起。 二.寻址方式举例 1.直接寻址

直接寻址时,指令中的地址码部分直接给出了操作数的有效地址。例如:MOV A,4FH ;A←(4FH)可用于直接寻址的空间有内部RAM 的低128 字节(包括其中的位寻址区与特殊功能寄存器)。 2.寄存器直接寻址

寄存器寻址时,指令中地址码给出的是某一通用寄存器的编号,寄存器的内容为操作数。 例如:MOV A,R7 ;A←(R7)

可用于寄存器寻址的空间有R0-R7,ACC,CY(位),DPTR,B。 3.寄存器间接寻址

寄存器间接寻址时,指令中给出的寄存器的内容为操作数的地址,而不是操作数本身。例如:MOV A,@R0 ;A←[(R1)]可用于寄存器间接寻址的空间只能是R0 和R1, 用DPTR 或PC 可间接寻址64K 字节外部的RAM 或ROM. 4.立即寻址

立寻址时,指令中地址码部分给出的就是操作数本身。 例如:MOV A,#0FFH ;A←0FFH 可用于立即寻址的空间有 5.变址寻址

变址寻址时,指定变址寄存器的内容与指令中给出的偏移量相加DPTR 所得的结果作为操作数的地址。 例如:MOVC A,@A+DPTR ; A←[(A)+(DPTR)]。

无论用DPTR 或PC 作为基准指针,变址寻址只适用于程序存储器(即ROM),通常用于读取数据表。 6.相对寻址

相对寻址时,由程序计数器PC 提供的基准地址与指令中提供的偏移量rel 相加,得到操作数的地址。例如:SJMP rel ;PC←(PC)+2+rel 7.位寻址

位寻址时,操作数是二进制数的某一位,其位地址出现在指令中。 例如:SETB bit ;(bit)←1

可用于位寻址的空间有内部RAM 的可位寻址区和SFR(特殊功能寄存器)中的字节地址可以被8 整除(即地址以0、8、F 结尾)的寄存器空间。 单片机经典教程11 单片机指令(一)

指令就是编程者给单片机下的命令,也就是我们平常所说的单片机软件,前面我们已经陆续地讲到了一些指令,但还远远不够,从这一课开始就要全面的讲解指令了,希望大家多动手实验,巩固所学的知识,说实在的,其实单片机并不难学。为了让大家比较容易记忆,按照常规分类,我把单片机的111 条指令分成了五类—即数据传递类指令、算术运算类指令、逻辑运算类指令、控制转移类指令和位操作指令。这一课先来看数据传递类指令:一.数据传递类指令数据传递类指令是单片机中用的最多的指令,在51 系列单片机的111 条指令中共有28 条是数据传递类指令,前面我们已经学到了几条,比如MOV R1,#250;MOV A,R6 等,那么它们是怎么分类的呢?请往下看: 1. 以累加器为目的操作数的指令 (1)MOV A,Rn (2)MOV Rn,A (3)MOV A,direct (4)MOV A,@Ri (5)MOV A,#data

指令(1)把Rn 中的数送入累加器A,Rn 代表工作寄存器R0-R7(以后我们只要写到Rn 都代表R0-R7 ,这一点请大家记住了); 指令(2)则相反,把工作寄存器中的数送入累加器A 中;

指令(3)是把直接地址中的数送入累加器A 中,driect 就代表直接地址(以后也相同);

指令(4)就是上一课我们讲的寄存器间接寻址,什么意思?这里再重复一遍,就是看一下工作寄存器中是什么值,把这个值作为地址,把这个地址中的数送入累加器A 中,Ri 代表什么意思呢?就是工作寄存器R0 或者R1(以后如果写Ri 都代表R0 或R1);

指令(5)就是把立即数(也叫常数)直接送入累加器A 中,很显然data 就代表立即数(以后也相同),其实这个我们以前提到过,加#的数就代表送入的是这个数的本身。接下来举几个实例加以说明,大家可以用DUBG8051 这个软件验证一下: A.MOV R7,#250;MOV A,R7 ;将工作寄存器R7 中的值250 送入A,R7 中的值保持不变。 B.MOV A,#250;MOV R7,A;将A 中的值250 送入工作寄存器R7,A 中的值保持不变。C.MOV 30H,#250;MOV A,30H ;将内存30H 单元中的值250 送入A,30H 单元中的值保持不变。D.MOV 20H,#250;MOV R0,#20;MOV A,@R0 ;先看R0 中是什么值,把这个值作为地址,并将这个地址单元中的值送入A 中。执行命令前R0 中的值为20H,则是将20H 单元中的值250 送入A 中。E.MOV A,#250 ;将立即数250 送入A 中,执行完本条指令后,A 中的值是250。 2.以寄存器Rn 为目的操作数的指令(1)MOV Rn,A (2)MOV Rn,direct (3)MOV Rn,#data 举几个实例大家自行分析一下:A.MOV R7,A ;B.MOV R7,30H ;C.MOV R7,#20 ;这组指令功能是把源地址单元中的内容送入工作寄存器,源操作数不变。 3.以直接地址为目的操作数的指令 34 _ 单片机教程(MCS-51 系列) (1) MOV direct,A 例如:MOV 30H,A(将累加器A 中的数送入内存单元30H)(2)MOV direct,Rn 例如:MOV 30H,R7(将寄存器R7 中的数送入内存单元30H)(3)MOV direct,direct 例如:MOV 30H,20H(将内存单元20H 中的数送入内存单元30H)(4)MOV direct,@Ri 例如:MOV 30H,@R0 (看一下R0 中是什么值,把这个值作为地址,并将这个地址单元中的值送入A 中。如执行指令前R0 中的值为20H,则是将20H 单元中的值送入A 中)。(5)MOV direct,#data 例如:MOV 30H,#20(将立即数20 送入内存单元30H) 4. 以间接地址为目的操作数的指令 (1)MOV @Ri,A (2)MOV @Ri,direct (3)MOV @Ri,#data16 这三条指令就不介绍了,大家自行分析一下,不过有一点希望大家记住,Ri只能用工作寄存器R0或者R1。 5. 十六位数的传递指令 MOV DPTR,#data16 指令说明:这是51 单片机中唯一的一条16 位立即数传递指令,大家知道51 系列单片机是一种8 位单片机,8 位单片机所能表示的最大数只能是28=0-255 。讲到这里大家应该明白了,为什么我们前面的实验中立即数不能大于255 。如果现在有个数是1234H (即二进制0001 0010 0011 0100),我们要把它送入DPTR ,该怎么办呢?当然有办法,INTEL 公司已经把DPTR 分成了两个寄存器,DPH 和DPL (看一下前面的特殊功能寄存器介绍),我们只要把12H( 高8 位)送入DPH ,把34H( 低8 位)送入DPL 中去就可以了,所以执行指令MOV DPTR,#1234H 和执行指令MOV DPH,#12H(1); MOV DPL,#34H(2);是一样的。二.指令练习请写出下列每条指令的执行结果,并DPL

单片机经典教程12 单片机指令(二)

这一课继续讲解其他的数据类指令。提示:下面的内容我们下册中才会用到,这里只是为了把数据传递类指令讲完,才提前把它们讲一下,

您不知道也没关系。

一.数据传递类指令 6.累加器A 与片外RAM 之间的数据传递类指令什么是片外RAM(即片外数据存储器)呢?单片机不是有内部RAM 吗?为什么还要片外RAM 呢?难道单片机的内部RAM 还不够用吗?的确如此,当单片机的内部RAM 不够时,我们就要扩充RAM 空间。那么单片机能扩充多少的外部RAM空间呢?89C51 单片机的片外RAM可以扩展到64K,即从0000H-FFFFH,那么它是怎样和累加器A 进行数据传递的?它们之间的传递指令共有以下四条: (1) MOVX A,@Ri (2) MOVX @Ri,A (3) MOVX A,@DPTR (4) MOVX @DPTR,A 指令说明: A.在51 系列单片机中,与外部存储器RAM 传递数据的只可以是累加器A,所有要送入或读出外部RAM 的数据必须先送到A 中去,在此我们可以看出内外部RAM 的区别了:内部RAM 间可以直接进行数据的传递,而外部RAM 则不行。比如,要将外部RAM 中某一单元(设为100H 单元的数据)送入另一个单元(设为200H 单元),就必须先将100H 单元中的内容读入A,然后再送到200H 单元中去。在这里有一个问题:CPU 是如何区分内、外部RAM 的?大家看这里的四条指令,其操作码都是MOVX ,而内部RAM 的操作码则是MOV,CPU 就是根据不同的指令来自动区分读写内、外部RAM 的。 B.要读出或写入外部的RAM ,当然还必须知道外部RAM 的地址,在后两条指令中,地址是被直接放在DPTR 中的;而前两条指令由于Ri(即R0 或R1)只是一个8 位的寄存器,所以只能提供低8 位的地址。不过有时我们要扩展的外部RAM 数量比较少(少于或等于256 个字节),提供低8 位的地址也就足够了。 C.使用时应当首先将要读出或写入的地址送入DPTR 或Ri 中,然后再用读写指令。举例:将外部RAM 中100H 单元中的内容送入外部RAM 中200H 单元中。 MOV DPTR,#0100H MOVX A,@DPTR MOV DPTR,#0200H MOVX @DPTR,A 7.累加器A 与片外ROM 之间的数据传递类指令 MOVC A,A+@DPTR 前一小节讲了累加器A 与外部RAM 之间的数据传递类指令,接下来再来讲讲片外ROM 与累加器A 之间的数据传递类指令。在讲解之前,先来了解一下内部ROM 和外部ROM 的组成,89C51 的内部有4K 的FLASH ROM 空间,其地址为000H-FFFH ,片外可以扩展到64K(OOOOH-FFFFH),在这64K 的ROM 空间中,有4K 字节的地址是片内和片外公用的(即000H-FFFH),而1000H-FFFFH 的空间是片外ROM 专用的。讲到这里大家就会问:既然有4K 的地址是公用的,那么CPU 是如何区分的呢?不知大家是否还记得,在第二讲单片机的硬件电路中,有一个引脚EA(即31 脚),当EA=1,CPU 从片内ROM 的4K 字节中取指令,如果地址超过了4K(FFFH),单片机就自动转向片外ROM 取指令,大家注意?:这个过程是自动完成的,不需要人工干预;而当EA=0 时,CPU 只从片外ROM 取指令。讲到这里,不知大家注意?没有,当使用外部ROM 和外部RAM 时,它们的寻址空间都是0000H-FFFFH,也就是说它们在地址上是重叠的,那么CPU 在读取指令时又是如何来区分当前是从ROM 取指令还是从单片机教程(MCS-51 系列) RAM 取指令呢?请大家来看第二课的89C51 单片机硬件电路图,29 脚是PSEN ,当我们置位PSEN 时(即PSEN=1),CPU 就读取外部ROM 指令;而要从外部RAM 读取指令时就置位WR(即16 脚)或RD(即17 脚),这样即使ROM 地址和RAM 地址是重叠的,也不会出现混乱。这里又有一个问题了,16 脚和17 脚不是并行口P3.6 和P3.7 吗?如果我们把它当作第二功能WR 和RD 来使用,CPU 又是如何来区分的呢?这个问题我们前面已经讲过了,这里再重复一遍:单片机引脚的第二功能是不需要人工干预的,也就是说只要CPU 执行到相应的指令,就自动转成了第二功能。了解了片外ROM 的读取指令原理,再来看片外ROM 与累加器A 之间的数据传递指令(注意?:ROM 只能读取指令,而不能写入数据,这一点和RAM 是不同的)。 MOVC A,A+@DPTR 指令说明: A.本指令是将ROM 中的数送入A 中。通常称其为查表指令,常用此指令来查一个已做好在ROM 中的表格。 B.此条指令引出一个新的寻址方法:变址

DUBG8051

1.MOV 12H,#34H 2.MOV R0,#23H 3.MOV R7,#22H 4.MOV R1,12H 5.MOV A,@R0 6.MOV 34H,@R1 7.MOV 45H,34H 8.MOV 12H,DPH 9.MOV R0,

寻址。本指令是要在ROM 的一个地址单元中找出数据,显然必须知道这个单元的地址,这个单元的地址是这样确定的:在执行本指令前DPTR 中有一个数,A 中也有一个数,执行指令时,将A 和DPTR 中的数加起来,就成为要查找的数的单元地址。 C.查找到的结果被放在A 中,因此,本条指令执行前后,A 中的值不一定相同。 举例:有一个数在R0 中,要求用查表的方法确定它的平方值(此数取值范围是0-5) MOV DPTR,#TAB MOV A,R0 MOVC A,@A+DPTR . . TAB: DB 0,1,4,9,16,25 设R0 中的值为?2?,送入A 中,而DPTR 中的值则为?TAB?,则最终确定的ROM 单元的地址就是?TAB+2?,也就是到?TAB+2 ?这个单元中去取数,取到的是?4?(Db 后面的第三个数)。其它数据也可以次类推。从这里可以看出,我们使用了标号(象TAB 等)来代替具体的ROM 单元地址,事实上,标号的真实含义就是地址的数值,在这里它就代表了TAB+0,TAB+1, TAB+25 这几个数据在ROM 中的存放位置;而我们以前学过的如LCALL DELAY 指令,DELAY 代表的是以DELAY 为标号的那段程序在ROM 中存放的起始地址,CPU 就是根据这个起始地址才找到指令的,无法理解是吗?没关系,让我们先来看几个符号的含义就会明白了。二.单片机的伪指令(注意?:伪指令不是单片机指令)我们前面简单提到过,END 是伪指令,那么到底什么是伪指令?它在单片机中有什么作用呢?接下来我们就来讨论这个问题,伪指令是单片机中用来给寄存器定义或者赋值的特殊指令为什么要用伪指令呢?让我们来看下面的实验: 1.DB—定义字节伪指令它的功能是从程序存储器ROM 单元的某个地址开始,存入一组规定好的8 位二进制常数。例如:ORG 2000H; TAB:DB 45H,48H,10;34H;以上指令经汇编后,将对从2000H 开始的若干ROM 单元赋值,即(2000H)=45H,(2001H)=48H,(2002H)=0AH,(2003H)=34H。讲到这里,有的人会问:在这些指令中,我直接用MOV 2000H,45H;MOV 2001H,48H ??不就得了,干吗要用DB 指令呢?是的,从理论上讲,两者的效果是一样的,只是因为我们现在的程序都很短,单片机不可能只做这些简单的工作,当程序比较长时,这些指令的意义就不一样了。除了刚刚提到的END 和DB 伪指令外,单片机中还有那些伪指令呢?下面简单讲解一下: 2.DW—定义字伪指令 37 _ 单片机之友 QQ:280919249 单片机教程(MCS-51 系列) 在计算机中,一个字由两个字节组成,也就是说,如果一个字节可以表示一个8 位数的话,那么一个字就可以表示一个十六位的数(关于这方面的问题我们留到下册中再来讨论,这里就不讲了,以免增加大家的学习难度),如此一来,这条伪指令的功能也就清楚了,就是从指定的ROM 单元开始,定义若干个16 位常数;上一课我们已经讲过,51 系列单片机要存放一个16 位的常数就必须把这个数分成两个8 位数据来存放,通常我们把一个16 位数的高8 位放入低地址,而把低8 位放入高地址(注意?:这两个地址必须是紧挨着的)。例如:ORG 3000H; ABC:DW 2345H,0A859H;程序经汇编后,(3000H)=23H,(3001H)=45H,(3002H)=A8,(3003H)=59H。注意?:象0A859H 这样的数值在写法上,A 的前面一定要加上个0。 3.DS—保留空间伪指令它的功能是从指定的地址开始,保留若干个字节的ROM 空间留作它用。例如:ORG 2000H; ABC:DS0 8H; LOOP:MOV A,30H;汇编以后,从2000H 开始,将保留8 个ROM 单元留作它用,那么以LOOP 为标号的指令就存放在2008H 单元中。这里有一点请大家注意?:这几条伪指令都只能对程序存储器(ROM)起作用,而不能用它们来对数据存储器(RAM)进行赋值或做其他的工作。至于它们到底有什么作用,我们什么时候才需要用到它们?我们将在下册的实验中再作讲解。现在让我们通过一段程序来解释一下查表程序的使用方法,这可是一定要学会的。例如: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 这条指令),如果我们是经常需要修改程序的,那多麻烦,所以就用标号来替代,只要一编译程序,位置就自动发生变化,我们把这件事交给计算机去做了。 8.堆栈的操作指令什么是堆栈,我们前面已经介绍过了,那么堆栈是如何进行数据传递的呢?对堆栈的操作指令有2 条:(1)PUSH direct (2)POP direct 第1 条指令称之为推入,就是将direct 中的内容送入到堆栈中;第2 条指令称之为弹出,就是将堆栈中的内容送回到direct 中。推入指令的执行过程是:首先将SP 中的值加1,然后把SP 中的值当作地址,将direct 中的值送进以SP 中的值为地址的RAM 单元中。例如:MOV SP,#5FH ; MOV A,#100 ; MOV B,#20 ; PUSH ACC ; PUSH B ; 38 _ 单片机之友 QQ:280919249 单片机教程(MCS-51 系列) 这段指令的执行过程是这样的:将SP 中的值加1,即变为60H ,然后将A 中的值(#100 )送到60H 单元中,因此执行完PUSH ACC 这条指令后,内存60H 单元的值就是100 ,同样,执行PUSH B 时,是将SP+1 ,即变为61H ,然后将B 中的值送入到61H 单元中,即执行完本条指令后,61H 单元中的值变为20。这是推入,那么弹出又是怎么样的呢?请看下面的例子: MOV SP,#5FH ; MOV A,#100 ; MOV B,#20 ; PUSH ACC ; PUSH B ; POP B ; POP ACC ; POP 指令的执行是这样的:首先将SP 中的值作为地址,并将此地址中的数送到POP 指令后面的那个direct 中,然后SP 减1。上面程序的执行过程是:将SP 中的值(现在是61H)作为地址,取61H 单元中的数值(现在是20),送到B 中,所以执行完POP B 指令后B 中的值是20,然后将SP 减1,那么此时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 指令则是双字节,双周期指令。更何况,堆栈的作用不止于此,所以一般的单片机上都设有堆栈,而我们在编写子程序,需要保存数据时,通常也采用堆栈的方法来实现。 9.其他的数据传递类指令(1)XCH A,Rn (2)XCH A,direct (3)XCH A,@Ri (4)XCHD A,@Ri (5)MOVC A,A+PC 前面的4 条指令是进行数据交换用的,第1 条,寄存器与累加器交换;第2 条直接地址与累加器交换;第3 条间接RAM 与累加器交换;第4 条间接RAM 与累加器的低4 位交换;第5 条是累加器与代码字节之间的数据传递类指令,这些指令作为初学者可能暂时还用不上,所以就不介绍了,大家只要了解一下就可以了,等下册中我们再来详细的讨论。三.本课总结到本课为止,数据传递类指令全部讲解完了,在单片机的指令中,数据传递类指令是使用最多的指令,因此这部分的内容是必须掌握的,如何来使


单片机经典教程 - 图文(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:某工程监理大纲

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: