2
\$\begingroup\$

I wrote a simple code counting 30 seconds using Timer 0 (Mode 0, it's 13-bit counter) of Atmel 89S51, and I used Proteus to simulate. After 30 seconds the LED light should be turned on.

I found that the LED light would be turned on at about 31 second, that seems to be an error of 1 second. I think this error is not acceptable since I only count 30 seconds.

In this picture you can see the simulation result:

http://i.imgur.com/etXD8cG.png

Simulation result

Here is the code:

#include <reg51.h>
long i=0;
main()
{ 
 EA=1; //Enable EA bit
 ET0=1; //Enable Timer 0
 TMOD=0x00; //Use Timer 0, Mode 0
 TH0=(8192-1000)/32; //Count 1ms
 TL0=(8192-1000)%32;
 TR0=1; //Start Timer 0
 while(1);
} 
void T0_int(void) interrupt 1
{
 TH0=(8192-1000)/32;
 TL0=(8192-1000)%32;
 //if i==30000,30000*1ms=30s
 if(++i==30000) 
 {
 P1=~0x01;
 }
}

Did I miss something or is there any way that can reduce this error?

Anindo Ghosh
50.8k8 gold badges108 silver badges205 bronze badges
asked Apr 4, 2013 at 3:48
\$\endgroup\$
2
  • \$\begingroup\$ I assume they're 16-bit counters, so shouldn't you have something more like TH0=(65536L-1000)/256; (with the same change elsewhere)? \$\endgroup\$ Commented Apr 4, 2013 at 4:01
  • \$\begingroup\$ Sorry I didn't make it clear, it's 13-bit counter. I'll edit my question. \$\endgroup\$ Commented Apr 4, 2013 at 4:11

2 Answers 2

4
\$\begingroup\$

I am no expert on this chip. Still, I see a common source of inaccuracy in your program: when the counter times out, the interrupt is activated, and some instructions after that you set the TL0, which makes the counter start to count down your 1ms again. Hence there is some dead time between each 1ms interval that is 'lost'. I am not sure this is enough to explain your 1s deviation but it could be.

There are various ways to reduce this 'lost' time:

  • experiment, measure, and adapt the value you assign to TH0 accordingly (duct tape development style)
  • exchange the TL0 and TH0 assignments (effect will be small)
  • (assuming the counter keeps running) instead of assigning a new value to TL0 you can update it (keeping the counts it has already accumulated): TL0 = TL0 - ((8192 - 1000) % 32 );

But the only real solution is to keep the timer running freely and be more intelligent with the counting of the timeouts.

answered Apr 4, 2013 at 6:45
\$\endgroup\$
1
  • \$\begingroup\$ Some chips have an extra register that contains the value that the timer should overflow. On AVR it is called "Output Compare Register". This would automate the TH0= and TL0= lines \$\endgroup\$ Commented Apr 4, 2013 at 19:23
0
\$\begingroup\$

++i and i++ are different.

  • i++ will return the value of i and then increment it
  • ++i will first increment the value stored in i and then return its value
answered Apr 5, 2013 at 3:08
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.