Home > Mobile >  Controlling Timer0 in ATmega328p
Controlling Timer0 in ATmega328p

Time:01-31

I'm trying to create a blocking delay for the ATmega328p for my arduino uno R3. but I'm running into problems with my function.

I am not sure if it has something to do with my clock source. I set it as 8 MHz at the top of my script, but the problem persists.

#define F_CPU 8000000UL

Here's a snip of my delay function, it's configured for a 10 ms delay at 8 MHz and uses a delayTime counter to create a longer delay

/* 
 * Function to instantiate timer operations 
 */
void makeDelay(int delayTime){
  // Call the timer for delayTime successively
  //  resulting in delay of (configured delay) * timerDelay
  while(delayTime > 0){
    /* Set the TCNT reg for 10ms @ 8 MHz */
    TCNT0 = 0xB2;
    
    // Define the mode and prescaler values
    TCCR0A = 0x00;  // Normal mode
    TCCR0B = 0x05;  //  prescaler = 1024

    // loop until overflow
    while( (TIFR0 & (1 << TOV0) == 0) );

    // Stop the timer
    TCCR0B = 0;

    // clear the overflow
    TIFR0 = 0x01;

    // decrement the counter
    delayTime--;
  }
}

Any advice would be appreciated.

CodePudding user response:

In your program this waiting condition is wrong:

(TIFR0 & (1 << TOV0) == 0)

Operator == has higher precedence than &. (1 << TOV0) == 0 is evaluated first and it is always false. Thus TIFR0 & 0 is always false too. Rewrite the condition as

((TIFR0 & (1 << TOV0)) == 0)

or

((TIFR0 & _BV(TOV0)) == 0)

You can use following formula to calculate TCCNT0 register value for milliseconds:

Nticks = 256 - ms*F_CPU/1000/prescaler

As Timer0 is used by Arduino runtime library, you should disable it at first.

Entire sketch may be like this:

#define MS2TICKS(ms) (256 - (ms)*(F_CPU/1000)/1024)

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);

  TCCR0B = 0;    // Stop timer
  TIMSK0 = 0;    // Disable timer interrupts
  TCCR0A = 0;    // Normal mode
  TIFR0  = ~0;   // Clear all interrupt flags
}

void my_delay()
{
  TCNT0 = MS2TICKS(10);
  TCCR0B = 0x05;       // Enable timer with prescaler 1024

  while ((TIFR0 & _BV(TOV0)) == 0);

  TCCR0B = 0;         // Stop Timer0
  TIFR0 = _BV(TOV0);  // Clear overflow flag
}

void loop()
{
  digitalWrite(LED_BUILTIN, HIGH);
  my_delay();
  digitalWrite(LED_BUILTIN, LOW);
  my_delay();
}

It generates 10 ms pulses with 10 ms pauses on LED output.

  • Related