单片机问题,为什么这个程序会连续执行两次

代码如下:

START:
MOV R0, #5

LOOP:
MOV P2, #0FFH
CALL DELAY
MOV P2, #040H
CALL DELAY
DJNZ R0, LOOP

DELAY:
MOV R3, #50

D1: MOV R4, #20
D2: MOV R5, #248
DJNZ R5, $
DJNZ R4, D2
DJNZ R3, D1
RET

END

其实是忘了在LOOP的最后一行加上 JMP START
但是出人意料的是它竟然连续闪了 10 次。按理说只能闪烁 5 次呀,因为 R0 计数是 5 呀。怎么回事呢?
R0 不是已经赋值为 5 了么?

另外那个单步执行我也试了,的确是两次,但是似乎很难看出为什么....

产生这种想象的根本原因,是在DJNZ R0, LOOP指令后缺少一条令指令计数器PC不变的指令,如SJMP $.
若不加该指令,会在程序循环5次(R0=5)后,即执行5次DJNZ R0, LOOP指令后,会再次进入延时程序(不是通过调用指令进入的),即此时SP的内容仍是07H;当延时程序执行RET时,会将07H单元的内容送到程序计数器PC中,SP的内容变为05H,此时程序将会从头开始执行,开始第2个5次循环。
在程序执行完第2个5次循环后,即执行10次DJNZ R0, LOOP指令后,会又次进入延时程序(不是通过调用指令进入的),即此时SP的内容仍是05H;当延时程序执行RET时,会将05H单元的内容送到程序计数器PC中,SP的内容变为03H,此时程序又会从头开始执行。
但此时从头开始执行的过程与前两个区别很大了。但执行第3条指令(调用指令)后进入延时程序,延时程序会把刚才压入堆栈中的断点覆盖掉,当执行完DJNZ R3, D1时,堆栈栈顶的内容变为0,执行完RET,程序又会从头开始执行,重环往复。从外观上看,P2一直为FFH,好像程序停止运行。
所以分析出现该现象,要注意堆栈。单步执行,好好观察。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-01-14
R0没有赋初值!另外建议不要使用前2B个地址,因为51中断矢量就在这个空间里。建议从0030H开始。以下程序在keil4中仿真成功。
ORG 0000H
AJMP AG
ORG 0030H
AG:MOV A,#11111110B
MOV R0,#8
AG1:RL A
MOV P0,A
ACALL DELAY
DJNZ R0,AG1
ACALL DELAY
MOV A,#11111111B
MOV P1,A
ACALL DELAY
MOV P0,#00000000B
ACALL DELAY
MOV P0,#11111111B
ACALL DELAY
MOV P0,#00000000B
ACALL DELAY
MOV P0,#11111111B
ACALL DELAY
SJMP AG
DELAY:MOV R3,#10
D3:MOV R2,#200
D1:MOV R1,#250
D2:DJNZ R1,D2
DJNZ R2,D1
DJNZ R3,D3
RET
END
第2个回答  2011-01-14
单步执行试试!很有帮助的,会看到执行过程,这样对知识学习也有帮助!
第3个回答  2011-01-14
赋初值就是给一个变化量先定一个固定的值。你的 MOV R0, #5

就是。
第4个回答  2011-01-15
MOV P2, #0FFH
CALL DELAY
MOV P2, #040H
CALL DELAY
是不是因为对p2赋值了两次呢,循环5次就对p2赋值了10次
每赋值一次就闪一次?
相似回答