51单片机延时出错

请高人帮我解决一下延时出错的问题
在定时中断内加上一个延时子程序,结果程序的执行顺序被打乱,这是为什么啊?
#include<reg52.h>
#define u8 unsigned char
#define u16 unsigned int
sbit P11=P1^0;
unsigned char a,num;
void delay(u8 i) ;
void main()
{
num=0;
EA=1;
ET0=1;
TMOD=0x01;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
TR0=1;
while(1)
{
if(num==2)
{
num=0;
P11=~P11;
}
}
}
void time1() interrupt 1
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
num++;
delay(num) ;
}
void delay(u8 i)
{
u16 j;
for(;i>0;i--)
for(j=40000;j>0;j--)
{
}
}
如果不加延时子程序,程序则无错
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
num++;
改为
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++
依然出错
怎么修改才能满足延时的要求呢?

的确会出错,这里有一个中断嵌套的问题。实际上,当你执行delay这个函数的时候定时器依然再走,由次又引发一个中断,这个中断又去调用delay函数。解决的办法是将delay函数定义为可重用,接着在进入中断时关闭定时器或者关闭定时器中断,然后再调用delay函数结束后打开定时器或者打开定时器中断。当然这可能会和你本来想要的功能有所出入,具体问题还是要具体分析。

上楼说的有错,你的这个程序与嵌套无关,51里面当进入中断后则处理中断,如果中断还未处理完,同一个中断又被触发,这时后它会被挂起,直到这个中断处理完了以后它才会再次进入中断,你的这个程序编译决对是没问题的,但是不会完成你要的功能,因为你开的是定时器0,定时器0中断程序里面却是给定时器1赋值,请问你是否看到,
void time1() interrupt 1
{
TH1=(65536-50000)/256; //〉〉〉〉〉〉〉应该是TH0=(65536-50000)/256;
TL1=(65536-50000)%256; //》》》》》》》应该是TL0=(65536-50000)%256;
num++;
delay(num) ;
}

上楼说的中断嵌套到底那个时会才会出现呢?
我可以告诉你,如果delay在主程序中调用了,中断里面也有调用,这样才会出嵌套问题。
注意上楼说的这段话是完全错的“实际上,当你执行delay这个函数的时候定时器依然再走,由次又引发一个中断,这个中断又去调用delay函数。”任意时候都不出现这类优先级一样,中断未处理完又会中断的。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2009-03-28
的确会出错,这里有一个中断嵌套的问题。实际上,当你执行delay这个函数的时候定时器依然再走,由次又引发一个中断,这个中断又去调用delay函数。解决的办法是将delay函数定义为可重用,接着在进入中断时关闭定时器或者关闭定时器中断,然后再调用delay函数结束后打开定时器或者打开定时器中断。当然这可能会和你本来想要的功能有所出入,具体问题还是要具体分析。本回答被提问者和网友采纳
第2个回答  2009-03-31
你的程序一定要改,中断服务程序精短是基本原则,是实现中断快速响应的保证。
首先在单片机中尽量不要处理类似
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
这样复杂的运算,特别是在中断服务程序中。因为实际需要消耗很多的指令周期。直接这么写
TH1=0x3C;
TL1=0xB0;
再者,在中断服务程序中不要嵌套函数,因为函数在某些编译器编译之后会进行入栈出栈操作。中断响应本身就是一个随机过程,必然会进行入栈出栈操作。如果栈的层级不够很容易使得入栈出栈数据出错。如果非要嵌套函数,请你可以把函数的实现再单独copy一次。
void time1() interrupt 1
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
num++;
u16 j;
for(;num>0;num--)
for(j=40000;j>0;j--)
{
}
}
最后,不要让定时中断服务程序的执行时间超过定时器的定时设定时间。原因楼上的也说了,系统为了保证精准的时钟中断,在中断服务程序运行过程中定时器是继续计时的。除非你在进入定时中断就马上手动停止定时器,退出中断服务程序前再次开启。当然这种采用这种方式在某些定时要求比较高的场合是不允许的。

我从程序上分析不出你写这段代码想要执行的预期功能,所以不能告诉你如何改进。改的方向主要还是把握上面几个的原则,想新的程序算法(或实现方法)。
第3个回答  2009-03-29
上楼说的有错,你的这个程序与嵌套无关,51里面当进入中断后则处理中断,如果中断还未处理完,同一个中断又被触发,这时候它会被挂起,直到这个中断处理完了以后它才会再次进入中断,你的这个程序编译决对是没问题的,但是不会完成你要的功能,因为你开的是定时器0,定时器0中断程序里面却是给定时器1赋值,请问你是否看到,
void time1() interrupt 1
{
TH1=(65536-50000)/256; //〉〉〉〉〉〉〉应该是TH0=(65536-50000)/256;
TL1=(65536-50000)%256; //》》》》》》》应该是TL0=(65536-50000)%256;
num++;
delay(num) ;
}

上楼说的中断嵌套到底那个时会才会出现呢?
我可以告诉你,如果delay在主程序中调用了,中断里面也有调用,这样才会出嵌套问题。
注意上楼说的这段话是完全错的“实际上,当你执行delay这个函数的时候定时器依然再走,由次又引发一个中断,这个中断又去调用delay函数。”类优先级一样,中断未处理完,中断会被挂起,直到这个中断处理完了以后它才会再次进入中断。
相似回答