# Timing Delay Error

I am new to embedded system programming. I am working on clock using 8051 timer and interrupt.The delay is perfectly of 1s but when I run my clock with computer clock I loses 3-5s in 10min.I have try many value in interrupt but no success.Please help..

delay();

void delay(int a)
{

for (i=0;i<a;i++){
TH1 = 0XA5;
TL1 = 0XFE;
TR1 = 1;
while(TF1==0);
TR1 = 0;
TF1 = 0;
}

}


interrupt;

void timer(void) interrupt 1        //interrupt no. 1 for Timer 0
{

TH0 = 0xF6;
TL0 = 0x36;
P2=0xFF;
dig_1 = dig_2 = dig_3 = dig_4 =dig_5 = dig_6 =0;

dig++;
dig=dig%6;

switch(dig)
{
case 0:
P2=digit[sec1];
dig_1 = 1;
break;

case 1:
P2= digit[sec2];
dig_2 = 1;
break;

case 2:
P2=digit[min1];
dig_3 = 1;
break;

case 3:
P2= digit[min2];
dig_4 = 1;
break;

case 4:
P2=digit[hr1];
dig_5 = 1;
break;

case 5:
P2= digit[hr2];
dig_6 = 1;
break;

}

}


main();

{
j=0;

TMOD = 0x11;        // mode1 of Timer0
//2720us

TH0 = 0xF6;
TL0 = 0x36;
ET0=1;              // enable timer0 interrupt
EA=1;               // enable interrupts
TR0 = 1;        //start timer

while(1)        // Forward counting
{
hr1=hr2=min2=min1=sec2=sec1=0;
for(hr2=0;hr2<3;hr2++){
if(hr2 == 0 || hr2 ==1){
l = 10;
}
if(hr2 == 2){
l = 4;
}
for(hr1=0;hr1<l;hr1++){

for(min2=0;min2<6;min2++){
for(min1=0;min1<10;min1++){
for(sec2=0;sec2<6;sec2++){
for(sec1=0;sec1<10;sec1++){
delay(40);
if(ctrl_1 ==0){
setting();
}

}
}
}
}
}
}

}
}

• The delay may be exactly 1 second, but how long does all the rest of the code, between subsequent 1 second delays, take to run? – Majenko Nov 15 '14 at 0:05
• Only interrupt is used for multiplexing running with delay(). – Iamat8 Nov 15 '14 at 1:19
• You mean your "loops" code in main() won't run? – diverger Nov 15 '14 at 1:53
• Why not use the interrupt to maintain the time-critical RTC (real-time clock) counters, and use the non-time-critical main() delay loop to run the display multiplexers? This system effectively has two threads, the interrupt is run at controlled intervals and main() is not. – MarkU Nov 15 '14 at 1:55

The interrupt is not magic- when an interrupt occurs, the delay loop stops momentarily while the processor steals cycles to multiplex the display routine, and then it resumes, so the delay routine takes longer than expected to complete (and jitters a bit), hence your clock runs slow. You could adjust the delay routine but I don't suggest that (there could be problems). The time between delay calls also has to be taken into account.

Ignoring the gory details of the 8051 timers, in general in this situation you should do the important timing using timer interrupts from a free-running timer, not a delay loop. You can count down in your interrupt routine and set a flag every xx milliseconds to have the multiplexing done in your main() routine. Main just waits for a flag then does the next multiplex digit. That way your clock can keep as good time as the crystal (which may not be great, but it should be a lot better). You can also do the display mux in the ISR if the timing works out, which would reduce the display scan jitter.

In general, never use a looped delay() for anything where the exact time is important (it's okay for generating a minimum delay), in fact, it's (usually) better to never use it at all once you get beyond "hello, world" type of LED blinking.

• I strongly second doing the display muxing in the ISR of the free-running timer. It's amazing how even a tiny amount of timing jitter can be very visible on such a display. Been there, done that! – Dave Tweed Nov 15 '14 at 2:41
• Is the code under interrupt timer(void) not ISR? – Iamat8 Nov 15 '14 at 4:40
• can you please suggest any example of your explanation. – Iamat8 Nov 15 '14 at 4:44