Следующими по важности командами переноса данных будут команды загрузки и чтения SRAM— idи st. С этими командами связаны такие «жуткие» понятия, как «прямая» и «косвенная» адресации, а также «относительная косвенная адресация» и прочая подобная «лабуда» из арсенала разработчиков микросхем и теоретиков программирования. Эти понятия на практике абсолютно не требуются, и только затуманивают мозги, потому что зачастую относятся к совершенно разным командам и узлам кристалла (это единственный раздел в описаниях МК, который спокойно можно пропускать при чтении, все остальные изучать очень полезно). Мы постараемся от термина «адресация» вообще отказаться и разберем здесь три основных режима чтения/записи SRAM: простой, а также с преддекрементом и постинкрементом. Все три употребляются очень часто, хотя два последних режима работают не во всех типах AVR.
Во всех случаях в чтении и записи SRAM используются регистры X, Y и Z — т. е. пары r27:r26, r29:r28и r31:r30соответственно, которые по отдельности еще именуют ХН, XL, YH, YL, ZH, ZL в том же порядке (т. е. старшим в каждой паре служит регистр с большим номером). Если обмен данными производится между памятью и другим регистром общего назначения, то достаточно только одной из этих пар (любой), если же между областями памяти — целесообразно задействовать две. Независимо от того, какую из пар мы используем, чтение и запись происходят по идентичным схемам, меняются только имена регистров.
Покажем основной порядок действий при чтении из памяти для регистра Z ( r31:r30). Чтение одной ячейки с заданным адресом Address, коррекция ее значения и последующая запись выполняются так:
ldi ZH,High(Address) ;старший байт адреса RAM
ldi ZL,Low(Address) ;младший байт адреса RAM
ld temp,Z ;читаем ячейку в temp
inc temp ;например, увеличиваем значение на 1
st Z,temp ;и снова записываем
Заметки на полях
При всех подобных манипуляциях нужно внимательно следить за двумя вещами: во-первых, за тем, чтобы не залезть в несуществующую область памяти (если объем SRAM составляет 512 байт, как в большинстве моделей, которые мы будем использовать, то ZH в данном примере может иметь значения только 0 или 1). Во-вторых, не забыть, что младшие адреса SRAM заняты регистрами (в большинстве моделей под это зарезервированы первые 96 адресов от $00 до $5F). И запись, например, по адресу $0000 (ZH=0, ZL=0) равносильна записи в регистр r0. Во избежание коллизий я по возможности поступаю следующим образом: резервирую пару ZH, ZL только под запись/чтение в память, и устанавливаю с самого начала регистр ZH в единицу. Тогда при любом значении ZL мы будем «шарить» только в старших 256 байтах из 512, чего для любых практических нужд обычно достаточно (а если недостаточно, то, скорее всего, все равно придется задействовать внешнюю память), а случайно пересечься с регистрами нет никакой возможности. Обязательно нужно также помнить, что и последние адреса памяти также нельзя занимать: мы сами дали в начале программы команду задействовать их под стек.
Режимы с преддекрементом и постинкрементом удобны, когда нужно прочесть или записать в память целый фрагмент (эти команды недействительны для большинства МК семейства Tuny). Схема действий аналогичная, только при этом команды выглядят так:
st -Z,temp ;с преддекрементом, запись в ячейку с адресом Z-1, после выполнения команды Z = Z-1
st Z+,temp ;с постинкрементом, запись в ячейку с адресом Z, после выполнения команды Z = Z+1
Аналогично выглядят команды чтения:
ld temp, -Z ;с преддекрементом, чтение из ячейки с адресом Z-1, после выполнения команды Z = Z-1
ld temp,Z+ ;с постинкрементом, чтение из ячейки с адресом Z, после выполнения команды Z = Z+1
Вот как можно в цикле записать 16 ячеек памяти подряд одним и тем же значением из temp, начиная с нулевого адреса старших 256 байтов памяти:
ldi ZH,1
clr ZL
LoopW:
st Z+,temp ;сложили в память
cpi ZL,16 ; счетчик до 16
brne LoopW
Еще одна важная, хотя и нечасто употребляемая команда переноса данных — инструкция lpm, которая позволяет прочесть произвольный байт из памяти программ. Напомню, что архитектура у большинства разновидностей МК, в том числе и AVR, гарвардская, когда память программ отделена от памяти данных, и в память программ контроллер самостоятельно ничего писать не может (кроме случая самопрограммирования, но это экзотика). Потому хранение в памяти программ тех констант, которые никогда не будут изменяться, прямо рекомендуется разработчиками AVR, за много лет так и не сумевшими окончательно решить проблему безопасного хранения данных в EEPROM (о чем мы еще будем долго и много говорить).
Читать дальше
Конец ознакомительного отрывка
Купить книгу