Радиолюбительские схемы на счетчиках. Счётчик импульсов с памятью на микроконтроллере Счетчик кругов электронный простая схема

Счетчик импульсов — это последовательностное цифровое устройство, обеспечивающее хранение слова информации и выполнение над ним микрооперации счета, заключающейся в изменении значения числа в счетчике на 1. По существу счетчик представляет собой совокупность соединенных определенным образом триггеров. Основной параметр счетчика — модуль счета. Это максимальное число единичных сигналов, которое может быть сосчитано счетчиком. Счетчики обозначают через СТ (от англ. counter).

Счетчики импульсов классифицируют

● по модулю счета:
. двоично-десятичные;
. двоичные;
. с произвольным постоянным модулем счета;
. с переменным модулем счета;
. по направлению счета:
. суммирующие;
. вычитающие;
. реверсивные;
● по способу формирования внутренних связей:
. с последовательным переносом;
. с параллельным переносом;
. с комбинированным переносом;
. кольцевые.

Суммирующий счетчик импульсов

Рассмотрим суммирующий счетчик (рис. 3.67, а ). Такой счетчик построен на четырех JK-триггерах, которые при наличии на обоих входах логического сигнала «1» переключаются в моменты появления на входах синхронизации отрицательных перепадов напряжения.

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

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

Трехразрядный вычитающий счетчик с последовательным переносом

Рассмотрим трехразрядный вычитающий счетчик с последовательным переносом, схема и временные диаграммы работы которого приведены на рис. 3.68.
{xtypo_quote}В счетчике используются три JK-триггера, каждый из которых работает в режиме Т-триггера (триггера со счетным входом).{/xtypo_quote}

На входы J и К каждого триггера поданы логические 1, поэтому по приходу заднего фронта импульса, подаваемого на его вход синхронизации С, каждый триггер изменяет предыдущее состояние. Вначале сигналы на выходах всех триггеров равны 1. Это соответствует хранению в счетчике двоичного числа 111 или десятичного числа 7. После окончания первого импульса F первый триггер изменяет состояние: сигнал Q 1 станет равным 0, a ¯ Q 1 − 1.

Остальные триггеры при этом свое состояние не изменяют. После окончания второго импульса синхронизации первый триггер вновь изменяет свое состояние, переходя в состояние 1, (Q x = 0). Это обеспечивает изменение состояния второго триггера (второй триггер изменяет состояние с некоторой задержкой по отношению к окончанию второго импульса синхронизации, так как для его опрокидывания необходимо время, соответствующее времени срабатывания его самого и первого триггера).

После первого импульса F счетчик хранит состояние 11О. Дальнейшее изменение состояния счетчика происходит аналогично изложенному выше. После состояния 000 счетчик вновь переходит в состояние 111.

Трехразрядный самоостанавливающийся вычитающий счетчик с последовательным переносом

Рассмотрим трехразрядный самоостанавливающийся вычитающий счетчик с последовательным переносом (рис. 3.69).

После перехода счетчика в состояние 000 на выходах всех триггеров возникает сигнал логического 0, который подается через логический элемент ИЛИ на входы J и К первого триггера, после чего этот триггер выходит из режима Т-триггера и перестает реагировать на импульсы F.

Трехразрядный реверсивный счетчик с последовательным переносом

Рассмотрим трехразрядный реверсивный счетчик с последовательным переносом (рис. 3.70).

В режиме вычитания входные сигналы должны подаваться на вход Т в. На вход Т с при этом подается сигнал логического 0. Пусть все триггеры находятся в состоянии 111. Когда первый сигнал поступает на вход Т в, на входе Т первого триггера появляется логическая 1, и он изменяет свое состояние. После этого на его инверсном входе возникает сигнал логической 1. При поступлении второго импульса на вход Т в на входе второго триггера появится логическая 1, поэтому второй триггер изменит свое состояние (первый триггер также изменит свое состояние по приходу второго импульса). Дальнейшее изменение состояния происходит аналогично. В режиме сложения счетчик работает аналогично 4-разрядному суммирующему счетчику. При этом сигнал подается на вход Т с. На вход Т в подается логический 0.
В качестве примера рассмотрим микросхемы реверсивных счетчиков (рис: 3.71) с параллельным переносом серии 155 (ТТЛ):
● ИЕ6 — двоично-десятичный реверсивный счетчик;
● ИЕ7 — двоичный реверсивный счетчик.

