Счетчик импульсов из часов. Простой счётчик числа оборотов - Конструкции простой сложности - Схемы для начинающих

Из типовых функциональных узлов цифровой техники нетрудно собрать электронный счетчик-секундомер, аналогичный тем, которые выпускаются для школьных физических кабинетов. В этих приборах используется счетно-импульсный метод измерения времени, который состоит в том, что измеряется число импульсов, период повторения которых известен. Подобные приборы содержат следующие основные узлы: генератор счетных импульсов, схему управления (в простейшем случае ее роль выполняет кнопка «Пуск»), двоично-десятичный счетчик, дешифраторы и индикаторы. Последние три узла образуют пересчетную декаду, моделирующую один десятичный разряд. Нужно заметить, что измерение времени счетно-импульсным методом сопровождается неизбежной ошибкой, равной единице счета. Связано это с тем, что прибор зафиксирует одинаковое число импульсов и, следовательно, покажет одинаковое время, если счет прекращен сразу же после поступления последнего импульса или перед самым поступлением предыдущего импульса. В этом случае ошибка примет наибольшее значение, равное времени между двумя соседними

Рис. 172. Пересчетная декада

импульсами. Если уменьшить период повторения импульсов и ввести дополнительные разряды счетчика, то можно в нужное число раз повысить точность измерения.

