|
|
  |
Counter0 и переполнение |
|
|
|
Jun 29 2012, 06:54
|
Группа: Новичок
Сообщений: 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
|
|
|
|
|
Jun 29 2012, 07:09
|
Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554

|
Цитата(Непомнящий Евгений @ Jun 29 2012, 10:01)  cli() же...
и кстати, не вижу sei() Ну причем здесь cli() Он запрещает выполнения прерывания, а не отменяет его. Они же смотят флаг Код if ((TIFR - т.е. возникало ли оно. А sei() нету... Ну не знаю, может Си все выходы функций через reti делает
|
|
|
|
|
Jun 29 2012, 07:18
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Если переполнение случилось после t = TCNT0, но до if, то t будет 255, ++m выполнена не будет Цитата(azazelloAV @ Jun 29 2012, 11:09)  А sei() нету... Ну не знаю, может Си все выходы функций через reti делает нет, с чего вдруг. Только для прерываний.
|
|
|
|
|
Jun 29 2012, 07:31
|
Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554

|
Цитата(Непомнящий Евгений @ Jun 29 2012, 10:18)  Если переполнение случилось после t = TCNT0, но до if, то t будет 255, ++m выполнена не будет Гм, логично. Спасибо большое. Пребольшое. Цитата нет, с чего вдруг. Только для прерываний. Ну а собственно, а почему бы и нет. А может компилятор раздупляется. Не знаю. А вообще бог с ним - не текущая задача.
Сообщение отредактировал azazelloAV - Jun 29 2012, 07:32
|
|
|
|
|
Jun 29 2012, 07:43
|
Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554

|
Цитата(Непомнящий Евгений @ Jun 29 2012, 10:35)  Ну потому что нет, такого не происходит  Так что тут или ошбка или 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;
|
|
|
|
|
Jun 29 2012, 07:46
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
SREG = oldSREG; - восстанавливает состояние прерываний, так что все ок Код m = timer0_overflow_count; // прерывание t = TCNT0; // t = 0, флаг TOV0 стоит if ((TIFR0 & _BV(TOV0)) && (t < 255)) m++; // выполнится
|
|
|
|
|
Jun 29 2012, 13:30
|
Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554

|
Цитата(Непомнящий Евгений @ Jun 29 2012, 10:46)  SREG = oldSREG; - восстанавливает состояние прерываний, так что все ок Долго думал. Ну в упор не вижу, ну не вижу зачем восстанавливать флаги прерываний. Где они нарушаются? Просвети, ибо ещё не дошёл до прозрачного понимания, а как известно, всё легкое очень сложно, пока конечно не поймёшь его.
|
|
|
|
|
Jun 29 2012, 13:57
|
Гуру
     
Группа: Свой
Сообщений: 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 (каким бы он не был до вызова функции).
|
|
|
|
|
Jun 29 2012, 14:16
|
Группа: Новичок
Сообщений: 6
Регистрация: 29-06-12
Пользователь №: 72 554

|
Цитата(_Артём_ @ Jun 29 2012, 16:57)  [code]uint8_t oldSREG = SREG;// сохранение статуса (с установленным или сброшенным флагом разрешения прерываний) cli(); // сброс I в SREG - здесь "они нарушаются" Всё. Туплю. Искал там, где не должно быть. Просто ещё не перевёл в подсознание некоторые вещи. Спасибо за терпение и примитивные вопросы. Ещё раз спасибо тем кто помог, теперь всё стало стройно и понятно.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|