|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
单片机的累加器A与片外RAM之间的数据传递类指令
& z+ l" w% Q' H+ tMOVX A,@Ri
, |5 u. H% s( v. e8 k2 [* fMOVX @Ri,A% g! @4 w" B' \% J5 x! i
MOVX A,@DPTR8 c! W' i2 @0 H0 k7 \. n' T1 A
MOVX @DPTR,A
8 t7 h- j# b7 B; k说明:7 n) o1 J1 H: [/ x
1)在51系列单片机中,与外部存储器RAM打交道的只能是A累加器。所有需要传送入外部RAM的数据必需要通过A送去,而所有要读入的外部RAM中的数据也必需通过A读入。在此我们能看出内外部RAM的区别了,内部RAM间能直接进行数据的传递,而外部则不行,比如,要将外部RAM中某一单元(设为0100H单元的数据)送入另一个单元(设为0200H单元),也必须先将0100H单元中的内容读入A,然后再传送到0200H单元中去。- f: y# L! n v& ?" l! o" o/ z
要读或写外部的RAM,当然也必须要知道RAM的地址,在后两条单片机指令中,地址是被直接放在DPTR中的。而前两条指令,由于Ri(即R0或R1)只是一个8位的寄存器,所以只供给低8位地址。因为有时扩展的外部RAM的数量比较少,少于或等于256个,就只需要供给8位地址就够了。
; r6 _1 ]4 B7 C* A0 ` t$ L使用时应当首先将要读或写的地址送入DPTR或Ri中,然后再用读写命令。9 T n6 x* S A4 Q9 [
例:将单片机外部RAM中100H单元中的内容送入外部RAM中200H单元中。" ~" e3 {+ c% H* f& l1 }4 [9 a
MOV DPTR,#0100H
9 R$ p5 c- y' u3 p2 a4 qMOVX A,@DPTR
! d- ]4 N, X! F' M; e3 p2 ~MOV DPTR,#0200H6 H. V( u. k0 U- a
MOVX @DPTR,A
8 S V9 P6 J) V. z( z+ h% j程序存储器向累加器A传送指令
" p1 u0 I6 c# j% r. A( sMOVC A,@A+DPTR 本指令是将ROM中的数送入A中。本指令也被称为单片机查表指令,常用此指令来查一个已做好在ROM中的表格 说明:
0 H/ u% K" T# |+ s2 a6 O, w4 P5 ]此条指令引出一个新的寻址办法:变址寻址。本指令是要在ROM的一个地址单元中找出数据,显然必须知道这个单元的地址,这个单元的地址是这样确定的:在执行本指令立脚点DPTR中有一个数,A中有一个数,执行指令时,将A和DPTR中的数加起为,就成为要查找的单元的地址。* v# a$ F0 \( [
查找到的结果被放在A中,因此,本条指令执行前后,A中的值不一定相同。
" Q6 D% J- o( X' |$ `0 a例:有一个数在R0中,要求用查表的办法确定它的平方值(此数的取值范围是0-5)
/ h& e! D$ K! Y/ }; L8 l' t& QMOV DPTR,#TABLE
# s! l9 i0 \5 C0 d5 n' jMOV A,R0
; s! [, ?/ ~% uMOVC A,@A+DPTR4 O9 k; }) \& Q: M/ Y# N% c
TABLE: DB 0,1,4,9,16,25
/ A: M9 i& p% _2 s0 ]设R0中的值为2,送入A中,而DPTR中的值则为TABLE,则最终确定的ROM单元的地址就是TABLE+2,也就是到这个单元中去取数,取到的是4,显然它正是2的平方。其它数据也能类推。
1 A3 L- U8 @+ F+ V% r: k6 p* _8 w ( k6 l$ u2 Y# @+ s) a* T
标号的真实含义:从这个地方也能看到另一个问题,我们使用了标号来替代具体的单元地址。事实上,标号的真实含义就是地址数值。在这里它代表了,0,1,4,9,16,25这几个数据在ROM中存放的起点位置。而在以前我们学过的如LCALL DELAY单片机指令中,DELAY 则代表了以DELAY为标号的那段程序在ROM中存放的起始地址。事实上,CPU正是通过这个地址才找到这段程序的。6 }, w1 m# [* p' W3 Y
能通过以下的例程再来看一看标号的含义:* P1 j* t& \" o& F5 X6 P |
MOV DPTR,#100H4 `2 e' O6 h+ y- F; g' O+ \2 y
MOV A,R0
) D1 {4 O* u' `, zMOVC A,@A+DPTR
3 b0 }2 d1 U2 g' RORG 0100H.
4 ~) s/ f7 ~1 T$ w, ?DB 0,1,4,9,16,25
5 i; }# h4 b7 Q如果R0中的值为2,则最终地址为100H+2为102H,到102H单元中找到的是4。这个能看懂了吧?/ I$ H- x) d6 L9 W/ I
那为什么不这样写程序,要用标号呢?不是增加疑惑吗?
2 g% V1 Y$ o5 W如果这样写程序的话,在写程序时,我们就必须确定这张表格在ROM中的具体的位置,如果写完程序后,又想在这段程序前插入一段程序,那么这张表格的位置就又要变了,要改ORG 100H这句话了,我们是经常需要修改程序的,那多麻烦,所以就用标号来替代,只要一编译程序,位置就自动发生变化,我们把这个麻烦事交给计算机��指我们用的电脑去做了。
, ] h/ E+ I4 d& i$ P堆栈操作! H# p8 O; x @
PUSH direct2 O" Y; b1 U3 O$ b! F
POP direct% z3 ^$ m. A' j z5 e2 a7 e1 {
第一条指令称之为推入,就是将direct中的内容送入堆栈中,第二条指令称之为弹出,就是将堆栈中的内容送回到direct中。推入指令的执行过程是,首先将SP中的值加1,然后把SP中的值当作地址,将direct中的值送进以SP中的值为地址的RAM单元中。例:0 Z6 s2 F" X8 N0 Y3 T" W: ^
MOV SP,#5FH
; a8 f9 n7 M: hMOV A,#100
4 Y4 x1 q: d$ }, y( @MOV B,#20: E* e( g3 y% h: y& M
PUSH ACC' _7 _5 c# }& U- h3 T6 R' |
PUSH B7 N2 N3 k5 \% ?, G2 Y8 i4 E
则执行第一条PUSH ACC指令是这样的:将SP中的值加1,即变为60H,然后将A中的值送到60H单元中,因此执行完本条指令后, 内存60H单元的值就是100,同样,执行PUSH B时,是将SP+1,即变为61H,然后将B中的值送入到61H单元中,即执行完本条指令后,61H单元中的值变为20。+ c- O; z: w5 i O$ R" Z
POP指令的在单片机中执行是这样的,首先将SP中的值作为地址,并将此地址中的数送到POP指令后面的那个direct中,然后SP减1。
3 `: w$ l. o B# I9 Z" v$ c接上例:1 q" P6 D& J4 }! @0 Q5 w* j
POP B
7 {, W0 W- D9 k! oPOP ACC
; y7 D7 l& g. @则执行过程是:将SP中的值(现在是61H)作为地址,取61H单元中的数值(现在是20),送到B中,所以执行完本条指令后B中的值是20,然后将SP减1,因此本条指令执行完后,SP的值变为60H,然后执行POP ACC,将SP中的值(60H)作为地址,从该地址中取数(现在是100),并送到ACC中,所以执行完本条指令后,ACC中的值是100。
( |5 g5 O; E4 x( j" ]' G0 j这有什么意义呢?ACC中的值本来就是100,B中的值本来就是20,是的,在本例中,的确没有意义,但在实际工作中,则在PUSH B后一般要执行其他指令,而且这些指令会把A中的值,B中的值改掉,所以在程序的结束,如果我们要把A和B中的值恢复原值,那么这些指令就有意义了。
6 {2 G4 w2 F# ?9 y3 }8 y还有一个问题,如果我不用堆栈,比如说在PUSH ACC指令处用MOV 60H,A,在PUSH B处用指令MOV 61H,B,然后用MOV A,60H,MOV B,61H来替代两条POP指令,不是也一样吗?是的,从结果上看是一样的,但是从过程看是不一样的,PUSH和POP指令都是单字节,单周期指令,而MOV指令则是双字节,双周期指令。更何况,堆栈的作用不止于此,所以一般的计算机上都设有堆栈,单片机也是一样,而我们在编写子程序,需要保存数据时,常常也不采用后面的办法,而是用堆栈的办法来实现。
; v; c$ k1 m9 H0 E例:写出以下单片机程序的运行结果
- G" @) a- N, E5 GMOV 30H,#12& Y: {! s6 P+ |# c8 J- c+ F
MOV 31H,#23
: {5 ^3 ]$ v% m: oPUSH 30H
/ d; n+ W9 n) qPUSH 31H: [) T3 q2 \0 c" C3 `# l
POP 30H
* e2 Q- j3 O. qPOP 31H. b- i7 x9 J; Y) V" ~! E. ?3 p
结果是30H中的值变为23,而31H中的值则变为12。也就两者进行了数据交换。从这个例程能看出:使用堆栈时,入栈的书写次序和出栈的书写次序必须相反,才能保证数据被送回原位,不然就要出错了。
. Y, R7 {* Y, Q: Q6 f6 g
5 l8 v; @& x+ t2 C作业:在MCS51下执行上面的例程,注意观察内存窗口和堆栈窗口的变化。
+ P% I; P' d, m |
|