Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Режимы с преддекрементом и постинкрементом используются, когда нужно прочесть/записать целый фрагмент из памяти (эти команды недействительны для ряда младших моделей МК семейства Tiny, но для часто упоминаемой в этой книге модели ATtiny2313 они работают). Схема действий аналогичная, только команды выглядят так: st -Z,temp /с преддекрементом, запись в ячейку с адресом Z-1, после ;выполнения команды регистр Z = Z-1

st Z+,temp ;с постинкрементом, запись в ячейку с адресом Z, после /выполнения команды регистр Z = Z+1
Аналогично выглядят команды чтения:
Id temp,-Z ;с преддекрементом, чтение из ячейки с адресом Z-1, после /выполнения команды регистр Z = Z-1
Id temp,Z+ ;с постинкрементом, чтение из ячейки с адресом Z, после /выполнения команды регистр Z = Z+1
Листинг 6.9 иллюстрирует, как можно в цикле записать 16 ячеек памяти подряд одним и тем же значением из temp, начиная с нулевого адреса старших 256 байтов памяти.

ldi ZH,1 clr ZL LoopW:
st Z+,temp /сложили в память cpi ZL,16 /счетчик до 16 brne LoopW

Еще одна важная команда переноса данных — инструкция lpm, которая позволяет прочесть произвольный байт из памяти программ. Напомню, что большинство разновидностей МК, в том числе и AVR, имеют гарвардскую архитектуру, когда память программ отделена от памяти данных, и в первую контроллер самостоятельно ничего писать не может (кроме случая самопрограммирования). Потому хранение в памяти программ тех констант, которые никогда не будут изменяться, прямо рекомендуется разработчиками AVR, за много лет так и не сумевшими окончательно решить проблему безопасного хранения данных в EEPROM (см. главу 2).

Вот типичная задача такого рода: пусть контроллер осуществляет управление семисегментным индикатором в динамическом режиме, когда в каждом такте приходится выводить разные цифры. Выстраивать рисунки (битовые маски) этих цифр каждый раз — замучаешься, и программа получится очень громоздкая и совершенно нечитаемая. Проще их "нарисовать" единожды и расположить по порядку (от нуля до 9) в любом месте программы (удобно — сразу после векторов прерываний). Дать понять компилятору, что это особая область памяти, которая его не касается, и должна быть перенесена без изменений, можно с помощью директивы .db, а чтобы потом можно было найти эту область, ее следует пометить обычной меткой:

N_mask: ;маски цифр на семисегментном индикаторе
.db 0b00111111,0b0£)000110,0b01011011,0b01001111,0b01100110,0b01101101,
ObOlllllOl,ObOOOOOlll,ObOlllllll,ObOllOllll
Метка может располагаться и до, и после директивы .db. Для лучшего понимания, как размещаются байты данных в памяти программ, следует учесть, что они, как и команды, объединяются здесь в двухбайтовые слова. Если число байтов, указанных в данной директиве .db, нечетное, то последнее выражение будет записано, как слово со старшим байтом — последним в ряду, — равным нулю, даже если далее идет еще одна директива .db.

Исходя из этого, можно в нужном месте использовать команду lpm следующим хитрым образом:
ldi ZH,High(N_mask*2) /загружаем адрес начала маски
ldi ZL,Low(N_mask*2)
add ZL,5 /адрес маски цифры 5
lpm /маска окажется в регистре гО

Здесь в регистр z (и только z!) заносится адрес начала массива констант, причем учитывается, что память программ имеет двухбайтовую организацию, а в z нужно заносить побайтные адреса, отчего появляется множитель 2. По этому адресу, как мы договорились, располагается маска цифры "О". Для загрузки цифры "5" прибавляем к адресу это значение и вызываем команду lpm. Результат окажется в самом первом регистре общего назначения гО, так что при таких действиях его нежелательно занимать под какие-то переменные. Нужно упомянуть, что современные МК семейства Mega поддерживают и более простой формат команды lpm, аналогичный обычной id (с любым регистром, необязательно го, но адресацией также через регистр z), но универсальности ради ограничимся традиционным форматом, который поддерживают все МК AVR.

Команды управления системой
Их всего три: nop (по operation, пустая команда), sleep (перевод МК в режим энергосбережения) и wdr — сброс сторожевого таймера. Последнюю команду мы разберем подробнее в главе 14, а здесь кратко остановимся на предыдущих. Операция пор входит в набор команд всех ассемблеров и служит для заполнения ячеек памяти программ пустыми значениями, если это зачем-то требуется: например, чтобы выровнять адрес процедуры по определенному адресу в памяти. Встретив эту команду (в AVR ее код — все нули двухбайтового слова), процессор выполнит единственную операцию инкрементирования содержимого счетчика команд.
Команда пор в AVR может быть, например, полезна для заполнения в таблице векторов прерываний мест для неиспользуемых прерываний вместо reti или способа с применением директивы .org (только следует учесть, что в МК с памятью программ объемом 8 кбайт и менее на одно прерывание требуется одна команда пор, а для МК с большей памятью — две). При использовании команды sleep предварительно режим энергосбережения должен быть разрешен и, если потребуется, установлен его тип. Разрешение осуществляется установкой бита SE В регистре MCUCR, как показано в разделе "Команды сдвига и операции с битами" данной главы. Если больше никаких битов не устанавливать, то это означает наиболее щадящий режим Idle, другие режимы необходимо выбирать специально (подробнее см. главу 14). Отметим, что инструкция советует устанавливать бит разрешения непосредственно перед командой sleep. На самом деле это просто механизм защиты от сбоев— в реальности просто не рекомендуется устанавливать разрешение с самого начала (в процедуре инициализации), а лишь по мере необходимости в процессе выполнения программы.



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru