Занимательная электроника — страница 106 из 128

Повторим: для того, чтобы манипуляции со счетными регистрами были успешными, при чтении необходимо сначала прочесть младший байт TCNTxL, потом старший TCNTxH, при записи сначала записать старший байт TCNTxH, потом младший TCNTxL. Аналогичное правило действует для всех 16-разрядных регистров Timer 1, которые мы будем рассматривать далее, за исключением регистров управления TCCR1A и TCCR1B, которые по сути есть два раздельных регистра, а не один.

* * *

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


Прерывание таймера по сравнению

Способ отсчета времени с помощью прерывания таймера по сравнению более понятен и удобен, чем с предзагрузкой значений в счетный регистр, — хотя бы потому, что число, с которым сравнивается содержимое счетных регистров, можно загружать только один раз. Если потом запустить таймер, то больше об этом можно не думать — все будет происходить автоматически. Поскольку в Tiny2313 и большинстве моделей Mega (если не во всех) все таймеры, в том числе и 8-разрядные, имеют такой режим (в «классических» его имел только 16-разрядный Timer 1), то применение его тем более целесообразно.

* * *

Подробности

Прерывание по сравнению происходит в момент, когда счетчик досчитывает до наперед заданного значения, хранящегося в специальном регистре сравнения. Есть одна тонкость, связанная с этим режимом. Входной тактовый сигнал счетчика обычно делится в соответствии с заданным коэффициентом деления (в наших примерах это 1/64). Поэтому в нашем случае каждое состояние счетчика остается неизменным в течение 64 тактов процессора. Так в какой именно момент возникает прерывание — сразу, как только счетчик досчитал до заданного значения, или в момент, когда это заданное значение в счетчике должно уже смениться следующим? Если предположить, что в AVR все устроено, как на рис. 16.13, в, то имеет место первый случай — счетчик начинает новый отсчет с первого системного такта сразу после совпадения величин. Тогда состояния счетчика получаются неравноправными: все они длятся по 64 системных такта (в соответствии с выставленным коэффициентом предделителя), кроме последнего, который длится один системный такт независимо от коэффициента деления. Так это было устроено в «классической» серии AVR. А вот для счетчиков семейств Меда и Tiny все иначе: там событие совпадения наступает по последнему такту при совпадении, в момент, когда состояние счетчика должно уже смениться. Поэтому, если вы зададите в регистрах сравнения, к примеру, число 2, то при коэффициенте деления 1/64 Timer 1 в МК AT90S2313 отсчитает до возникновения прерывания 129 системных тактов (или примерно 2 такта входной частоты счетчика), а в МК ATtiny2313 — 192 системных такта (ровно 3 такта входной частоты). Таким образом, в первом случае коэффициент деления входной частоты таймера в режиме сравнения равен установленному числу N плюс один такт системного генератора, а во втором — числу N + 1.

* * *

Причем в этом режиме можно упростить программу предельно — один из выводов контроллера (при прерывании с применением регистра сравнения А это OC1A — вывод 15 для 2313) можно включить в режим автоматического переключения в момент совпадения, без дополнительного программного управления. Если больше ничего в момент совпадения делать не требуется, не нужно даже будет включать прерывание — переключение вывода происходит аппаратно. Нам здесь это не подходит, т. к. светодиод двухцветный, и все равно необходимо переключать две линии одновременно, а вот в следующей главе мы эту возможность используем.

Для того чтобы установить режим сравнения, нужно вместо прерывания по переполнению разрешить прерывание по сравнению А (бит OCIE1A в регистре TIMSK), a также установить значение в регистрах сравнения (OCR1AH и OCR1AL), с которым будет сравниваться содержимое счетчика. Нетрудно догадаться, что для цикла счета в полсекунды оно равно вычисленному нами ранее значению 31 250. При записи в эти регистры нужно помнить то, что было сказано ранее про обращение с 16-разрядными регистрами в таймерах.

Есть в этом деле и еще один нюанс. Что будет происходить с таймером после того, как значения в счетных регистрах и регистрах сравнения станут одинаковыми (кроме того, что произойдет прерывание)? Ясно, что тут могут быть варианты: таймер может продолжить счет, обнулиться, установиться в какое-то наперед заданное значение и т. п. Это поведение настраивается — для выбора режима обнуления (чтобы после сравнения таймер пришел бы в исходное состояние) следует установить бит WGM12 (в «классической» версии МК он назывался CTC1) — бит номер 3 в регистре TCCR1B.

Программа с учетом всего сказанного будет выглядеть таким образом:





Естественно, значение, загружаемое в регистры сравнения OCR1AH: OCR1AL, необязательно должно быть равно в точности 31 250. Это дает удобный способ для точной подстройки интервала времени, который может иметь определенный разброс из-за неточностей используемого кварца. Но мы займемся этим уже в следующей главе.

ГЛАВА 20Изобретаем велосипед

Настольные часы и термометр-барометр на микроконтроллере


— В таком случае, купите мне, сударь, часы, — попросил Планше.

— Возьми вот эти, — сказал Атос, со свойственной ему беспечной щедростью отдавая Планше свои часы.

А. Дюма. Три мушкетера


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

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


Часы со счетом времени на МК

Часы мы сделаем на основе светодиодных индикаторов — поскольку схема все равно будет потреблять довольно много, то так или иначе потребуется сетевой источник питания, и слепые ЖК-индикаторы ставить нет особого смысла. Также договоримся, что секунды мы не показываем (в настольных часах этого никто и не делает, заменяя их отсчет миганием разделительной точки или двоеточия).

Для выбора МК из предлагаемых фирмой Atmel просто подсчитаем, сколько нам требуется выводов. Во-первых, надо управлять четырьмя разрядами индикации (ЧЧ: ММ). Это мы будем делать в режиме динамической индикации, когда в каждый отдельный момент времени напряжение питания подается только на один разряд индикаторов, и в это же время на сегменты, которые все соединены между собой параллельно, подается код, соответствующий именно этому разряду. При четырех разрядах непосредственное управление предполагает 74 = 28 задействованных выводов, а динамическое — всего 7 + 4 = 11.

Затем нам надо засвечивать разделительный символ — в часах это традиционно двоеточие. Наконец, часы нужно устанавливать. Для этого минимально необходимы две кнопки (включение режима установки и собственно установка). Итого получилось по минимуму 14 выводов.

Остановимся на знакомом нам МК ATtiny2313 — он выпускается в 20-выводном корпусе (см. рис. 19.2), в котором 5 выводов занято под системные нужды (два питания, Reset и два вывода для подключения кварца). Итого нам остается на все про все 15 выводов, что нас устраивает (выводы для программирования тоже задействуем). Мы даже вроде бы получаем один резервный вывод, но далее увидим, что на самом деле под все желательные дополнительные функции выводов нам будет не хватать, и придется изворачиваться (конечно, можно остановиться на ATmega8, у которого 28 выводов корпуса, но мы делаем схему в учебных целях, и тут дефицит даже полезнее).


Общее построение схемы

Теперь общая схема. Выбираем индикаторы большого размера (с цифрой 1 дюйм, или 25,4 мм высотой), с общим анодом, т. е. типа SA10, если ориентироваться на продукцию Kingbright. Лично я предпочитаю желтое свечение (например, SC10-21Y), но это не имеет значения. Так как падение напряжения у них может достигать 4 В, то от того же питания, что требует МК (5 В), питать их нельзя, поэтому нам потребуется два питания: одно стабилизированное +5 В и второе нестабилизированное (пусть будет +12 В). Управлять разрядами индикаторов мы будем от транзисторных ключей с преобразованием уровня (ког