Рейтинговые книги
Читем онлайн Занимательная электроника - Юрий Ревич

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 120 121 122 123 124 125 126 127 128 ... 152

* * *

Обратите внимание, что оператор reti (окончание обработки прерывания) при обработке прерывания таймера встречается дважды — это вполне нормальный прием, когда подпрограмма разветвляется. Можно, конечно, и пометить последний оператор reti меткой, и тогда текст процедуры стал бы неотличим от первого варианта, но так будет корректнее.

Обратите также внимание на форму записи ldi temp, (1 << TOIE1). Поскольку бит, обозначаемый как TOIE1, в регистре TIMSK имеет номер 7, то эта запись эквивалентна записи ldi temp,0b10000000 — можно писать и так, и так, и еще кучей разных способов. Например, для запуска таймера с коэффициентом 1/64 требуется, как видно из текста программы, установить младшие два бита регистра TCCR1B. Здесь мы устанавливаем их в temp напрямую, но поскольку эти биты называются CS11 и CS10, то можно записать так:

ldi temp, (1 << CS11) I (1 << CS10)

или даже так:

ldi temp, (3 << CS10)

Подробно этот способ записи приведен в описании AVR-ассемблера на сайте Atmel[35].

* * *

Подробности

В этой программе есть один тонкий момент, связанный с загрузкой счетных регистров таймера. При чтении и записи 16-разрядных регистров Timer 1 их содержимое может измениться в промежутке между чтением или записью отдельных 8-разрядных «половинок» (ведь, например, в данном случае таймер продолжает считать, пока идет обработка прерывания). Потому в 16-разрядных таймерах AVR предусмотрен специальный механизм чтения и записи таких регистров. При записи первым загружается значение старшего байта, которое автоматически помещается в некий (недоступный для программиста) буферный регистр. Затем, когда поступает команда на запись младшего байта, оба значения объединяются, и запись производится одновременно в обе «половинки» 16-разрядного регистра. Наоборот, при чтении первым должен быть прочитан младший байт, при этом значение старшего автоматически фиксируется помещением в тот же буферный регистр, и при следующей операции чтения старшего байта его значение извлекается оттуда. Таким образом и при чтении значения оба байта соответствуют одному и тому же моменту времени.

Повторим: для того, чтобы манипуляции со счетными регистрами были успешными, при чтении необходимо сначала прочесть младший байт 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 они реализуются, как говорится, «с полпинка». Здесь же мы покажем пример того, как можно отсчитывать время, что называется, «в лоб», — это же решение годится и для индикации любых значений (например, показаний каких-нибудь датчиков).

1 ... 120 121 122 123 124 125 126 127 128 ... 152
На этой странице вы можете бесплатно читать книгу Занимательная электроника - Юрий Ревич бесплатно.

Оставить комментарий