Delay with timer/counter2 is too short

Hello all,

I’m trying to use the following delay functions (which I’ve copied from a sample) with my duemilanove.
The problem is that if I do a delay_ms(1000) it only waits 0.25ms.
I’ve tried to look at the Atmega docs and don’t understand the problem.
The “TCCR2B = (1<<CS21);” command should set the timer clock at 1MHz, right? So the code should work.
Any thoughts?

Here is the code (this is not the entire code, there are other SPI related stuff in there which I omitted) :

//General short delays
void delay_ms(uint16_t x)
{
for (; x > 0 ; x–)
delay_us(1000);
}

//General short delays
void delay_us(uint16_t x)
{
while(x > 256)
{
TIFR2 = (1<<TOV2); //Clear any interrupt flags on Timer2
TCNT2 = 0; //256 - 125 = 131 : Preload timer 2 for x clicks. Should be 1us per click
while( (TIFR2 & (1<<TOV2)) == 0);

x -= 256;
}

TIFR2 = (1<<TOV2); //Clear any interrupt flags on Timer2
TCNT2= 256 - x; //256 - 125 = 131 : Preload timer 2 for x clicks. Should be 1us per click
while( (TIFR2 & (1<<TOV2)) == 0);
}

void setup()
{
// initialize the serial communications:
Serial.begin(9600);
TCCR2B = (1<<CS21);

char count = 0;

while (1)
{
Serial.println(count, DEC);
delay_ms(1000);
count++;
}
}

I'm trying to use the following delay functions...

Why? What's wrong with delay and delayMicroseconds?

Nothing. These functions work correctly.

I did see a recommendation somewhere to use the timer2 for delays if one needs to do other stuff (instead of just busy waiting). Also, as I am having problems with my SPI communication to the BMA180 (for which this sample code was supplied), I want to know if that may be related to some kind of timing issues (and to generally understand the timing in the Atmega328).

Got it.

void setup()
{
...
  TCCR2B = (1<<CS21);

I strongly suggest that you set both TCCR2A and TCCR2B. Do not assume the configuration registers are the way you want them to be. Ideally, you should disable the timer first…

  TCCR2B = 0;
  TCCR2A = /* put code here to configure the timer*/;
  TCCR2B = /* put code here to configure and start the timer*/;

Thanks for the prompt reply.
I’ll try later and update on the result.

When I also zeroed TCCR2B I got a delay_ms(1000) of 0.5s.

Can this be explained by the fact that my Duemilanove is 16Mhz (and maybe the sample was taken from an 8Mhz one)?

Yes. The timers are driven from the processor clock. If the processor clock speed is doubled, the timers also run twice as fast.

So I can close the file on this one. Thanks Coding Badly for the tip.