Направление счета определяется тем, на какой вывод (5 или 4) подаются импульсы. Входы 1, 9, 10, 15 — информационные, а вход 11 используется для предварительной записи. Эти 5 входов позволяют осуществить предварительную запись в счетчик (предустановку). Для этого нужно подать соответствующие данные на информационные входы, а затем подать импульс записи низкого уровня на вход 11, и счетчик запомнит число. Вход 14 — вход установки О при подаче высокого уровня напряжения. Для построения счетчиков большей разрядности используются выходы прямого и обратного переноса (выводы 12 и 13 соответственно). С вывода 12 сигнал должен подаваться на вход прямого счета следующего каскада, а с 13 — на вход обратного счета.

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

Итак, исходя из полученного в предыдущем разговоре опыта, мы выяснили один из главных параметров счетчика – разрядность. Для того, чтобы счетчик смог считать до 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 в двоичном счислении и подать импульс записи на вход С.

Все знают для чего существует микрокалькулятор,но оказывается кроме математических вычислений он способен и на многое другое. Обратите внимание, если нажать кнопку «1», затем «+» и далее нажимать «=», то с каждым нажатием на кнопку «=» число на дисплее будет увеличиваться на единицу. Чем не цифровой счетчик?

Если к кнопке «=» подпаять два проводка, их можно будет использовать как вход счетчика, например, счетчика витков для намоточного станка. И ведь, счетчик может быть и реверсивным, для этого нужно сначала набрать на дисплее число, например, число витков катушки, а затем нажать кнопку « - », и кнопку «1». Теперь при каждом нажатии на «=» число будет уменьшаться на единицу.

Однако, нужен датчик. Самый простой вариант, - геркон (рис.1). Геркон проводами подключаем параллельно кнопке «=», сам геркон стоит на неподвижной части намоточного станка, а магнит закрепим на подвижной, так что бы за один оборот катушки магнит один раз проходил возле геркона, вызывая его замыкание.

Вот и все. Нужно намотать катушку, делаем «1+» и далее с каждым оборотом, то есть, с каждым витком показания дисплея будут увеличиваться на единицу. Нужно отмотать катушку, - набираем на дисплее микрокалькулятора число витков катушки, и делаем «-1», далее с каждым оборотом размотки катушки показания дисплея будут уменьшаться на единицу.

Рис.1. Схема подключения геркона к калькулятору.

А, предположим, нужно измерить большое расстояние, например, длину дороги, размер земельного участка, длину маршрута. Берем обычный велосипед. Правильно, - на вилке крепим неметаллический кронштейн с герконом, а магнит закрепляем на одной из спиц велосипедного колеса. Затем, измеряем длину окружности колеса, и выраженную её в метрах, например, получилась длина окружности колеса 1,45 метра, так и набираем «1,45+», после чего с каждым оборотом колеса показания дисплея будут увеличиваться на 1,45 метра, и в результате на дисплее будет видно пройденное велосипедом расстояние в метрах.

Если есть неисправный китайский кварцевый будильник (обычно механизм у них очень не долговечный, а вот электронная плата весьма надежна), можно взять от него плату и по схеме показанной на рисунке 2 сделать из неё и калькулятора секундомер.

Питание на плату будильника поступает через параметрический стабилизатор на светодиоде HL1 (светодиод должен быть с прямым напряжением 1,4-1,7V, например, красный АЛ307) и резисторе R2.

Импульсы формируются из импульсов управления шаговым двигателем часового механизма (катушки должны быть отключены, плата используется самостоятельно). Эти импульсы через диоды VD1 и VD2 поступают на базу транзистора VТ1. Напряжение питания платы будильника всего 1,6V, при этом уровни импульсов на выходах для шагового двигателя еще ниже.

