Вот типичная задача такого рода: пусть контроллер осуществляет управление семисегментным индикатором в динамическом режиме, когда в каждом такте приходится выводить разные цифры. Выстраивать рисунки (битовые маски) этих цифр каждый раз замучаешься, и программа получится очень громоздкая, к тому же совершенно нечитаемая. Проще их «нарисовать» один раз и расположить по порядку (от 0 до 9) прямо в любом месте программы (удобно сразу после векторов прерываний). Дать понять компилятору, что это особая область памяти, которая его не касается, и должна быть перенесена без изменений, можно с помощью директивы db, а чтобы потом можно было найти эту область, ее следует пометить обычной меткой:
N_mask:;маски цифр на семисегментном индикаторе
.db0b000111111, 0b0000001110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111
Заметим, что таким образом можно формировать hex-файлы для предварительной записи констант в EEPROM, хотя мы будем пользоваться иным, более корректным методом (см. главу 15 ). Теперь можно в нужном месте использовать команду lpmследующим хитрым образом:
ldi ZH,High(N_mask*2) ;загружаем адрес начала маски
ldi ZL,Low(N_mask*2)
add ZL,5 ;адрес маски цифры «5»
lpm ;маска окажется в регистре r0
Надо сказать, что современные МК семейства Mega поддерживают и более простой формат команды lpm, аналогичный обычной id, но универсальности ради я привык к традиционному формату, который поддерживают все МК AVR. Здесь в регистр Z (и только Z!) заносится адрес начала массива констант, причем учитывается, что память программ имеет двухбайтную организацию, а в Z надо заносить побайтные адреса, отчего появляется множитель 2. По этому адресу, как мы договорились, располагается маска цифры «0». Для загрузки цифры «5» прибавляем к адресу это значение и вызываем команду lpm. Полученное значение маски окажется в самом первом регистре общего назначения го, так что при таких действиях его не следует занимать под какие-то переменные.
О Fuse-битах
Это «несчастье» свалилось на нашу голову с появлением семейств Tuny и Mega и привело к многочисленным проклятиям на голову фирмы Atmel со стороны армии любителей, которые стали один за другим «запарывать» кристаллы при программировании. Теперь уже все привыкли и обзавелись соответствующим софтом, а сначала было довольно трудно. Положение усугублялось тем, что в описании этих сущностей действовала извращенная логика: как мы знаем, любая чистая EEPROM (по принципу ее устройства) содержит единицы, и слово «запрограммированный» по отношению к такой ячейке означает, что в нее записали нули. Поэтому разработчики программатора AS-2 даже специально написали в окне программирования конфигурационных ячеек (такое название более правильное, чем fuse-бит, буквально означающее «предохранительный бит») памятку на этот счет (рис. 13.7).
Рис. 13.7. Окно типового состояния конфигурационных ячеек в нормальном режиме работы ATmega8535
На рис. 13.7 приведено безопасное рабочее состояние конфигурационных ячеек для ATmega8535, причем выпуклая кнопка означает единичное состояние ячейки, а нажатая — нулевое (и не путайтесь с этим самым «запрограммированным» состоянием!). Для разных моделей набор fuse-битов различный, но означают они одно и то же, потому мы разберем типовое их состояние на этом примере. Перед первым программированием нового кристалла просто один раз установите эти ячейки в нужное состояние.
Переписывать фирменные руководства я не буду, остановлюсь только на самых необходимых моментах. По умолчанию любая микросхема семейств Mega или Tuny запрограммирована на работу от внутренней RC-цепочки, за что разработчикам большое спасибо, иначе было бы невозможным первичное программирование по SPI, а только через параллельный программатор.
Для работы с обычным кварцем, присоединенным по типовой схеме, требуется установить все ячейки CKSEL0—3 в единицы, что согласно логике контроллера означает незапрограммированное их состояние. Это и ведет к критической ошибке. Решив при поверхностном чтении очень невнятно написанного, и к тому же по-английски, руководства, что установка всех единиц означает запрограммировать все ячейки, пользователь смело устанавливает их на самом деле в нули, отчего микросхема переходит в состояние работы от внешнего генератора и разбудить ее через SPI-интерфейс уже невозможно. Легче всего в этом случае переустановить fuse-биты с помощью параллельного программатора, либо за неимением такового, попробовать-таки подключить внешний генератор (его можно собрать по одной из схем из главы 9 ), как описано в руководстве.
Читать дальше
Конец ознакомительного отрывка
Купить книгу