Измерение временных интервалов

Представляю наработки по измерению длительности импульса и периода последовательности импульсов. Вообще, это довольно востребованная тема. В первую очередь на основании представленных наработок напрашивается реализовать частотомер, который в свою очередь, перерастает в массу устройств, как то: металлоискатели, измерители индуктивностей, ёмкостей, ESR, и пр. Кроме того сейчас в продаже имеются различные преобразователи (напряжение/ток/давление — частота), где представленные функции могут найти применение. Генератор импульсов я реализую на ATtiny2313. Быстренько набросаю исходник:


Контроллер тактирую от кварца 20 МГц (в принципе это не важно). Использую «неправильные» задержки стандартной библиотеки (имеется в виду «неправильные» в плане оптимальности реализации оных с помощью таймеров), однако для данного примера это совершенно не критично. Непосредственно измеритель реализую на ATmega128 kit — она у меня под рукой. Рассмотрим процесс измерения длительности импульса.
На верхнем осциллограмме синим цветом показан график зависимости значения счётного регистра TCNT1 от времени счёта (для удобства время я обозначил периодами переполнения OverflowC). Значение TCNT1 инкрементируется от  нуля до максимального значения 65535 (чёрный пунктир), затем следует сброс в ноль и периодический повтор n раз (см. вершины «треугольников) .  На нижней осциллограмме показан импульс длительностью Т,  приходящий на вход захвата ICR1 счётчика T1 (PD4)  с нашего вновь испечённого генератора (хотя можно подать с любого генератора). Сначала настраиваем прерывание по захвату по нарастающему фронту. По этому фронту запоминаем значение счётчика TCNT1 = EdgeR. Затем перестраиваем прерывание по захвату по ниспадающему фронту. По нему  запоминаем значение TCNT1 = EdgeF. Между этими моментами времени могут произойти (если длительность импульса больше периода переполнения таймера 1)  n переполнений таймера 1. Зная время переполнения таймера, а также длительность такта счёта tckl легко вычисляем значение длительности импульса по формуле:
Tpulse = EdgeF(tckl) — EdgeR(tckl) + 65536OverflowC(tckl);
или, упростив выражение:
Tpulse = tckl(EdgeF — EdgeR + 65536OverflowC);

Период последовательности импульсов измеряется так же

только прерывание по захвату настроено постоянно по нарастающему фронту.

Очевидно, что минимальная длительность импульса, которую сможет обработать данная реализация функции будет меньше времени выполнения  действий в обработчике прерывания по захвату. Симуляция в AVRStudio отмеряла 49 тактов, т.е для 8 МГц — это 6,12 мкс, что и подтверждается практикой — минимальное значение длительности импульса, которое правильно вычисляется — 7 мкс (см. фото).

Если сделать измеритель на контроллере с частотой 20 МГц (максимальная для AVR mega), то минимальная обрабатываемая длительность будет уже 2,45 мкс, т.к такт — 50 нс * 49 = 2,45 мкс. Но это цифры для ДАННОЙ реализации — на ассемблере будет, конечно немного лучше. Если необходимо измерять меньшие временные интервалы, нужно воспользоваться внешними управляемыми делителями. Но это уже другая история.
В архиве исходник. Понятное дело, что исходник нужно править в зависимости от поставленных задач.

Запись опубликована в рубрике Микроконтроллерный конструктор с метками , . Добавьте в закладки постоянную ссылку.

13 комментариев: Измерение временных интервалов

  1. Саша говорит:

    а дальше?

  2. s_black говорит:

    Что «дальше»?

  3. Саша говорит:

    продолжение б хотелось — например частотомер, измеритель индуктивности

  4. s_black говорит:

    Не всё сразу 🙂 Процесс идёт.

  5. naperon говорит:

    Написано «Период последовательности импульсов изменяется так же»
    А разве период изменяется?

  6. s_black говорит:

    🙂 Измеряется, конечно. Очепятка получилась — уже исправил.

  7. гость говорит:

    Опять одна и та же, кочующая с одного сайта на другой, ошибка. Вес переменной OverflowC равен 65536!
    Tpulse = tckl(|EdgeF — EdgeR| + 65536OverflowC) — более строгое выражение
    «…минимальная длительность импульса, которую сможет обработать данная реализация функции будет меньше??? (больше!!!) времени выполнения действий в обработчике прерывания по захвату.» Извините.

  8. s_black говорит:

    Здравствуйте гость!
    1. Материалы моего сайта ни с какого сайта не скопипащены — всё пишу сам. Если на что-то ссылаюсь, то обязательно указываю.
    2. В данной статье основой примера послужили материалы книги автора Ю.А. Шпак «Программирование на языке Си AVR и PIC микроконтроллеров». стр. 168
    3. Насчёт веса 65536 согласен — провтыкал (((.
    4. Насчёт «минимальной длительности…» хорошенько подумайте и поймёте, что Вы ошиблись.
    5. Извиняться не нужно — одно дело делаем)))
    Удачи, коллега!

  9. akl говорит:

    Здравствуйте.
    1,2. Виноват, нечетко выразился. Имелось ввиду, что эта ошибка (65535 вместо 65536, а также 255 вместо 256) слишком распространенная.
    4. «хорошенько подумайте и поймёте, что Вы ошиблись.» Возвращаю.
    Удачи, коллега!

  10. дЕНИС говорит:

    не работает измеритель периода. и вообще вы учли что EdgeF<EdgeR а наоборот видимо нет… а при выводе на дисплей этих значений они постоянно плывут,а должны изменяться только при захватах по нар.фронту как тут задумано,и почему то разница между ними постоянно одинакова

  11. s_black говорит:

    Почему обязательно EdgeF < EdgeR ? Оно может быть и меньше, и больше, и равно. Просто если так будет, то добавка к произведению будет отрицательная, т.е вычитание. Мне трудно так, навскидку, сказать, почему у Вас не работает. Ещё раз посмотрите внимательно исходник и монтаж. Схема и прошивка неоднократно проверены - непроверенных мною конструкций я сайт не выкладываю.

  12. Антон говорит:

    А зачем в выражении
    PulseClocks = ((unsigned long)EdgeF - (unsigned long)EdgeR + ((unsigned long)OverflowC <>3;//вычисляем длительность импульса

    Все переменные умножаются на unsigned long

  13. s_black говорит:

    Это называется «приведение типов». Почитайте в любом учебнике по Си. Удачи!

Добавить комментарий

Ваш e-mail не будет опубликован.