Чтобы схема нормально работала, необходимы диоды с низким уровнем прямого напряжения, такие как ВАТ85, или германиевые.

Эти импульсы поступают на транзисторный ключ на VТ1 и VТ2. В коллекторной цепи VТ2 включена обмотка маломощного реле К1, контакты которого подключены параллельно кнопке «=» микрокалькулятора. Когда есть питание +5V контакты реле К1 будут замыкаться с частотой 1 Гц.

Чтобы запустить секундомер нужно предварительно сделать действие «1+», затем выключателем S1 включить питание схемы формирователя импульсов. Теперь с каждой секундой показания дисплея будут увеличиваться на единицу.

Чтобы остановить счет достаточно выключить питание формирователя импульсов выключателем S1.

Чтобы был счет на уменьшение, нужно сначала набрать на дисплее микрокалькулятора исходное число секунд, а потом сделать действие «-1» и включить питание формирователя импульсов выключателем S1. Теперь с каждой секундой показания дисплея будут убывать на единицу, и по ним можно будет судить, сколько времени осталось до некоторого события.

Рис.2. Схема превращения китайского бодульника в секундомер.

Рис.3. Схема счетчика пересечений ИК-луча с применением калькулятора.

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

Принципиальная схема ИК-датчика отражения для работы с микрокалькулятором показана на рисунке 3.

Генератор ИК-сигнала выполнен на микросхеме А1 типа «555» (интегральный таймер) Он представляет собой генератор импульсов частотой 38 кГц, на выходе которого включен через ключ инфракрасный светодиод. Частота генерации зависит от цепи C1-R1, при налаживании подбором резистора R1 нужно установить на выходе микросхемы (вывод 3) частоту близкую к 38 кГц. Светодиод HL1 помещают с одной стороны прохода, надев на него непрозрачную трубку, которая должна быть точно направлена на фотоприемник.

Фотоприемник выполнен на микросхеме HF1 - это стандартный интегральный фотоприемник типа TSOP4838 для систем дистанционного управления телевизоров и другой домашней техники. Когда на этот фотоприемник попадает луч от HL1, на его выходе - ноль. При отсутствии луча -единица.

Таким образом, между HL1 и HF1 ничего нет - контакты реле К1 разомкнуты, а в момент прохождения какого-либо объекта - контакты реле замыкаются. Если на микрокалькуляторе сделать действие «1+», то с каждым прохождением объекта между HL1 и HF1 показания дисплея микрокалькулятора будут увеличиваться на единицу, и по ним можно будет судить, сколько коробок отгружено или сколько человек вошло.

Крюков М.Б. РК-2016-01.

Счетчики электрических импульсов

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

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

Счетчики электрических импульсов имеются как в ТТЛ, так и в КМОП сериях. В качестве примера счетчика ТТЛ рассмотрим микросхему К155ИЕ5. Функциональная схема счетчика К155ИЕ5 приведена на рисунке 1.51,а, а его условное обозначение на принципиальных схемах на рисунке 1.51,б. Счетчик К155ИЕ5 имеет фактически два счетчика: с коэффициентом пересчета два (вход С0 и выход Q 0) и с коэффициентом пересчета восемь (вход С1 и выходы Q 1, Q 2, Q 3). Счетчик с коэффициентом пересчета шестнадцать легко получается, если соединить выход Q 0 с входом С1, а импульсы подавать на вход С0. Временная диаграмма работы такого счетчика приведена на рисунке 1.52.

На рисунке 1.53 приведены схемы подключения, изменяющие коэффициент пересчета счетчика К155ИЕ5. Выходы счетчика Q 0, Q 1, Q 2, Q 3 имеют соответственно весовые коэффициенты 1, 2, 4, 8. Соединив выходы Q 1, Q 2 с входами установки счетчика в нуль, получим счетчик с коэффициентом пересчета шесть (рис. 1.53,а). На рисунке 1.53,б показана схема подключения для получения коэффициента пересчета десять, а на рисунке 1.53,в – двенадцать. Однако в схемах, приведенных на рисунках 1.53,а – в, отсутствует возможность установки счетчиков в нулевое состояние.