Одна декада счетчика-секундомера показана на рисунке 172. Она состоит из двоично-десятичного счетчика на дешифратора на и индикатора на неоновой лампе Для питания индикатора нужно высокое напряжение , поэтому по правилам техники безопасности прибором должен пользоваться руководитель. В схеме используется дешифратор, специально предназначенный для работы с высоковольтным индикатором. Вместо лампы можно использовать лампы других типов: рассчитанные на напряжение питания 200 В и силу тока индикации Микросхема состоит из триггера со счетным входом (вход и триггерного делителя на 5 (вход При соединении выхода счетного триггера (выхрд 1) с входом делителя образуется двоично-десятичный счетчик. Он реагирует на задний фронт положительного импульса или на отрицательный скачок напряжения, поданного на вход . В условных обозначениях счетный фронт иногда показывается в виде стрелки, направленной к Микросхеме, если она реагирует на положительный скачок напряжения, или стрелки, направленной от микросхемы, если она реагирует на отрицательный перепад напряжения.

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

устанавливается в нулевое состояние кнопкой «Уст. О», при этом на входы счетчика подается логическая 1. Затем переключателем выбирается источник счетных импульсов - им может быть или триггер, или мультивибратор. В режиме «счет механических замыканий» при последовательном нажатии и отпускании кнопки происходит двоично-десятичный счет и на индикаторе последовательно загораются цифры 1, 2, 3 и т. д. до цифры 9, затем загорается цифра 0 и счет повторяется. В режиме счета импульсов на вход счетчика поступают импульсы мультивибратора, собранного по уже известной схеме на рис. 168). Для измерения времени в секундах частота импульсов должна равняться 1 Гц. Она устанавливается переменным резистором и емкостью равной

Для получения многоразрядного двоично-десятичного счетчика включаются последовательно, т.е. выход первого соединяется со входом второго, выход второго соединяется со входом третьего и т. д. Для установки многоразрядного счетчика в нулевое состояние входы объединяются и подключаются к кнопке «Уст. 0».

Если, например, прибор предполагается использовать на уроках физики, то время нужно измерять в довольно широком диапазоне - от 0,001 до 100 с. Для этого генератор должен иметь частоту а счетчик должен состоять из пяти десятичных разрядов. При этом показания цифрового индикатора будут иметь следующий вид: 00,000; 00,001; 00,002 и т.д. до 99,999 с.

Область применения учебного счетчика-секундомера можно значительно расширить, если ввести в него два дополнительных устройства - блок бесконтактного управления и блок выдержек времени. Первый блок должен обеспечивать автоматическое и безинерционное включение и отключение прибора. Для этого можно использовать уже известную схему фотореле (рис. 76), выбрав нужную чувствительность и согласовав напряжения источников питания. В схеме управления должно быть два фотодатчика - один используется для включения, а другой для выключения счетчика-секундомера в моменты пересечения лучей движущимся телом. Зная расстояние между фотодатчиками и показания секундомера, легко вычислить скорость движения тела. В блоке-приставке используются два усилителя фототока. Их выходные сигналы управляют работой счетного триггера, один из выходов которого через транзисторный ключ соединен со входом секундомера.

Можно привести также другие примеры использования электронных счетчиков. Например, автомат, моделирующий игру «в кости», состоит уже рассмотренной декады на

И неоновой лампы управляемой импульсами мультивибратора (см. рис. 168, 172). Игроки поочередно нажимают кнопку прерывающую счет. Выигрывает тот, у кого индикатор покажет большее число. Момент остановки счетчика, как и момент остановки подбрасываемого кубика с точками от 1 до 6, определяется случайными причинами, поэтому счетная декада вместе с мультивибратором являются электронным датчиком случайных чисел. Приведем еще примеры ее использования в различных игровых ситуациях.

При проверке скорости реакции игроков резистором устанавливается определенная частота работы мультивибратора и скорость смены цифр индикатора (см. рис. 168 и 172). Участникам игры предлагается нажимать на кнопку мультивибратора каждый раз, как индикатор покажет определенную, заранее выбранную цифру. Выполнить поставленное условие тем сложнее, чем выше частота переключения. Первыми выбывают из игры наиболее медлительные, победителем становится игрок, обла дающий лучшей реакцией. В другом, более сложном варианте игры нужно продолжать нажатия кнопки в установленном судьей темпе после того, как исчезают показания индикатора. Для этого его закрывают механической шторкой или отключают кнопкой

Счетную декаду вместе с мультивибратором особенно удобно использовать в играх, если ее питание сделать автономным, т. е. не связанным с сетью. В этом случае используют семисегментный светодиодный индикатор управляемый дешифратором интегральной схемы . С этой микросхемой и индикатором мы уже знакомы (рис. 150, 163). Схемы мультивибратора и счетчика остаются неизменными. Схема датчика случайных чисел, работающего от источника с напряжением 5 В, показана на рисунке 173.

Примером более сложного устройства, работающего на основе электрического счетчика, является блок выдержки времени, или таймер. На рисунке 174 показана принципиальная схема таймера, позволяющего включать различную нагрузку на время от 0 до 999 с. Он состоит из трехразрядного десятичного счетчика, собранного на микросхеме трех дешифраторов на микросхеме мультивибратора и схемы управления на микросхеме а также микросхеме Источником счетных импульсов является мультивибратор, настроенный на частоту 1 Гц. Его импульсы подаются на вход трехразрядного десятичного счетчика. Двоичные коды с каждого разряда подаются на дешифраторы На их выходах последовательно пояезляются нулевые сигналы по мере поступления на входы

Рис. 173. Пересчетная декада со светодиодным индикатором

соответствующих двоичных кодов. Установка нужной выдержки времени осуществляется переключателями соединяющими выходы дешифраторов с элементами микросхемы Входы элементов И попарно соединены для получения элемента Переключателем устанавливаются единицы секунд, переключателем десятки секунд и переключателем сотни секунд. Если, например, переключатели соединяются с выводами 2, 3 и 7 дешифраторов, то на входах элемента ИЛИ-НЕ будут три 0 только в момент, когда счетчик зафиксирует 237 импульсов или пройдет промежуток времени, равный 237 секундам с момента начала счета. При этом на выходе элемента ИЛИ-НЕ появится сигнал 1. До этого момента при всех двоичных кодах счетчика на выходе логического элемента был нулевой сигнал.

Схема управления таймера работает следующим образом. Предварительно нажимается кнопка «Стоп», в результате RS-триггер, собранный по микросхеме устанавливается в нулевое состояние. С прямого выхода нулевой уровень напряжения подается на транзистор 1/77, в эмиттерную цепь которого включена обмотка электромагнитного реле. Транзистор и реле находятся в выключенном состоянии. Одновременно с этим на инверсном выходе 6 появляется высокий уровень, который служит сигналом сброса для счетчика. При нажатии кнопки «Пуск» RS-триггер переходит в единичное состояние, на прямом выходе 3 появляется. высокий уровень напряжения, достаточный для открывания транзистора 1/77 и срабатывания реле. Его контакты замыкают цепь питания нагрузки. Одновременно с этим

(кликните для просмотра скана)

нулевой уровень напряжения, снимаемый с инверсного выхода триггера, «открывает» счетчик. Счетчик работает до тех пор, пока на выходах дешифратора не появятся выходные сигналы, соответствующие набранному числу. В. этом случае, как уже говорилось, на выходе возникает единичный сигнал, который через инвертер подается на вход -триггера. Происходит его установка в нулевое состояние и, соответственно, выключение транзистора, электромагнитного реле и нагрузки. Счетчик устанавливается в нулевое состояние.

Таймер будет показывать текущее время в секундах, если к выходам дешифраторов подключить светодиоды. Отсчет времени станет более удобным, если двоично-десятичные коды счетчиков подать на дешифраторы работающие совместно с семи-сегментными индикаторами

видео работы устройства

Схема собрана на микроконтроллере PIC16F628A. Она может считать входные импульсы от 0 до 9999. Импульсы поступают на линию порта RA3 (кнопка SA1 активный уровень низкий). С каждым импульсом показания индикатора меняются на +1. После 999 импульса на индикаторе высвечивается 0 и загорается точка начала второй тысячи (правая по схеме) и т. д. Так счёт может продолжаться до значения 9999. После этого счёт останавливается. Кнопка SA3 (линия порта RА1) служит для сброса показаний в 0.

Схема счётчика импульсов с памятью на микроконтроллере

Изначально схема была изготовлена для работы с питанием от трёх пальчиковых батарей. Поэтому с целью экономии энергии в схему включена кнопка включения индикации для контроля состояния счётчика SA2 (линия порта RA4). Если в этой кнопке нет необходимости, её контакты можно закоротить. В схеме можно использовать подтягивающие резисторы в пределах от 1к до 10к. Биты конфигурации INTRC I/O и PWRTE установлены. При отключении питания показания счётчика в памяти контроллера сохраняются. При погашенном индикаторе схема остаётся работоспособной при снижении питания до 3,5 вольт. Практика показала, что заряда батареек хватает почти на неделю непрерывной работы схемы.


Печатная плата счётчика


Фото счетчика

Схема, прошивка МК и печатная плата в формате S-layuout в архиве (15кб) .

От администратора . Резисторы R1-R3 можно выбрать номиналом до 10К.

Как и триггеры, счетчики совсем необязательно составлять из логических элементов вручную – сегодняшняя промышленность выпускает самые разнообразные счетчики уже собранные в корпуса микросхем. В этой статье я не буду останавливаться на каждой микросхеме-счетчике отдельно (в этом нет необходимости, да и времени займет слишком много), а просто кратко рассажу на что можно рассчитывать, во время решения тех или иных задач цифровой схемотехники. Тех же, кого интересует конкретные типы микросхем-счетчиков, я могу отправить к своему далеко неполному справочнику по ТТЛ и КМОП микросхемам.

Итак, исходя из полученного в предыдущем разговоре опыта, мы выяснили один из главных параметров счетчика – разрядность. Для того, чтобы счетчик смог считать до 16 (с учетом нуля – это тоже число) нам понадобилось 4 разряда. Добавление каждого последующего разряда будет увеличивать возможности счетчика ровно вдвое. Таким образом, пятиразрядный счетчик сможет считать до 32, шести – до 64. Для вычислительной техники оптимальной разрядностью является разрядность, кратная четырем. Это не есть золотым правилом, но все же большинство счетчиков, дешифраторов, буферов и т.п. строятся четырех (до 16) или восьмиразрядными (до 256).

Но поскольку цифровая схемотехника не ограничивается одними ЭВМ, нередко требуются счетчики с самым различным коэффициентом счета: 3, 10, 12, 6 и т.д. К примеру, для построения схем счетчиков минут нам понадобится счетчик на 60, а его несложно получить, включив последовательно счетчик на 10 и счетчик на 6. Может нам понадобиться и большая разрядность. Для этих случаев, к примеру, в КМОП серии есть готовый 14-ти разрядный счетчик (К564ИЕ16), который состоит из 14-ти D-триггеров, включенных последовательно и каждый выход кроме 2 и 3-го выведен на отдельную ножку. Подавай на вход импульсы, подсчитывай и читай при необходимости показания счетчика в двоичном счислении:

К564ИЕ16

Для облегчения построения счетчиков нужной разрядности некоторые микросхемы могут содержать несколько отдельных счетчиков. Взглянем на К155ИЕ2 – двоично-десятичный счетчик (по-русски – «счетчик до 10, выводящий информацию в двоичном коде»):

Микросхема содержит 4 D- триггера, причем 1 триггер (одноразрядный счетчик – делитель на 2) собран отдельно – имеет свой вход (14) и свой выход (12). Остальные же 3 триггера собраны так, что делят входную частоту на 5. Для них вход – вывод 1, выходы 9, 8,11. Если нам нужен счетчик до 10, то просто соединяем выводы 1 и 12, подаем счетные импульсы на вывод 14 а с выводов12, 9, 8, 11 снимаем двоичный код, который будет увеличиваться до 10, после чего счетчики обнулятся и цикл повторится. Составной счетчик К155ИЕ2 не является исключением. Аналогичный состав имеет и, к примеру, К155ИЕ4 (счетчик до 2+6) или К155ИЕ5 (счетчик до 2+8):

Практически все счетчики имеют входы принудительного сброса в «0», а некоторые и входы установки на максимальное значение. Ну и напоследок я просто обязан сказать, что некоторые счетчики могут считать и туда и обратно! Это так называемые реверсивные счетчики, которые могут переключаться для счета как на увеличение (+1), так и на уменьшение (-1). Так умеет, к примеру, двоично-десятичный реверсивный счетчик К155ИЕ6:

При подаче импульсов на вход +1 счетчик будет считать вперед, импульсы на входе -1 будут уменьшать показания счетчика. Если при увеличении показаний счетчик переполнится (11 импульс), то прежде чем вернуться в ноль, он выдаст на вывод 12 сигнал «перенос», который можно подать на следующий счетчик для наращивания равзрядности. То же назначение и у вывода 13, но на нем импульс появится во время перехода счета через ноль при счете в обратном направлении.

Обратите внимание, что кроме входов сброса микросхема К155ИЕ6 имеет входы записи в нее произвольного числа (выводы 15, 1, 10, 9). Для этого достаточно установить на этих входах любое число 0 — 10 в двоичном счислении и подать импульс записи на вход С.

Конструкция выполнена только на одной микросхеме К561ИЕ16. Так как, для его правильной работы нужен внешний генератор тактовых импульсов, то в нашем случае мы его заменим простым мигающим светодиодом. Как только подадим напряжение питание на схему таймера, емкость С1 начнет заряжаться через резистор R2 поэтому на выводе 11 кратковременно появится логическая единица, сбрасывающая счетчик. Транзистор, подсоединенный к выходу счетчика, откроется и включит реле, которое через свои контакты подключит нагрузку.


Здесь используется второй триггер микросхемы К561ТМ2, который в первой схеме не задействован. Он включается последовательно первому триггеру образуя двухразрядный двоичный счетчик, отличающийся от «типового» только наличием цепи задержки R3-C2 в первом триггерном звене. Теперь состояние выходов триггеров будет меняться соответственно двоичному коду. При включении питания оба триггера устанавливаются в нулевое состояние, чтобы это происходило вход R второго триггера соединен с таким же входом первого. Теперь цепь C1-R2 действует на оба триггера, обнуляя их при подаче питания. С первым нажатием кнопки в единичное состояние устанавливается триггер D1.1, -включается лампа Н1.

Первый из описываемых далее счетчиков представляет собой генератор случайного числа. Его можно использовать для определения очередности ходов в различных игровых ситуациях, в качестве лототрона и др. В генераторе используются интегральные схемы серии К155. На элементах DD1.1 -DD1.4 интегральной схемы К155ЛН1 собран генератор прямоугольных импульсов с рабочей частотой порядка нескольких килогерц.


При нажатии на тумблер SB1 замыкаются контакты кнопки и импульсы с выхода генератора следуют на вход первого из 4 последовательно соединенных JK- триггеров. Их входы включены так, что JK-триггеры по сути работают в счетном режиме. Вход каждого триггера соединен с инверсным выходом предыдущего, поэтому все они переключаются с достаточно приличной частотой, в соответствие с ней вспыхивают и светодиоды HL1...HL4.

Этот процесс идет до тех пор, пока нажата SB1. Но как только ее отпускают, как все триггеры окажуться в каком-то устойчивом состоянии. При этом будут гореть только те светодиоды, которые подсоединены к выходам триггеров которые окажуться в нулевом состоянии 0.

Каждому светодиоду задается свой числовой эквивалент. Поэтому для определения выпавшей комбинации необходимо просуммировать числовые значения горящих светодиодов.

Схема генератора случайного числа настолько проста, что не требует никакой наладки и начинает работать сразу с подачей питания. Вместо JK-триггеров в конструкции можно применить двоичный счетчик К155ИЕ5.

Автомат обладает двумя идентичными каналами, каждый из которых содержит тактовый генератор на элементах DD1.1 -DD1.4 (DD2.1 - DD2.4), четырех разрядный двоичный счетчик DD3, DD5 (DD4, DD6), схемы управления на DD8.1, DD8.2 (DD8.3, DD8.4), узлы индикации DD10.1 (DD10.2).


Объединяет оба канала модуль контроля (DD7), реализующих формулу «исключающее ИЛИ». Логика работы DD7 очень проста: если на вход элемента приходят два одинаковых логических уровня, то на его выходе формируется уровень логического 0, иначе 1.

В момент включения питания и нажатия на кнопку «Сброс» (SB1) триггеры DD3...DD6 переключаются в единичное состояние и светодиоды тухнут. Параллельно на выходах DD8.1 и DD8.3 формируется логическая 1, разрешающая запуск тактовых генераторов. Импульсы с их выходов, следуют на триггеры и провоцируют их синхронное переключение. Вспыхивают и соответствующие светодиоды. Скоростью переключения последних можно упровлять сопротивлениями R1 и R2, расположенными в пультах игроков.

Если играющий, считая, что состояния светодиодов обоих каналов равнозначны, нажимает на кнопку SB2. Тогда на выходе элемента DD8 формируется логический ноль, запирающий генераторы и фиксирующий состояния триггеров. Уровень единицы, формируется на выходе DD8.2 и блокирует переключение триггера на DD8.3, DD8.4 и разрешая работу индикации. Благодаря этому можно выяснить, кто из двух играющих быстрее нажмет на кнопку.

Логические уровни с инверсных выходов триггеров следуют на узел контроля DD7.1 - DD7.4, где происходит сравнение. Если они равнозначны, то на выходах элементов узла контроля появляется уровень логического нуля.

Инвертируясь DD9.1- DD9.4, он вызывает возникновение высокого уровня на выходе схемы ИЛИ (VD1-VD4). Таким образом, обе единицы одновременно будут только на входе DD10.1. На его выходе формируется логический ноль и начинает гореть светодиод HL9 фиксирующей победу игрока, нажавшего на кнопку SB2.

Если при нажатии SB2 логические уровни были разными, то на выходе схемы ИЛИ формируется уровень нуля. При этом единичный уровень поступает только на вход DD10.2, и зажигание соответствуюшего светодиода фиксирующего победу другого игрока.

Аналогично схема будет вести себя и в случае если первой нажать кнопку SB3. Время переключения DD8.1 - DD8.4 достаточно низкое поэтому вероятность сбоя почти исключена.

Схема имеет узел автоматического отключения питания через полчаса, но при желании его можно отсоединить и раньше, коснувшись пальцем сенсора.

Для сборки конструкции необходимо семь транзисторов и три ИМС: К155ЛАЗ, и К155ИЕ8.

Приставка состоит из узла звукового сигнализатора на VT1, VT2 и DD1 - DD3 и узла коммутации питания на VT3-VT7.


Схема звукового сигнализатора состоитиз тактовый генератор на DD1.1, DD1.2 и VT1. Он генерирует прямоугольные импульсы с частотой следования около 1 Гц.

После включения питания тактовый генератор начинает посылать тактирующие импульсы, а импульс сброса, формируемый цепью R4, С2, сбрасывает счетчик и триггер, управляющий коэффициентом деления.

Уровень логической единицы, идет с шестого выхода триггера DD3.1, и блокирует диод VD1, включая тональный генератор на DD1.4 и транзисторе VT2. Параллельно импульсы, следуют на десятый вход элемента DD1.4 с тактового генератора частотой один Гц, включая и в отключая тональный генератор, формирующий прерывистый звуковой сигнал.

Кроме того уровень логической 1, идущий с выхода 6 триггера, задает коэффициент деления счетчика равный шестнадцати. После поступления на вход счетчика 17-го импульса на выходе шесть DD2 формируется положительный импульс, переключающий DD3.1 в единичное состояние. С выхода 6 низкий уровень этого триггера блокирует работу тонального генератора и устанавливает коэффициент деления счетчика 64. После прихода следующих 64 импульсов на выходе счетчика генерируется положительный импульс, переключающий триггер DD3.1 в нулевое состояние. Выходной сигнал триггера разрешает работу тонального генератора и устанавливает коэффициент деления равный шестнадцати. Таким образом, приставка через каждые 64 секунды генерирует прерывистый тональный звуковой сигнал длительностью 16 секунд. В таком режиме приставка может работать до выключения питания.

Питание схемы звуковой сигнализации происходит через «электронный выключатель» и устройство автоматической коммутации питания, на транзисторах VT3-VT7. Кроме того этот модуль, ограничивает ток, потребления приставки в дежурном режиме на уровне микроампер, что позволяет не использовать в конструкции механический выключатель питания.

Для включения приставки кратковременно замыкаем точки А и Б. При этом на базу VT3 через сопротивление R9 идет положительный потенциал напряжения и составной транзистор образованный на VT4-VT5 отпирается, обеспечивая ток делителя напряжения на резисторах R10, R11. Падение напряжения на R10 и участке коллектор - эмиттер VT5 отпирает составной транзистор VT6- VT7.

Напряжение питания через VT7 проходит на узел звуковой сигнализации. Параллельно через R6, R7 и участок коллектор - эмиттер VT3 заряжается емкость С4. За счет падения напряжения в цепи заряда емкости составной транзистор VT4-VT5 поддерживается открытым, обеспечивая работу составного транзистора VT6-VT7.

По мере заряда емкости С4 потенциал в точке R6, VD2, С4, R7 падает и при определенной величине составной транзистор VT4- VT5 запирается, заним и закрывается VT6-VT7, отключая цепь питания звуковой сигнализации.

Емкость С4 быстро разряжается и приставка переходит в спящий режим. Время работы задается сопротивлением R6 и емкостью С4 и для указанных номиналов время составляет 30 мин. Можно отключить питание и вручную, коснувшись сенсорных контактов E1, Е2.

Отрицательный потенциал напряжения через сопротивление поверхности кожи и R8 попадает на базу транзистора VT3, отпирая его. Напряжение на коллекторе резко падает и запирает составной транзистор VT4-VT5, который закрывает VT6, VT7.

Часто при работе микроконтроллерного устройства есть необходимость отсчитывать «антропоморфное» время – сколько долей секунды светиться светодиоду, максимальный промежуток времени double-click и т. д. В общем, отсчитывать не только нано- и микросекунды, но и десятки миллисекунд, а то и секунды, минуты и даже часы (боюсь сказать о сутках…).
В то же время в микроконтроллерах нередко нужно одновременно с этим иметь дело с микросекундами – периоды импульсов, антидребезговое ожидание и т. п.
Есть также устройства, которые работают непрерывно многие часы и даже сутки – авиационная техника, автомобильная, скважинные устройства (там речь идет иной раз о непрерывной работе несколько дней). В этих случаях недопустимо переполнение таймеров и 8-битных переменных.
Хотелось бы это все объединить в одно изящное и универсальное решение – иметь средство измерения времени с точностью до микросекунды, не переполняющееся несколько дней.
Почему бы и нет? Помучился я некоторое время и родил решение для 8-битных микроконтроллеров AVR. Для этого я задействовал 8-битный таймер-счетчик и 4х-байтную переменную. С PIC-ами и AT89 я сейчас не работаю, а с другими embedded-платформами не дружу. Впрочем, если читатели помогут – сделаю и для них.
Достоинства – код в высшей степени повторяемый (я уже 5-ое устройство с ним делаю); простота в работе (не используются прерывания для клиентской части работы); клиентская часть кода условно платформенно-независимая; в прерывании – одна операция суммирования (но, правда, для 4-хбайтной величины); нет внешнего устройства - таймера реального времени.
Недостаток я нашел один – занят один такой полезный и всегда нужный таймер…
Статья будет интересна в первую очередь начинающим - Америку я тут не открыл.

Теория

Итак, я имею в своем распоряжении устройство на основе Atmega16A с кварцем 12MHz. Берем его таймер-счетчик 0. Это восьмиразрядный таймер – нам и хватит. Почему? Считаем:
  1. берем 12 MHz от кварца и берем коэффициент деления на 8 – получаем частоту 1500 KHz;
  2. берем режим CTC (сброс при совпадении) и ставим прерывание на совпадение с 150 – получаем частоту срабатывания прерывания 10 KHz;
  3. на этом самом прерывании инкрементируем переменную (получается инкремент каждые 0.1 миллисекунды);
  4. если это беззнаковая 32х-битная величина, то она переполнится приблизительно после
    • 429496729.6 миллисекунд;
    • 42949.7 секунд;
    • 7158.3 минут;
    • 119.3 часов;
    • 4.97 суток.
Другими словами, такое решение мне создает таймер с точностью до 0.1 миллисекунды на (почти) 5 суток (надо тут, правда, учитывать, что реальные кварцы имеют погрешность - об это далее). А если еще анализировать значение собственно таймера 0 – он инкрементируется каждые 2/3 микросекунды – то можно получит счетчик с точностью до 0.67 микросекунды.
Хватит? Мне – за глаза. Используя счетчик по 0.1 миллисекунды, я в своих проектах:
  • считаю длительности свечения и пауз между ними светодиодов;
  • учитываю timeouts при работе с UART, USB;
  • задаю всевозможные ситуации в тестовом оборудовании – сложные пространственно-временнЫе комбинации;
  • выдерживаю заданные промежутки времени при опросе АЦП и прочих датчиков;
  • сообщаю компьютеру время своей (устройства) работы и с заданным интервалом времени передаю информацию;
  • с учетом счетчика до микросекунды я осуществляю антидребезговый контроль при нажатии клавиш, анализ импульсов в протяженных линиях.
И все это спокойно влазит В ОДИН КОНТРОЛЛЕР ATmega16! Причем это не Ассемблер, а межплатформенный Си! И никакого внешнего счетчика реального времени!
Неплохо, да?

Настройка для AVR

Как это все сделать в AVR?
Прежде всего, заводим внешнюю переменную, которую я называю «ДециМиллиСекунда»:
// в main.h typedef unsigned long dword; // беззнаковое 32х-битное целое extern volatile dword dmsec; // 0.1msec // в main.c volatile dword dmsec;
Как верно подметил @no-smoking, эта переменная должна быть volatile, чтобы ее компилятор не попытался оптимизировать.
Инициализацию этой переменной я делаю в функции:
dmsec = 0;
Далее я задаю режим работы таймера 0:
// . таймер 0 – 0.1msec Timer0_Mode (TIMER_Mode_CTC | TIMER0_Clk_8); Timer0_Cntr (149); Timer_Int (Timer0_Cmp);
При этом в каком-нибудь MCU_init.h объявляю все, что надо:
// в mcu_init.h #include // . TIMSK #define Timer0_Cmp (1 << 1) // совпадение таймера 0 // . TCCRn #define WGM1 (1 << 3) #define CS1 (1 << 1) // . источник сигнала для таймера 0 #define TIMER0_Clk_8 CS1 // предделитель 8 // . режим работы таймера #define TIMER_Mode_CTC WGM1 // CTC (сброс при совпадении) // . настройка таймера #define Timer_Int(Mode) TIMSK = (Mode) #define Timer0_Mode(Mode) TCCR0 = (Mode) #define Timer0_Cntr(Cntr) OCR0 = (Cntr)
Ну и далее, когда можно, разрешаю прерывания:
#asm ("SEI")
Осталось описать прерывание. Это проще, чем все предыдущее:
#include interrupt Timer0_Compare (void) { ++dmsec; }
Все, таймер описан, настроен и запущен!

Настройка для PIC

Вот что мне подсказали уважаемые PICоманы:

На пиках это легко повторяется при помощи модуля Timer2. Именно в нем есть аналогичная функция прерывания по совпадению.

PR2 = 75 - значение, при котором таймер обнулится и сгенерирует прерывание
T2CON.T2CKPS = 2 - прескалер 1:16
T2CON.T2OUTPS = 0 - без постскалера
T2CON.TMR2ON = on - таймер включен

IPR1.TMR2IP = 1 --высокоприоритетное прерывание
PIR1.TMR2IF = off --сбрасываем флаг прерывания
PIE1.TMR2IE = on --включаем прерывание по совпадению TMR2 и PR2
INTCON.GIE = on --включаем обработку прерываний

Как видно, прескалер тут в 2 раза больше, потому PR2 в 2 раза меньше.
Данные настройки будут генерировать прерывания с частотой 10 kHz при системной частоте в 48 MHz (на таймер идет Fosc/4) - стандартная частота для USB Full Speed.

Использование

Код для клиента этого таймера получается кросс-платформенным (если не считать обращения к значению таймера 0 в AVR).
Вот фрагмент кода обмена по USB:
#include "main.h" // тут переменная dmsec, next_USB_timeout #include "FT245R.h" // тут функции работы с модулем USB #include "..\Protocol.h" // тут протокол обмена микроконтроллер - компьютер // ** // ** Анализ пакетов по USB // ** void AnalyzeUSB (void) { #define RECEIVE_BYTE(B) while (!FT245R_IsToRead)\ { if (dmsec > end_analyze) return; }\ B = FT245_ReadByte (); #define RECEIVE_WORD(W) // аналогично для 2х байт #define RECEIVE_DWORD(W) // аналогично для 4х байт dword end_analyze, d; NewAnalyze: if (!FT245R_IsToRead) // нет пакетов? return; end_analyze = dmsec + max_USB_timeout; // timeout для текущего анализа next_USB_timeout = dmsec + MaxSilence_PC_DEV; // timeout для общего обмена RECEIVE_BYTE (b) // заголовок пакета switch (b) { case SetFullState: RECEIVE_DWORD (d); // читаем слово is_initialized = 1; // обрабатываем ChangeIndicator (); break; } // switch (pack) goto NewAnalyze; #undef RECEIVE_BYTE // отменяем #define #undef RECEIVE_WORD #undef RECEIVE_DWORD }
Макрофункции RECEIVE_BYTE, RECEIVE_WORD, RECEIVE_DWORD реализуют процедуры чтения с учетом timeout для данной фазы обмена. В итоге, если чего зависло на другой стороне, то микроконтроллер не впадет в «спячку». Обратите внимание – WatchDog не понадобился! И все благодаря переменной/константе max_USB_timeout, которая задает timeout с точностью до 0.1 миллисекунды.
Точно также реализуется анализ «тишины в эфире» переменной next_USB_timeout. Это позволяет микроконтроллеру 1) узнать, что компьютер куда-то исчез, 2) как-то об этом сигнализировать (в моем случае загорается светодиод «ошибка»). Константа/переменная MaxSilence_PC_DEV позволяет варьировать понятие «тишины» в широчайших пределах – от доли миллисекунды до нескольких суток.
Аналогично реализуются все остальные моменты.
Если же вам нужно использовать счетчик микросекунд, то там появляется функция сравнения:
#define GetUSec(A,B) { #asm ("CLI"); A = dmsec; B = TCNT0; #asm ("SEI"); } // ** // ** Разница во времени между событиями с точностью до 2/3usec // ** dword Difference (dword prev_dmsec, byte prev_usec) { dword cur_dmsec; byte cur_usec; dword dif; // . засекаем текущее время GetUSec (cur_dmsec, cur_usec); // вычисляем разницу dif = cur_dmsec - prev_dmsec; dif <<= 8; if (cur_usec < prev_usec) dif += 255 + (dword) cur_usec - prev_usec; else dif += cur_usec - prev_usec; return dif; }
Функции передается предыдущий момент времени – предыдущее значение dmsec и таймера 0.
Вначале мы макросом GetUSec останавливаем прерывания, чтобы в момент копирования не испортилось значение dmsec и счетчика. И копируем текущее время.
Далее мы приводим разницу во времени к формату 2/3 микросекунды с учетом переполнения.
Ну и возвращаем это время.
А далее мы это используем в обычном if для контроля антидребезга и прочих мероприятий. Только не забудьте также приостановить прерывания при засекании текущего момента времени – а лучше используйте макрос GetUSec.

