Наверняка, я не первый кто с этой проблемой сталкивался, подскажите, пожалуйста, какие есть варианты решения. Заранее очень благодарен.
Длительность периода в реальном времени
В одной из задач возникла необходимость измерять длительность временного промежутка между повторяющимися событиями в реальном времени. Для этого планирую использоваться таймер с функцией захвата. Однако возникла следующая проблема: длительность измеряемого временного промежутка может быть больше, чем полный счёт таймера от 0 до 65535. Разумное решение — сделать программное расширение таймеру, но тогда возникает другая проблема: момент фиксации времени события (осуществляемый таймером автоматически) и момент чтения этого времени (аппаратной части и программной) отличаются. Между этими двумя моментами времени может произойти переполнение таймера, в результате программная и аппаратная части временного штампа события окажутся рассинхронизированы.
Наверняка, я не первый кто с этой проблемой сталкивался, подскажите, пожалуйста, какие есть варианты решения. Заранее очень благодарен.
Наверняка, я не первый кто с этой проблемой сталкивался, подскажите, пожалуйста, какие есть варианты решения. Заранее очень благодарен.
- Реклама
Использовать прерывание при переполнении. Количество_прерываний * 65536 + TCNTx.
Docendo discimus
- Сообщения: 289
- Зарегистрирован: Чт ноя 06, 2014 13:09:06
B@R5uk,
Мои рассуждения: Приоритет CAPTURE выше чем OVERFLOW (все AVRы не просматривал, на mege8 так), т.е
1) если влетели в ОVEFLOW, инкрементируем программный счетчик и выходим из обработчика.
2) если влетели в CAPTURE, читаем ICR, читаем Overflow Flag (флаг переполнения). Если флаг переполнения не стоит, то проблем нет. Если флаг переполнения стоит, то возникает неопределенность о которой Вы говорите (если я правильно понял), но она легко решается: если считанный ICR "болшой", то CAPTURE возникло до переполнения, если "маленький", то после переполнения, которое еще не обработано.
Мои рассуждения: Приоритет CAPTURE выше чем OVERFLOW (все AVRы не просматривал, на mege8 так), т.е
1) если влетели в ОVEFLOW, инкрементируем программный счетчик и выходим из обработчика.
2) если влетели в CAPTURE, читаем ICR, читаем Overflow Flag (флаг переполнения). Если флаг переполнения не стоит, то проблем нет. Если флаг переполнения стоит, то возникает неопределенность о которой Вы говорите (если я правильно понял), но она легко решается: если считанный ICR "болшой", то CAPTURE возникло до переполнения, если "маленький", то после переполнения, которое еще не обработано.
viiv, что означает "большой" или "маленький" ? Это "сколько в граммах" ?
Единственное решение при неатомарных ситуациях - запрет другим потокам модифицировать данные. В данном случае - это останов таймера на время его чтения. Потеряются некоторые такты, но зато вероятность нарваться на неприятности сводится к нулю.
Есть ещё вариант. Поле чтения таймера, прочитать флаг его переполнения. Если он взведён (переполнение было) - сбрасываем его (чтобы не влететь в overflow) и прибавляем к считанному значению 65536.
Единственное решение при неатомарных ситуациях - запрет другим потокам модифицировать данные. В данном случае - это останов таймера на время его чтения. Потеряются некоторые такты, но зато вероятность нарваться на неприятности сводится к нулю.
Есть ещё вариант. Поле чтения таймера, прочитать флаг его переполнения. Если он взведён (переполнение было) - сбрасываем его (чтобы не влететь в overflow) и прибавляем к считанному значению 65536.
- Сообщения: 2406
- Зарегистрирован: Ср фев 23, 2011 12:12:31
Насколько нужна точность измерения? А если просто уменьшить частоту таймера? Т.е. те же 65535 будут набираться гораздо дольше, ровно во столько, во сколько будет ниже частота.
Глупый не задает вопросы. Глупый и так все знает.
- Реклама
- Сообщения: 289
- Зарегистрирован: Чт ноя 06, 2014 13:09:06
В предельном случае сравнить c 0x8000.Аlex писал(а):viiv, что означает "большой" или "маленький" ? Это "сколько в граммах" ?![]()
останавливать таймер незачем.Аlex писал(а): В данном случае - это останов таймера на время его чтения.
Я про это и писал, только просто добавть 65536 нельзя, так как при установленном флаге переполнения, это самое переполнение могло возникнуть как до CAPTURE так и после.Аlex писал(а): Есть ещё вариант. Поле чтения таймера, прочитать флаг его переполнения. Если он взведён (переполнение было) - сбрасываем его (чтобы не влететь в overflow) и прибавляем к считанному значению 65536.
Немного не допонял проблему в вопросе и поторопился с ответом. Оказывается, используют аппаратный захват.
B@R5uk, у Вас проблема надуманная, которой, на самом деле, не существует. Вы говорите о двух взаимоисключающих вещах.
Если вызвалось прерывание от события по захвату, а до этого не было прерывания по переполнению - значит переполнения вовсе не было, и можно смело читать захваченные данные и счётчик переполнений (он всё равно не обновится, пока мы не дойдём до обработчика переполнения). Если бы до захвата было переполнение таймера, Вы бы сначала влетели в обработку по переполнению, а потом уже по захвату.
B@R5uk, у Вас проблема надуманная, которой, на самом деле, не существует. Вы говорите о двух взаимоисключающих вещах.
Если вызвалось прерывание от события по захвату, а до этого не было прерывания по переполнению - значит переполнения вовсе не было, и можно смело читать захваченные данные и счётчик переполнений (он всё равно не обновится, пока мы не дойдём до обработчика переполнения). Если бы до захвата было переполнение таймера, Вы бы сначала влетели в обработку по переполнению, а потом уже по захвату.
- Сообщения: 289
- Зарегистрирован: Чт ноя 06, 2014 13:09:06
ИМХО это не верно. 1) прерывания могут быть запрещены, например, работает дгугой обработчик. Если при запрещенных прерываниях произошло два события (И CAPTURE и ОVRFLOW), то при разрешении прерываний вызовется обработчик с бОльшим приоритетом(CAPTURE), не зависимо от того, какое событие было раньше.Аlex писал(а): Если бы до захвата было переполнение таймера, Вы бы сначала влетели в обработку по переполнению, а потом уже по захвату.
Если бы у бабки был ... А если упадёт метеорит на МК, то он вообще не сможет ничего обрабатывать
Если знаем о такой проблеме, то нужно как то не допускать её возникновения, т.б. - стараться не запрещать в программе прерывания.
ЗЫ: Сравнение с 0x8000 - неудачное решение. Вы предлагаете все значения до 0x8000 считать переполнением таймера ?
Если знаем о такой проблеме, то нужно как то не допускать её возникновения, т.б. - стараться не запрещать в программе прерывания.
ЗЫ: Сравнение с 0x8000 - неудачное решение. Вы предлагаете все значения до 0x8000 считать переполнением таймера ?
- Сообщения: 289
- Зарегистрирован: Чт ноя 06, 2014 13:09:06
Мы же не знаем, что у ТС за задача. Может у него еще что-то работает. Что без прерываний с UART-ом и с другой переферией работать?Аlex писал(а): Если знаем о такой проблеме, то нужно как то не допускать её возникновения, т.б. - стараться не запрещать в программе прерывания.
Да и в AVR не все команды выполняются за 1 такт, есть и 2-х тактовые и трехтактовый, и четырехтактовые. выполнение команды - атомарное, т.е. не может "разорваться" вызовом прерывания.
Так что в пределе эти два события (CAPTURE и OVF) могут возникнуть и во премя выполнения одной ассемблерной команды.
Да, при установленном бите переполнения таймера и считанном ICR<0x8000 считать, что событие CAPTURE произошло после переполнения таймера, которое еще не обработано.Аlex писал(а):ЗЫ: Сравнение с 0x8000 - неудачное решение. Вы предлагаете все значения до 0x8000 считать переполнением таймера ?
О порогах можно подумать, может я чего не учел. Но разделить диапазон пополам пока сажется не таким уж плохим решением.
==============
ЗЫ. Уважаемый, Аlex, похоже топик-стартеру данный вопрос не очень-то интересен, так как никакой реакции от него нету. Идея озвучена, информации для размышления ТС есть. Бабушку с метеоритами обсуждать нет никакого желания.
Ну, это и называется программное расширение таймера. Со всеми вытекающими проблемами.pyzhman писал(а):Использовать прерывание при переполнении. Количество_прерываний * 65536 + TCNTx.
Думал про это. К сожалению, точность фиксирована, а период при любой частоте гарантированно может оказаться длиннее цикла таймера.AndTer писал(а):Насколько нужна точность измерения? А если просто уменьшить частоту таймера?
Весьма громкое утверждение. Хотя я тоже думал про остановку. Во-первых, по событию захвата таймер не останавливается, а именно в этот момент происходит чтение аппаратной части временного штампа (младших двух байт). К моменту обработки прерывания (или просто в цикле после проверки соответствующего флага), когда будет осуществляться чтение программной части временного штампа и появится возможность остановки таймера, уже может появиться рассинхрон. Во-вторых, ARV так устроена, что выключение таймера не выключает предделитель, который продолжает считать. В-третьих, отключение таймера приведёт к нарушению самого главного требования задачи — регистрации временных штампов событий в реальном времени.Аlex писал(а):Единственное решение при неатомарных ситуациях - запрет другим потокам модифицировать данные. В данном случае - это останов таймера на время его чтения.
Остальное почитал, требует осмысления. Я так понял единственная возможность решения проблемы — это положиться на приоритет прерываний?
Работа с USART есть. Вывод в цикле, а ввод придётся делать через прерывания. Цикл слишком длинный, чтобы закончить его обсчёт за время приёма двух байт подряд.viiv писал(а):Может у него еще что-то работает. Что без прерываний с UART-ом и с другой периферией работать?
Два прерывания - захват и переполнение.
В обработчике переполнении счетчик переполнений инкрементируется .
В захвате:
1. Сброс счетчика.
2. Если захваченный счет небольшой (например если не установлен старший бит захваченных данных), то проверяется флаг переполнения. Если флаг переполнения установлен, инкрементируется счетчик переполнений.
3. Вычиляете фактическое значение периода (если почему то затрытный расчет, то считается в основной программе).
4. Сброс флаг переполнения и счетчика переполнений.
В обработчике переполнении счетчик переполнений инкрементируется .
В захвате:
1. Сброс счетчика.
2. Если захваченный счет небольшой (например если не установлен старший бит захваченных данных), то проверяется флаг переполнения. Если флаг переполнения установлен, инкрементируется счетчик переполнений.
3. Вычиляете фактическое значение периода (если почему то затрытный расчет, то считается в основной программе).
4. Сброс флаг переполнения и счетчика переполнений.
Z_h_e, сбрасывать счётчик не годится, задержки между появлением события и его обработкой, в которой вы предлагаете проводить сброс, приведут к неконтролируемым добавкам (или вычитаниям) для временных штампов событий. То есть весь смысл слов "в реальном времени" потеряется.
Суммируя то, что обсуждали Аlex и viiv. Возможны следующие варианты развития событий.
Вариант А
1) Событие захвата;
2) Обработка события захвата;
3) Событие переполнения;
4) Обработка события переполнения.
В этом случае результат получается правильный.
Вариант Б
1) Событие переполнения;
2) Обработка события переполнения;
3) Событие захвата;
4) Обработка события захвата.
В этом случае результат получается тоже правильный.
Вариант В
1) Событие захвата;
2) Событие переполнения;
3) Обработка события захвата;
4) Обработка события переполнения.
Произошло некоторое наложение, но результат получается правильный.
Вариант Г
1) Событие захвата;
2) Событие переполнения;
3) Обработка события переполнения;
4) Обработка события захвата.
Из-за накладки результат получается неправильный. Программная часть временного штампа на единицу больше, чем надо.
Вариант Д
1) Событие переполнения;
2) Событие захвата;
3) Обработка события захвата;
4) Обработка события переполнения.
Как и в прошлом варианте результат получается неправильный. Но программная часть временного штампа на единицу меньше, чем надо.
Вариант Е
1) Событие переполнения;
2) Событие захвата;
3) Обработка события переполнения;
4) Обработка события захвата
Несмотря на накладку результат получается правильный.
Мне пока не совсем понятно, какие именно из этих вариантов можно исключить, тем более, что мнения участников выше по этому вопросу разошлись. Но в любом случае, в процедуре обработки события захвата необходимо каким-либо образом определять какой именно из вариантов имел место быть, внося при необходимости поправку плюс или минус один к программной части временного штампа.
Жаль, конечно, что проблема не имеет готового решения. Но надеюсь, что правильное решение планомерным подходом получится таки найти. Заранее спасибо всем участвующим за помощь.
Суммируя то, что обсуждали Аlex и viiv. Возможны следующие варианты развития событий.
Вариант А
1) Событие захвата;
2) Обработка события захвата;
3) Событие переполнения;
4) Обработка события переполнения.
В этом случае результат получается правильный.
Вариант Б
1) Событие переполнения;
2) Обработка события переполнения;
3) Событие захвата;
4) Обработка события захвата.
В этом случае результат получается тоже правильный.
Вариант В
1) Событие захвата;
2) Событие переполнения;
3) Обработка события захвата;
4) Обработка события переполнения.
Произошло некоторое наложение, но результат получается правильный.
Вариант Г
1) Событие захвата;
2) Событие переполнения;
3) Обработка события переполнения;
4) Обработка события захвата.
Из-за накладки результат получается неправильный. Программная часть временного штампа на единицу больше, чем надо.
Вариант Д
1) Событие переполнения;
2) Событие захвата;
3) Обработка события захвата;
4) Обработка события переполнения.
Как и в прошлом варианте результат получается неправильный. Но программная часть временного штампа на единицу меньше, чем надо.
Вариант Е
1) Событие переполнения;
2) Событие захвата;
3) Обработка события переполнения;
4) Обработка события захвата
Несмотря на накладку результат получается правильный.
Мне пока не совсем понятно, какие именно из этих вариантов можно исключить, тем более, что мнения участников выше по этому вопросу разошлись. Но в любом случае, в процедуре обработки события захвата необходимо каким-либо образом определять какой именно из вариантов имел место быть, внося при необходимости поправку плюс или минус один к программной части временного штампа.
Жаль, конечно, что проблема не имеет готового решения. Но надеюсь, что правильное решение планомерным подходом получится таки найти. Заранее спасибо всем участвующим за помощь.
Значит не сбрасывайте, но флаг переполнения в обработчике захвата все равно надо также проверять. Предложенный мной алгоритм должен работать.B@R5uk писал(а):сбрасывать счётчик не годится,
Этот вариант исключён.B@R5uk писал(а):Вариант Г
1) Событие захвата;
2) Событие переполнения;
3) Обработка события переполнения;
4) Обработка события захвата.
Из-за накладки результат получается неправильный. Программная часть временного штампа на единицу больше, чем надо.
Если событие захвата произойдёт раньше события переполнения, то программа по-любому сначала обработает захват, а потом уже переполнение.
А вот вариант Д:
вполне возможен. И ничего с этим не поделаешь.B@R5uk писал(а): 1) Событие переполнения;
2) Событие захвата;3) Обработка события захвата;
4) Обработка события переполнения.
Как и в прошлом варианте результат получается неправильный. Но программная часть временного штампа на единицу меньше, чем надо.
Берите другой проц, у которого есть, как минимум, 2 приоритета. Тогда, повесив переполнение на старший приоритет, Вы исключите ошибку.
Добавлено after 6 minutes 3 seconds:
Нельзя этого делать.Z_h_e писал(а):но флаг переполнения в обработчике захвата все равно надо также проверять
Если событие захвата произойдёт до переполнения, то, проверкой на переполнение в событии захвата, вы прибавите лишние 65536 попугаев.
Это тоже самое, что предложил viiv - проверять на 0x8000. Но то предложение, конечно же, ещё глупее...
Можно и нужно. Обратите внимание на важную составляющую алгоритма - проверка флага, если захваченные данные меньше половины максимума счетчика.Аlex писал(а):Нельзя этого делать.
Если событие захвата произойдёт до переполнения, то...
Но скорректировать алгоритм надо, сброс флага переполнения нужно делать не всегда, а только если захваченные данные также меньше половины. Это из-за того что счетчик не надо сбрасывать.
А, дак речь идёт о проверке уже захваченного значения. А я всё думаю, причём тут значение счётчика
Тогда да, какая то доля правды в этом есть...
Тогда да, какая то доля правды в этом есть...
А по мне - алгоритм полностью рабочий и решает задачу ТС. По крайней мере я не вижу адекватной ситуации, при которой он работать не будет.Аlex писал(а):Тогда да, какая то дол правды в этом есть...
Да, похоже, действительно, рабочий.
ЗЫ: Всем плюсики в карму, за хорошее решение
ЗЫ: Всем плюсики в карму, за хорошее решение
Как вариант - вырезка из старого проекта решавшего аналогичную задачу. Если ешё актуально.B@R5uk писал(а):...Наверняка, я не первый кто с этой проблемой сталкивался, подскажите, пожалуйста, какие есть варианты решения.