На рисунках 1.54,а, б приведены соответственно счетчики с коэффициентами пересчета шесть и семь, в которых предусмотрен вход установки счетчика в нулевое состояние. Анализ работы схем, приведенных на рисунках 1.53 – 1.54, показывает, что для получения заданного коэффициента пересчета соединяют с входами логического элемента И те выходы счетчика, весовые коэффициенты которых в сумме дают необходимый коэффициент пересчета.

В таблице1.3 приведены состояния на выходах счетчика с коэффициентом пересчета десять после поступления каждого очередного импульса, причем счетчик предварительно был установлен в нулевое состояние.

Рассмотрим некоторые из счетчиков КМОП серии. На рисунке 1.55 приведено условное обозначение микросхемы К561ИЕ8 – десятичного счетчика с дешифратором. Микросхема имеет вход установки в нулевое состояние R , вход для подачи счетных импульсов положительной полярности CP и вход для подачи счетных импульсов отрицательной полярности CN .

Переключение счетчика происходит по спадам импульсов положительной полярности на входе CP , при этом на входе CN должна быть логическая единица. Переключение счетчика будет происходить по спадам импульсов отрицательной полярности на входе CN , если на входе CP логический нуль. На одном из десяти выходов счетчика всегда присутствует логическая единица. Установка счетчика в нуль происходит при подаче на вход R логической единицы. При установке счетчика в нулевое состояние на выходе «0» установится логическая единица, а на всех остальных выходах – логические нули. Микросхемы К561ИЕ8 можно объединять в многоразрядные счетчики с последовательным переносом, соединяя выход переноса предыдущей микросхемы с входом CN последующей. На рисунке 1.56 приведена схема многоразрядного счетчика на микросхемах К561ИЕ10.

Промышленностью выпускаются счетчики для электронных часов. Рассмотрим некоторые из них. На рисунке 1.57 приведено условное обозначение микросхемы К176ИЕ3, а на рисунке 1.58 – микросхемы К176ИЕ4. На этих рисунках выходы микросхем показаны для стандартного обозначения сегментов индикатора, приведенного на рисунке 1.59. Эти микросхемы отличаются друг от друга коэффициентом пересчета. Коэффициент пересчета микросхемы К176ИЕ3 равен шести, а коэффициент пересчета микросхемы К176ИЕ4 равен десяти. Установка в нуль рассматриваемых счетчиков осуществляется подачей сигнала логической единицы на вход R . Переключение триггеров счетчика происходит по спаду положительных импульсов на входе С. Микросхемы имеют выход переноса р (вывод 2), к которому подключается обычно вход следующего счетчика. Спад напряжения на этом выходе формируется в момент перехода счетчика из состояния 9 в состояние 0. Микросхемы различаются сигналами на выводе 3. Для микросхемы К176ИЕ3 на выводе 3 появляется логическая единица при установке счетчика в состояние 2, а для микросхемы К176ИЕ4 – в состояние 4. Это необходимо для обнуления показаний часов в 24 часа.

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

На рисунке 1.60 приведена схема подключения люминесцентного индикатора к выходам микросхемы К176ИЕ4. Подключение индикатора к выходам микросхемы К176ИЕ3 будет аналогичным.

Схемы подключения светодиодных индикаторов к выходам микросхемы 176ИЕ4 приведены на рисунках 1.61,а и 1.61,б. На входе S устанавливается логический нуль для индикаторов с общим катодом и логическая единица для индикаторов с общим анодом.

Описание микросхем К176ИЕ5, К176ИЕ12, К176ИЕ13, К176ИЕ17, К176ИЕ18, К176ИД2, К176ИД3 и их применение в электронных часах можно найти в . Микросхемы К176ИЕ12, К176ИЕ13, К176ИЕ17, К176ИЕ18 допускают напряжение питания от 3 до 15 В.

Часто при работе микроконтроллерного устройства есть необходимость отсчитывать «антропоморфное» время – сколько долей секунды светиться светодиоду, максимальный промежуток времени 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 микросекунд для переменной-счетчика. Ибо, как оказалось, иногда одной миллисекунды не хватает.