реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Counter0 и переполнение
azazelloAV
сообщение Jun 29 2012, 06:54
Сообщение #1





Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554



Не могу разобратся в простом коде, может кто просветит.

Код
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 &

Да и вообще, может кто подскажет как это сделать корректно, без потери точности

Сообщение отредактировал azazelloAV - Jun 29 2012, 06:56
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jun 29 2012, 07:01
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



cli() же...

и кстати, не вижу sei()
Go to the top of the page
 
+Quote Post
azazelloAV
сообщение Jun 29 2012, 07:09
Сообщение #3





Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554



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

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

Ну причем здесь cli()
Он запрещает выполнения прерывания, а не отменяет его. Они же смотят флаг
Код
if ((TIFR
- т.е. возникало ли оно.
А sei() нету... Ну не знаю, может Си все выходы функций через reti делает
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jun 29 2012, 07:18
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Если переполнение случилось после t = TCNT0, но до if, то t будет 255, ++m выполнена не будет

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


нет, с чего вдруг. Только для прерываний.
Go to the top of the page
 
+Quote Post
azazelloAV
сообщение Jun 29 2012, 07:31
Сообщение #5





Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554



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

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

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

Ну а собственно, а почему бы и нет. А может компилятор раздупляется. Не знаю. А вообще бог с ним - не текущая задача.

Сообщение отредактировал azazelloAV - Jun 29 2012, 07:32
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jun 29 2012, 07:35
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(azazelloAV @ Jun 29 2012, 11:31) *
Ну а собственно, а почему бы и нет.


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

Так что тут или ошбка или sei() дергается где-то в вызывающем коде.
Go to the top of the page
 
+Quote Post
azazelloAV
сообщение Jun 29 2012, 07:43
Сообщение #7





Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554



Цитата(Непомнящий Евгений @ 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;
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Jun 29 2012, 07:46
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



SREG = oldSREG; - восстанавливает состояние прерываний, так что все ок

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




Go to the top of the page
 
+Quote Post
azazelloAV
сообщение Jun 29 2012, 13:30
Сообщение #9





Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554



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

Долго думал. Ну в упор не вижу, ну не вижу зачем восстанавливать флаги прерываний. Где они нарушаются?
Просвети, ибо ещё не дошёл до прозрачного понимания, а как известно, всё легкое очень сложно, пока конечно не поймёшь его.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jun 29 2012, 13:57
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(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 (каким бы он не был до вызова функции).
Go to the top of the page
 
+Quote Post
azazelloAV
сообщение Jun 29 2012, 14:16
Сообщение #11





Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554



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


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


Ещё раз спасибо тем кто помог, теперь всё стало стройно и понятно.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 20:21
Рейтинг@Mail.ru


Страница сгенерированна за 0.01418 секунд с 7
ELECTRONIX ©2004-2016