51单片机定时器中断函数返回和普通函数返回的细节

51单片机,汇编。想做高精度时钟。纠结于定时中断函数返回的问题。
用仿真器一直没明白,定时中断函数执行过程中定时器处于中止状态?
如下程序:
ORG 0000H
AJMP MAIN
;
ORG 0003H
RETI
;
ORG 000BH
AJMP TIMER0
;
ORG 0013H
RETI
;
ORG 001BH
RETI
;
ORG 0030H
MAIN: MOV TMOD,#01H
MOV TH0,#0FFH
MOV TL0,#0A0H
SETB EA
SETB ET0
SETB TR0
AJMP $
TIMER0: MOV TH0,#0FFH
MOV TL0,#0A0H
MOV A,#FFH
LOOP: DEC A
JNZ LOOP
RETI
END
是否在TIMER0函数执行过程中及其调用的函数执行过程中,定时器0处于中止状态,直至REI返回?RETI返回时将PC从栈中取回继续执行中断前程序,是否同时清除定时器0中断标志位?
还是当TIMER0函数执行的同时,定时器0中断标志位已经清0,并且定时器0已经开始重新计时?
另外,中断函数执行时,单片机只将PC压栈,那么普通函数调用时,单片机将哪些寄存器值压栈?全部功能寄存器?还是只有PC?还是部分功能寄存器值压栈?
另外有个不爽的代码。
51汇编不支持MOV R0,R1这种代码,只能MOV R0,01H。真是无语。
Sorry.习惯于C和C++的一些说法,大家也别太深究。
前面定时器0中断子程序里写了一段循环是说明问题。总共255*3=765时钟周期。但在我自己的代码里可能还不止这么多,按中断优先级的说法,同级中断子程序执行中,定时器0溢出的中断不会再响应。如果用做高精度的时钟,应该会出现漏掉部分中断造成计时变慢,不知道有什么解决办法。另外,中断子程序必须给TH0,TL0重新赋值,如果想要时钟更精确的话要考虑这部分代码的执行时间?比如:
TIMER0: MOV TH0,#FFH
MOV TL0,#0A0H
RETI
这样的中断子程序本身执行要4个时钟周期,如果要精确计时95ms是不是至少改成
MOV TH0,#0FFH
MOV TL0,#9CH
?
网上查了一些资料,没有查找51单片机自定义栈的说明,下面是自己自定义栈以及现实的一个子程序,使用R0做自定义栈栈顶指针。不知道是否正确?

汇编语言里面,没有“函数”这个词汇。

定时器0只是在TR0为零的时候,才停止;在其它的任何期间,不停。
加一计数到FFFFH,再加一,将产生溢出标志TF0,计数值变成0000H。
定时器0溢出标志TF0在中断响应的时候,自动清零。(T2例外)。

中断响应,只有PC自动压栈。
调用子程序,也是只有PC自动压栈。
------------------------------------------
做高精度的时钟,可以选用外接的实时时钟器件,如DS1302。
如果一定要用单片机自身的T0,就应该把T0优先级定为唯一的高级,不让其它中断干扰它。
如果要改动下面的这个初始值,是个好办法。
TIMER0: MOV TH0,#FFH
MOV TL0,#0A0H
RETI
但是对FFA0的修改,是应该往“大”了改。
本人曾用单片机的定时器做过时钟,一个月,也差不了一秒;
呵呵,是用家里的一个电子表,摆在一起,进行比对的。
主要就是对初始值,进行了多种不同数值的测试。
--------------
自己管理一片空间,进行类似堆栈的“后进先出”,或者滑动存储的“先进先出”,都是可以的。
给出的代码没有细看,自己进行测试,就知道是否正确了。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2010-08-24
定时器不会自动停止,只有在TR0为零时才能停止。

如果你想要在中断中停止计时,可以将定时器先关掉,退出中断钱再打开。

中断函数调用没有返回值,返回命令RETI
其他函数可以有返回值,返回指令RET

进入中断、调用子函数都是PC压栈
第2个回答  2010-08-24
MOV A,#FFH
LOOP: DEC A
JNZ LOOP
而你的定时初始值为(ffa0),即你的定时器0是每隔95微妙就中断一次,而中断中的循环大于255微秒,即:你在执行中断程序时又产生了新的中断,这样就将中断程序给覆盖掉了。
第3个回答  2010-08-24
为什么不用C呢 很费解