Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Counter0 и переполнение
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
azazelloAV
Не могу разобратся в простом коде, может кто просветит.

Код
unsigned long micros() {
unsigned long m;    
cli();
m = timer0_overflow_count;
t = TCNT0;  
if ((TIFR0 & _BV(TOV0)) && (t < 255))
        m++;
    
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}


Не пинайте только, код взят с библиотеки ардуино - функция получения времени в микросекундах.
Ну вот объясните, ну вот с чего, с чего они взяли что прерывание по переполнению (сам флаг) не будет между этими двумя строчками
Код
t = TCNT0;  
if ((TIFR0 &

Да и вообще, может кто подскажет как это сделать корректно, без потери точности
Непомнящий Евгений
cli() же...

и кстати, не вижу sei()
azazelloAV
Цитата(Непомнящий Евгений @ Jun 29 2012, 10:01) *
cli() же...

и кстати, не вижу sei()

Ну причем здесь cli()
Он запрещает выполнения прерывания, а не отменяет его. Они же смотят флаг
Код
if ((TIFR
- т.е. возникало ли оно.
А sei() нету... Ну не знаю, может Си все выходы функций через reti делает
Непомнящий Евгений
Если переполнение случилось после t = TCNT0, но до if, то t будет 255, ++m выполнена не будет

Цитата(azazelloAV @ Jun 29 2012, 11:09) *
А sei() нету... Ну не знаю, может Си все выходы функций через reti делает


нет, с чего вдруг. Только для прерываний.
azazelloAV
Цитата(Непомнящий Евгений @ Jun 29 2012, 10:18) *
Если переполнение случилось после t = TCNT0, но до if, то t будет 255, ++m выполнена не будет

Гм, логично. Спасибо большое. Пребольшое.

Цитата
нет, с чего вдруг. Только для прерываний.

Ну а собственно, а почему бы и нет. А может компилятор раздупляется. Не знаю. А вообще бог с ним - не текущая задача.
Непомнящий Евгений
Цитата(azazelloAV @ Jun 29 2012, 11:31) *
Ну а собственно, а почему бы и нет.


Ну потому что нет, такого не происходит sm.gif

Так что тут или ошбка или sei() дергается где-то в вызывающем коде.
azazelloAV
Цитата(Непомнящий Евгений @ Jun 29 2012, 10:35) *
Ну потому что нет, такого не происходит sm.gif

Так что тут или ошбка или sei() дергается где-то в вызывающем коде.

Наврядле в вызывающем коде, функция слишком универсальна, её напрямую дергают, привожу полный код
Код
unsigned long micros() {
    unsigned long m;
    uint8_t oldSREG = SREG, t;
    
    cli();
    m = timer0_overflow_count;
#if defined(TCNT0)
    t = TCNT0;
#elif defined(TCNT0L)
    t = TCNT0L;
#else
    #error TIMER 0 not defined
#endif

  
#ifdef TIFR0
    if ((TIFR0 & _BV(TOV0)) && (t < 255))
        m++;
#else
    if ((TIFR & _BV(TOV0)) && (t < 255))
        m++;
#endif

    SREG = oldSREG;
    
    return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

Кстати, опять вопрос возник, а что если прерывание произойдёт между
Код
m = timer0_overflow_count;
t = TCNT0;
Непомнящий Евгений
SREG = oldSREG; - восстанавливает состояние прерываний, так что все ок

Код
m = timer0_overflow_count;
// прерывание
t = TCNT0; // t = 0, флаг TOV0 стоит
if ((TIFR0 & _BV(TOV0)) && (t < 255))
        m++; // выполнится




azazelloAV
Цитата(Непомнящий Евгений @ Jun 29 2012, 10:46) *
SREG = oldSREG; - восстанавливает состояние прерываний, так что все ок

Долго думал. Ну в упор не вижу, ну не вижу зачем восстанавливать флаги прерываний. Где они нарушаются?
Просвети, ибо ещё не дошёл до прозрачного понимания, а как известно, всё легкое очень сложно, пока конечно не поймёшь его.
_Артём_
Цитата(azazelloAV @ Jun 29 2012, 16:30) *
Где они нарушаются?


Код
uint8_t oldSREG = SREG;// сохранение статуса (с установленным или сброшенным флагом разрешения прерываний)
cli(); // сброс I в SREG - здесь "они нарушаются"
// код

SREG = oldSREG;// восcтановление SREG


Цитата(azazelloAV @ Jun 29 2012, 16:30) *
Ну в упор не вижу, ну не вижу зачем восстанавливать флаги прерываний.

Например в IAR AVR такая функция реализуется через ключевое слово __monitor - во время работы такой функции гарантировано не возникнут прерывания, а на выходе из неё восстановится статус с битом I (каким бы он не был до вызова функции).
azazelloAV
Цитата(_Артём_ @ Jun 29 2012, 16:57) *
[code]uint8_t oldSREG = SREG;// сохранение статуса (с установленным или сброшенным флагом разрешения прерываний)
cli(); // сброс I в SREG - здесь "они нарушаются"


Всё. Туплю. Искал там, где не должно быть. Просто ещё не перевёл в подсознание некоторые вещи. Спасибо за терпение и примитивные вопросы.


Ещё раз спасибо тем кто помог, теперь всё стало стройно и понятно.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.