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

Схема на рис. 19.4 составлена в предположении, что от цифровой индикации мы отказались, и порт С, занятый ранее сегментами, у нас освободился. Младшие разряды этого порта мы и задействуем для управления линейкой светодиодов. Остальные соединения на схеме не показаны (см. рис. 15.2). Ради простоты индикацию температуры опустим. Вывод Е (разрешения) микросхем управляется старшим разрядом четырехбитового числа с вывода РСЗ. Логика К155ИД11 такова, что если на Е уровень логического нуля, то работа микросхемы DD2 запрещена, если «1»— запрещается работа микросхемы DD3. Так как во втором случае на выходе Р верхней микросхемы уровень логического нуля, то нижняя микросхема зажжет все светодиоды. Ограничительных резисторов для светодиодов не требуется, они встроены в микросхему, хотя яркость в этом случае может быть непредсказуемой (а вот К1003ПП1 «умеет», в том числе, управлять яркостью).



Рис. 19.4.Схема шкальной индикации для измерителя давления и температуры


Программу придется переделать таким образом. Расчеты физических величин нам уже не требуются, но вот преобразование масштабов провести придется. Потому на подготовительном этапе нужно выяснить значение коэффициентов К и Z таких, чтобы по уравнению зависимости выходного кода от значений, прочитанных из АЦП, приведенному в главе 15, у нас значение выходного кода, равного нулю, соответствовало 710 мм рт. ст. Таким образом, коэффициент Z, который нужно вычесть из кода АЦП, будет равен значению кода при 710 мм рт. ст., или, как несложно рассчитать, примерно 840 (с учетом того, что датчик работает не с нуля давления, см. главу 15).

Значение же, соответствующее 785 мм рт. ст., должно соответствовать какому-нибудь «круглому» двоичному числу (не очень важно, какому, т. к. мы потом его все равно урежем до 4 бит). Из характеристик датчика мы знаем, что максимальная шкала АЦП в 10 бит соответствует давлению около 850 мм рт. ст. Нас же интересует шкала всего в 75 мм (от 710 до 785), что составит около 90 единиц кода. Потому мы смело можем выбрать, например, 128 для верхнего предела шкалы (что соответствует 7 битам). Тогда коэффициент К (который ранее составлял 0,895 мм рт. ст. на единицу кода), теперь будет примерно 128/90 = 1,422. Оба коэффициента, естественно, должны уточняться при калибровке.

Сама процедура расчета не нуждается в переделке (меняются только значения коэффициентов, остальное можно оставить, как есть, хотя если внимательно ее рассмотрите, то увидите, что есть резервы для сокращения необходимых ресурсов, например, задействованных регистров). Единственное, что следует учесть— вычисленные значения хранятся в регистрах AregH: AregL (см. Приложение 5), но 7-битовый результат, конечно окажется только в регистре AregL, а регистр АregH всегда будет равен нулю. После расчета, вместо преобразования В двоично-десятичный КОД (rcall bin2BCD16), мы должны записать:

lsr AregL

lsr AregL

lsr AregL  ;теперь результат усечен до 4 бит

in temp.PortC  ;значение разрядов PortC в temp

cbr temp,15  ;обнуляем младшие 4 бита

ori temp,AregL  ;устанавливаем младшие 4 бита

out PortC,temp  ;выводим

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

В заключение отмечу, что в сконструированном мной однажды приборе для некоей яхты была задействована более сложная и более красивая шкальная индикация: при значении параметра ниже некоторого порога индикаторы меняли цвет на красный, который сменялся зеленым при повышении параметра до нормы. Естественно, готовые микросхемы (типа К155ИД11 и подобные) такую задачу решить не позволяют, и пришлось городить всю процедуру внутри контроллера, управляя светодиодами напрямую. Задачу изменения цвета удалось решить, применив двухвыводные двухцветные LED (L117), которые обоими выводами коммутировались к выводам МК (для одного цвета действовало сочетание состояний 0 и 1, для другого — 1 и 0, а погашен LED оказывался при одинаковом состоянии выводов).


