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.