Longer Time Delay When More Then One "while" Polling Instruction

323 views Asked by At

Microcontroller : ATmega328P in Arduino Uno
Clock Frequency : 16MHz

void timeDelay_CTC(float sec, unsigned char times)          //0.1 <= sec <= 4
{
    OCR1A = (sec / 0.000064f) - 1;
    TCCR1A = 0b00000000;
    TCCR1B = 0b00001101;
    for( unsigned char i = 1; i <= times; i++ )
    {
        while( (TIFR1 & (1<<OCF1A)) == 0 );
        TIFR1 |= (1<<OCF1A);
    }
    TCCR1A = 0;
    TCCR1B = 0;
}

The above function is used for calculating the number of time delay cycles and then implement it in CTC mode. It works well. Now, I want to write a similar function in normal mode. The folowing is the code.

void timeDelay_NORM(float sec, unsigned char times)
{
    unsigned int cycle = (sec / 0.000064f);
    TCNT1 = 65534 - cycle;
    TCNT1 = 49910;
    TCCR1A = 0b00000000;
    TCCR1B = 0b00000101;
    for( unsigned char x = 1; x <= 2; x++ )
    {
        while( (TIFR1 & (1<<TOV1)) == 0 );
        TIFR1 |= (1<<TOV1);
    }
    TCCR1A = 0;
    TCCR1B = 0;
}

However, the normal mode function with argument "times" > 1, the time delay will be much longer than expected. So, I tried the following code.

void timeDelay_NORM(float sec, unsigned char times)
{
    //unsigned int cycle = (sec / 0.000064f);
    //TCNT1 = 65534 - cycle;
    TCNT1 = 49910;                              //Cycles for 0.5sec
    TCCR1A = 0b00000000;
    TCCR1B = 0b00000101;
    //for( unsigned char x = 1; x <= 2; x++ )
    //{
        while( (TIFR1 & (1<<TOV1)) == 0 );      //Run 0.5sec two times to delay 1sec
        TIFR1 |= (1<<TOV1);
        while( (TIFR1 & (1<<TOV1)) == 0 );
        TIFR1 |= (1<<TOV1);
    //}
    TCCR1A = 0;
    TCCR1B = 0;
}

I found that when it run the following instruction 2 times, the time delay will be much longer than expected. It delay around 5s instead of 1s.

while( (TIFR1 & (1<<TOV1)) == 0 );
TIFR1 |= (1<<TOV1);

Can you teach me how to make it work? Or give me some hints.

Thank you for your help!

1

There are 1 answers

2
Rev On BEST ANSWER

You do not reset TCNT1 between the loop iterations.

On the first loop it will count (UINT16_MAX - 49910) cycles. After TOV1 is set, TCNT1 rolls over to 0 (overflow) and counts up all the way to UINT16_MAX which causes the longer delay.