Подстройка внешних часов

Кварцевые резонаторы имеют весьма высокую точность: ±1 с в сутки для электронных часов равносильны, например, ошибке в 1 м на 86 км при измерении длины. Но, не говоря уж о специальных технических применениях, такой точности при измерении времени недостаточно даже в быту— часы с такой ошибкой будут уходить на полминуты в месяц и их придется подводить каждые два-три месяца, как минимум. Если для стрелочных часов такая процедура ничего сложного не представляет, то для электронных она выливается в довольно занудные манипуляции с кнопками или необходимость (как в нашем измерителе с часами) коррекции времени через подключение к компьютеру.

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

Для начала о самой поправке: можно, конечно, попросту ввести задержку вроде той, что служит для формирования сигналов I2С (собственно, так и отсчитывали время в контроллерах, когда в них еще не было таймеров). Но это не очень хорошо по той же причине, по которой такие паузы лучше не использовать в Windows, где много процессов протекают параллельно. Либо это задержит весь контроллер, либо (если прерывания разрешены) задержка может быть непредсказуемой длительности. Потому лучше задействовать таймер (скажем, Timer 2, который имеется во всех Mega, a Timer 1 оставим для других надобностей), только запускать его так, чтобы он формировал прерывания достаточно короткой длительности. Например, ежесуточная коррекция ступеньками по 10 мс нас будет вполне устраивать (при точном подборе задержки ошибка составит не более 1 с в три месяца, если не учитывать «гуляние» частоты кварца самой по себе).

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

Если часы спешат, то значение Кккор должно находиться в пределах 1—127 (старший бит равен нулю), и оно определяет задержку, которую мы проводим с помощью таймера, настроенного на 10 мс, раз в сутки. Для этого надо остановить часы, пропустить столько циклов таймера, сколько задано в Кккор, и запустить их заново с того же значения. Максимальная задержка составит 1,27 с в сутки, что намного перекрывает возможную ошибку кварца.

Сложнее, если часы отстают. Чтобы отличить эту ситуацию от предыдущей, мы задаем старший бит Кккор равным единице, но в пределах 155–254 (т. е. коррекция возможна в пределах 1 с). Почему именно в этих пределах, мы сейчас поймем. Величина задержки программой будет вычисляться, как разность между 255 и Кккор (задержка, равная нулю, не имеет смысла, отсюда максимальное значение 254). В МК мы останавливаем часы, включаем таймер, делаем столько сравнений, сколько задано этой разностью, затем устанавливаем секунды = 1 и запускаем часы опять (теперь они идут немного вперед). Отсюда понятно, почему мы не можем задать Кккор меньше 155 — при таком алгоритме значение, к примеру, 128 привело бы к еще большему отставанию. Следовательно, чем больше задержка (разность между 255 и Кккор), тем меньше коррекция в данном случае: если нам нужно коррекцию свести к нулю, то следует задать значение Кккор = 155. Отметим, что остановка и пуск часов сами по себе займут время порядка миллисекунд, но ошибка будет невелика, и ее можно не учитывать.

Для коррекции задействуем Timer 2 с коэффициентом 1:256, получаем на выходе 15 625 Гц (при тактовой частоте 4 МГц). Если использовать прерывание по сравнению с величиной 156, получаем примерно 100 Гц (или 10 мс). Кккор мы будем хранить в EEPROM (по адресу KоrrEE), и переписывать его в RAM (по адресу KorrRAM) — эти адреса выбираются из любых свободных. Процедура для инициализации регистра сравнения таймера и коэффициента коррекции приведена в листинге 19.2 (в секторе начальной загрузки, о самой программе см. главу 16).

Листинг 19.2

;команду ldi temp,(1<

   ldi temp, (1«TOIE0)|(1<<ОСIЕ2)

;добавляем:

 ldi temp,156

            out OCR2,temp  ;получаем 100 Гц Timer2

;коэффициент коррекции ============

   clr ZH;addr eepr

          ldi ZL,KorrEE

          rcall ReadEEP

          cpi temp,$FF