Результаты

Этот таймер оказался для меня в высшей степени удобным решением. Думаю, он и вам пригодится. А применил я его в следующих своих проектах:
  • Коммутатор фехтовальных ситуаций . Это здоровенная плата пол на пол метра с тремя контроллерами - ATmega128 как центральный и ATmega64 как два вспомогательных (правая и левая стороны). Между тремя контроллерами и их компонентами нет гальванической связи - питание на основе ионисторов, связь через опторазвязки. Центральный контроллер заряжает группы одних ионисторов и питает в это время обе стороны от других ионисторов. Тут пришлось сделать многоступенчатый алгоритм коммутации всего этого с тем, чтобы минимизировать взаимосвязь. В частности, речь идет о слаженной работе 8 реле - тут работают таймеры на 3.3мсек (гарантированное время срабатывания реле). Ну и, собственно, обе стороны управляют 10 реле и еше с пол сотни мультиплексоров. Все это хозяйство работает с четко заданными временнЫми характеристиками (с точностью до 1 мсек, максимальные длительности - 6 секунд). Ну и, в конце концов, банальные timeout для USB, UART.
  • Датчик глубины . Здесь я решаю другую задачу (проект в работе). Имеются два проводника (многометровые), задающие ситуацию «сдвиг вверх на 1 см» и «сдвиг вниз на 1 см». Способов задания направления множество. В любом случае это определенные комбинации импульсов. С помощью этого таймера я определяю дребезг, длительность устойчивого импульса. С компьютера задается максимально допустимое время дребезга (10 микросекунд тут хватает), антидребезговое ожидание, минимальная/максимальная длительность импульса. Ну и есть режим отладки - датчик становится логическим анализатором. Это позволяет отлаживать работу линии и корректировать коэффициенты. Ну и опять же timeout, светодиоды.
  • Датчик аналоговых сигналов . Банальное 8-ми канальный АЦП. Здесь я использую таймер для выдерживания необходимых пауз.
Уважаемые хабрапользователи с других платформ могут мне подсказать код инициализации соответствующего таймера, а также правила доступа к нему - я это тут добавлю. Возможно, что для других платформ будет необходимо подобрать другие времена. Но в любом случае это должно быть нечто в пределах нескольких единиц микросекунд для самого таймера и нечто кратное 100 микросекунд для переменной-счетчика. Ибо, как оказалось, иногда одной миллисекунды не хватает.

 

Пожалуйста, поделитесь этим материалом в социальных сетях, если он оказался полезен!