Более длительная задержка, когда более одного во время опроса инструкции

Микроконтроллер: ATmega328P в Arduino Uno
Тактовая частота: 16 МГц

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;
}

Вышеупомянутая функция используется для расчета количества циклов временной задержки, а затем реализуется в режиме CTC. Это работает хорошо. Теперь я хочу написать аналогичную функцию в обычном режиме. Ниже приведен код.

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;
}

Однако для функции нормального режима с аргументом «times» > 1 задержка по времени будет намного больше, чем ожидалось. Итак, я попробовал следующий код.

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;
}

Я обнаружил, что при выполнении следующей инструкции 2 раза задержка по времени будет намного больше, чем ожидалось. Задержка составляет около 5 с вместо 1 с.

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

Можете ли вы научить меня, как заставить его работать? Или дайте мне пару советов.

Спасибо за помощь!


person Casper    schedule 13.11.2014    source источник


Ответы (1)


Вы не сбрасываете TCNT1 между итерациями цикла.

В первом цикле будет подсчитано (UINT16_MAX - 49910) циклов. После установки TOV1 TCNT1 сбрасывается на 0 (переполнение) и ведет счет до UINT16_MAX, что вызывает более длительную задержку.

person Rev    schedule 13.11.2014
comment
Большое спасибо. После добавления TCNT1 = cycle_NORM; после инструкции while функция работает хорошо. =] Я хочу спросить, почему не нужно делать то же самое в режиме CTC? OCR1A будет автоматически очищен после установки бита флага? - person Casper; 13.11.2014
comment
@CasperLi: Да, CTC на самом деле означает Clear on Timer Compare, что указывает именно на это. Значение счетчика очищается при сравнении :) - person Rev; 13.11.2014