Команды пересылки данных

Команды пересылки данных

Табл 2. Команды пересылки данных:

Команда

Описание

Действие

Циклы

Код операции

Флаги

ATtiny

ATmega

mov    Rd,Rr

Move Between Registers

Rd←Rr

1

0010 11rd dddd rrrr

None

+

+

movw   Rd,Rr

Copy Register Word

Rd+1:Rd←Rr+1:Rr

1

0000 0001 dddd rrrr

None

±

+

ldi    Rd,K

Load Immediate

Rd←K

1

1110 KKKK dddd KKKK

None

+

+

ld     Rd,X

Load Indirect

Rd←(X)

2

1001 000d dddd 1100

None 

  ±

+

ld     Rd,X+

Load Indirect and

Post-Inc.

Rd←(X), X←X+1

2

1001 000d dddd 1101

None

±

+

ld     Rd,-X

Load Indirect and

Pre-Dec.

X←X-1, Rd←(X)

2

1001 000d dddd 1110

None

±

+

ld     Rd,Y

Load Indirect

Rd←(Y)

2

1000 000d dddd 1000

None 

  ±

+

ld     Rd,Y+

Load Indirect and

Post-Inc.

Rd←(Y), Y←Y+1

2

1001 000d dddd 1001

None

±

+

ld     Rd,-Y

Load Indirect and

Pre-Dec.

Y←Y-1, Rd←(Y)

2

1001 000d dddd 1010

None

±

+

ldd    Rd,Y+q

Load Indirect with Displacement

Rd←(Y+q)

2

10q0 qq0d dddd 1qqq

None

±

+

ld     Rd,Z

Load Indirect

Rd←(Z)

2

1000 000d dddd 0000

None 

  +

+

ld     Rd,Z+

Load Indirect and

Post-Inc.

Rd←(Z), Z←Z+1

2

1001 000d dddd 0001

None

±

+

ld     Rd,-Z

Load Indirect and

Pre-Dec.

Z←Z-1, Rd←(Z)

2

1001 000d dddd 0010

None

±

+

ldd    Rd,Z+q

Load Indirect with Displacement

Rd←(Z+q)

2

10q0 qq0d dddd 0qqq

None

±

+

lds    Rd,k

Load Direct from SRAM

Rd←(k)

2

1001 000d dddd 0000

kkkk kkkk kkkk kkkk

None

±

+

st     X,Rr

Store Indirect

(X)←Rr

2

1001 001r rrrr 1100

None

±

+

st     X+,Rr

Store Indirect and

Post-Inc.

(X)←Rr, X←X+1

2

1001 001r rrrr 1101

None

±

+

st     -X,Rr

Store Indirect and

Pre-Dec.

X←X-1, (X)←Rr

2

1001 001r rrrr 1110

None

±

+

st     Y,Rr

Store Indirect

(Y)←Rr

2

1000 001r rrrr 1000

None

±

+

st     Y+,Rr

Store Indirect and

Post-Inc.

(Y)←Rr, Y←Y+1

2

1001 001r rrrr 1001

None

±

+

st     -Y,Rr

Store Indirect and

Pre-Dec.

Y←Y-1, (Y)←Rr

2

1001 001r rrrr 1010

None

±

+

std    Y+q,Rr

Store Indirect with Displacement

(Y+q)← Rr

2

10q0 qq1r rrrr 1qqq

None

±

+

st     Z,Rr

Store Indirect

(Z)←Rr

2

1000 001r rrrr 0000

None

+

+

st     Z+,Rr

Store Indirect and

Post-Inc.

(Z)←Rr, Z←Z+1

2

1001 001r rrrr 0001

None

±

+

st     -Z,Rr

Store Indirect and

Pre-Dec.

Z←Z-1, (Z)←Rr

2

1001 001r rrrr 0010

None

±

+

std    Z+q,Rr

Store Indirect with Displacement

(Z+q)← Rr

2

10q0 qq1r rrrr 0qqq

None

±

+

sts    k,Rr

Store Direct to SRAM

(k)←Rr

2

1001 001r rrrr 0000

kkkk kkkk kkkk kkkk

None

±

+

lpm

Load Program Memory

R0←(Z)

3

1001 0101 1100 1000

None

+

+

lpm    Rd,Z

Load Program Memory

Rd←(Z)

3

1001 000d dddd 0100

None

±

+

lpm    Rd,Z+

Load Program Memory

and  Post-Inc.

Rd←(Z), Z←Z+1

3

1001 000d dddd 0101

None

±

+

elpm

Extended Load

Program Memory

R0←(RAMPZ:Z)

3

1001 0101 1101 1000

None

±

elpm   Rd,Z

Extended Load

Program Memory

Rd←(RAMPZ:Z)

3

1001 000d dddd 0110

None

±

elpm   Rd,Z+

Extended Load Program Memory and Post-Inc.

Rd←(RAMPZ:Z),

(RAMPZ:Z)←

←(RAMPZ:Z)+1

3

1001 000d dddd 0111

None

±

spm

 

Store Program Memory

(Z)←R1:R0

1001 0101 1110 1000

None

±

+

in     Rd,P

In Port

Rd←P

1

1011 0PPd dddd PPPP

None

+

+

out    P,Rr

Out Port

P←Rr

1

1011 1PPr rrrr PPPP

None

+

+

push   Rr

Push Register in Stack

STACK←Rr, SP←SP-1

2

1001 001r rrrr 1111

None

±

+

pop    Rd

Pop Register from Stack

SP←SP+1, Rd←STACK

2

1001 000d dddd 1111

None

±

+

Группа команд пересылки данных сведена в табл.2. Под определением пересылки (перемещения) в данном случае понимается копирование содержимого источника без его изменения в приёмник. При этом ни одна из инструкций пересылок не влияет ни на какие флаги регистра состояния SREG. Множество возможностей адресации позволяют с одинаковым успехом обрабатывать как отдельные байты так и массивы данных. При этом часто существует несколько путей для реализации той или иной операции.

В пределах РОН пересылка производится с помощью команды mov Rd,Rr (Пересылка между регистрами). Кроме этого, имеется возможность перемещения двухбайтовых чисел (регистровых пар R1:R0, R3:R2,…, R29:R28, R31:R30) с помощью команды movw  Rd,Rr (Пересылка между регистровыми парами), где на месте операндов Rd и Rr должны стоять младшие регистры в обозначениях регистровых парах приёмника и источника соответственно (например, movw  R0, R30 для пересылки R1:R0 ← R31:R30). Обе эти команды выполняются за один машинный цикл:

mov R17,R16 ; возведение в квадрат R16 mul R17,R16 ; с помещением двухбайтового результата movw R16,R0 ; в регистровую пару R17:R16

Для загрузки константы в регистр служит команда с непосредственной адресацией ldi Rd,K (Загрузка константы в регистр). Она работает только со старшими РОНами (R16…R31).

Команды для работы с SRAM микроконтроллера используют, в основном, косвенную адресацию. Для этих целей применяются три 16-разрядных индексных регистра X,Y,Z, которые находятся в адресном пространстве РОН и по совместительству также являются регистровыми парами R27:R26, R29:R28, R31:R30.

Копировать байт из памяти ОЗУ в РОН можно любой из команд: ld Rd,X, ld Rd,Y, ld Rd,Z (Косвенное чтение из памяти данных). В этом случае в регистре приёмнике окажется содержимое ячейки памяти данных, адрес которой находится в одном из индексных регистров. Кроме этого, существует ещё две вариации данного действия. В одной из них после копирования производится инкрементирование регистров  X,Y,Z, на что указывает знак “+”  в командах: ld Rd,X+, ld Rd,Y+, ld Rd,Z+ (Косвенное чтение из памяти данных с постинкрементом). Во втором случае, перед пересылкой, содержимое индексного регистра сначала уменьшается на 1 (знак “-” в команде): ld Rd,-X, ld Rd,-Y, ld Rd,-Z (Косвенное чтение из памяти данных с преддекрементом).

Команды косвенного чтения с постинкрементом/преддекрементом очень эффективны при работе с массивами однотипных данных. Для обращения же к элементам структуры (набору данных разного типа) удобно использовать ld Rd,Y+q, ld Rd,Z+q (Косвенное относительное чтение из памяти данных), в которых в качестве указателей используется Y,Z со смещением q (адрес ячейки памяти определяет сумма (Y)+q или (Z)+q). Смещение q в командах -фиксированная величина, лежащая в пределах 0…63.

Пересылка данных из РОН в ОЗУ посредством косвенной адресации реализуется с помощью команд: st X,Rr, st Y,Rr, st Z,Rr (Косвенная запись в память данных). Содержимое регистра в них копируется в ячейку памяти, адрес которой определяется указателями X,Y и Z соответственно. Точно также существуют команды загрузки с постинкрементом st X+,Rr, st Y+,Rr, st  Z+,Rr (Косвенная запись в память данных с постинкрементом) и с преддекрементом индексного регистра st -X,Rr, st -Y,Rr, st  -Z, Rr (Косвенная запись в память данных с преддекрементом). Ещё две команды этой группы используют косвенную адресацию со смещением: st Y+q,Rr, st Z+q,Rr (Косвенная относительная запись в память данных). Здесь смещение q может находится в пределах 0…63.

Как видно между командами выгрузки из памяти и загрузки в память существует полная симметрия. У каждой операции пересылки существует аналогичная, для пересылки в обратном направлении, причём с использованием трёх равноправных индексных регистров. Кроме того все они выполняются за один промежуток времени в 2 машинных цикла. Типичный  пример их совместного использования может выглядеть следующим образом:

ldi YL, low(buffer1) ; копирование SIZE байт из ldi YH, high(buffer1) ; буфера buffer1 в буфер buffer2 ldi ZL, low(buffer2) ; перед копированием в индексные ldi ZH, high(buffer2) ; регистры Y и Z заносятся адреса ldi R16,SIZE ; буферов buffer1 и buffer2 copy: ld R17,Y+ st Z+,R17 dec R16 brne copy .

Копирование данных из ОЗУ в РОН и обратно может быть произведено и с использованием прямой адресации по командам lds Rd,k (Прямое чтение из памяти данных) и sts k,Rr (Прямая запись в память данных) соответственно. В этом случае двухбайтовый адрес k ячейки памяти находится в коде операции, а сами команды занимают 2 слова (4 байта) памяти программ.

Все вышеуказанные команды пересылок работают в едином адресном пространстве где под РОН отведены адреса 0x00…0x1F, под РВВ от 0x20…0x5F, остальное под ячейки ОЗУ. Поэтому, например, копирование R16←R17 может быть произведено разными путями: mov R16,R17, lds R16,0x0011, ld R16,X (в регистре X адрес 0x0011) и т.д. Первый способ здесь, конечно, более предпочтительный (использует пересылку типа регистр-регистр и выполняется быстрее), но остальные команды позволяют получить доступ к произвольному элементу любой области памяти и поэтому очень универсальны.

Для обращения к РВВ служат команды: in Rd,P (Ввод из порта), out P,Rr (Вывод в порт). Первая считывает значение РВВ в один из РОНов, а вторая производит пересылку РОН в РВВ.

Поскольку напрямую модифицировать РВВ невозможно, приходится сначала копировать их содержимое в рабочие РОН, производить необходимые изменения, а потом заносить обратно:

in R16,PORTC ; запись и модификация РВВ, andi R16,0b00001111 ; отвечающего за содержимое порта out PORTC,R16

Тоже самое относится и к данным, расположенным в ОЗУ:

lds R16,0x0200 ; запись и модификация байта из ОЗУ, inc R16 ; находящегося по абсолютному адресу 0x0200 sts 0x0200,R16

В группе команд пересылки данных имеются две, специально разработанные для работы со стеком. Это push Rr (Сохранение в стеке) и pop Rd (Извлечение из стека). Не смотря на то, что основное назначение стека это сохранение адресов возврата при вызове подпрограмм, эти инструкции позволяют использовать его и для оперативного сохранения данных, находящихся в РОН. Командой push Rr содержимое регистра копируется в ячейку памяти (вершину стека), адрес которой содержится в указателе стека SP, после чего значение SP уменьшается на 1. По команде pop Rd указатель стека возвращается на предыдущий элемент (SP+1), а значение, байта записанное по этому адресу копируется в регистр.

Таким образом реализуется память магазинного типа, где вообще не надо заботиться о задании адресов сохраняемых и восстанавливаемых из в памяти ОЗУ данных. Единственное, про что всегда необходимо помнить, – это порядок доступа к элементам стека Last In First Out (Первый Вошел Последний Вышел). Очередность, в которой регистры восстанавливаются из стека, должна быть обратной по отношению к очередности сохранения регистров:

ldi R16, low(RAMEND) ;установка вершины стека out SPL,R16 ldi R16, high(RAMEND) out SPH,R16 . push R16 ;сохранение регистров в стеке push R17 push R18 . pop R18 ;восстановление регистров из стека pop R17 pop R16

Имеется и другая возможность программно реализовать стек данных. Команды ld Rd,X+, ld Rd,Y+, ld Rd,Z+ по сути являются  иной реализацией действия push Rr, а st -X,Rd, st -Y,Rd, st -Z, Rd подобны pop Rd. Разница состоит лишь в том, что в качестве индексного регистра выступает не SP, а один из регистров–указателей (X,Y,Z) и вершина стека перемещается в сторону увеличения адресов ОЗУ:

ldi ZL, low(stack) ;установка вершины стека ldi ZH, high(stack) . ld R16, Z+ ;сохранение регистров в стеке ld R17, Z+ ld R18, Z+ . st -Z, R18 ;восстановление регистров из стека st -Z, R17 st -Z, R16

Учитывая то, что SP расположен в пространстве РВВ, а X,Y,Z в РОН, использование эмуляции стека может быть даже более предпочтительной. Регистры X,Y,Z могут быть быстрей модифицированы и кроме того отсутствует опасность повредить их содержимое при вызове подпрограмм и возникновении прерываний.

Подобно большинству микроконтроллеров, у AVR имеется возможность хранения таблиц констант в памяти программ. Для их чтения разработаны команды lpm (Загрузка памяти программ), lpm Rd,Z (Загрузка памяти программ), lpm Rd,Z+ (Загрузка памяти программ с постинкрементом). Все они переписывают содержимое байта из FLASH памяти программ (адрес байта находится в Z) в один из РОН. С помощью первой инструкции, не имеющей параметров, копирование производится в R0. Вторая и третья модификации команды используют в качестве приёмника любой РОН. Команда lpm Rd,Z+ при этом осуществляет ещё и инкрементирование индексного регистра Z после считывания. Типичный пример копирования строки из памяти программ в ОЗУ может выглядеть следующим образом:

ldi ZL,low(2*string) ;копирование строки “Hello World” ldi ZH,high(2*string);длиной 11 байт из памяти программ ldi YL,low(buffer) ;в ОЗУ микроконтроллера по ldi YH,high(buffer) ;адресу buffer ldi R16,11 cycle: lpm R17,Z+ st Y+,R17 dec R16 brne cycle . .org 0x1000 string: .db “Hello World”, 0

Здесь последовательно осуществляется считывание строки "Hello World !" (13 байт в кодировке ASCII) расположенной в памяти программ начиная с адреса 0x1000 (задан директивой .org 0x1000). Для резервирования FLASH памяти используется директива ассемблера .db, после которой непосредственно следуют данные. Строка переписывается в ОЗУ по адресу buffer.

Есть два важных момента при использовании операций такого типа. В приведённом выше фрагменте программы в качестве указателя на строку в индексный регистр Z заносится удвоенный адрес метки 2*string и это не случайность. Дело в том, что метке string соответствует адрес слова программ 0x1000. Но слово программ у AVR имеет блину 2 байта, а в указатель Z необходимо занести именно адрес байта т.е. 2*0x1000 = 0x2000. По той же причине в памяти программ необходимо выделять только чётное (кратное двум) количество байтов и если это не так, то надо добавлять незначащий байт 0 в самом конце, как это и случилось в нашем примере (строка "Hello World !" содержит 13 байт). Попутно заметим, что строки символов ASCII, как правило, и хранят в таком формате (добавляют в конце 0). Это позволяет автоматически  распознавать конец строки и считывать, не зная заранее её длины.

Использование 2-байтового регистра Z позволяет адресовать только 64 кб при считывании памяти программ. Этого явно недостаточно для тех моделей AVR, которые имеют 128 и 256 кб FLASH-памяти. Для того чтобы работать во всём диапазоне адресов к указателю Z в этом случае добавляется регистр RAMPZ из пространства РВВ, в котором используются 1 или 2 младших бита. Этот 3-байтовый индексный регистр RAMPZ:ZH:ZL используют инструкции elpm (Расширенная загрузка памяти программ), elpm Rd, Z (Расширенная загрузка памяти программ), elpm Rd,Z+ (Расширенная загрузка памяти программ с постинкрементом).

Последняя инструкция в группы команд пересылки spm (Запись памяти программ). Она реализует возможность самопрограммирования микроконтроллеров AVR. Конкретное действие, которое выполняет эта команда, зависит от установок в управляющем РВВ SPMCSR. Это может быть стирание страницы памяти программ, занесение данных для записи во временный буфер или копирование буфера в память программ, а также чтение ячеек идентификаторов и защиты. В любом случае для задания адреса области используется указатель Z, а данные, если они необходимы, передаются в регистровой паре R1:R0. Так как действие данной инструкции связано с модификацией программного кода, для ее корректного применения предпринят ряд мер предосторожности, о чём подробно будет сказано в разделе “Самопрограммирование микроконтроллеров AVR”.

Перейти к следующей части:


Категория: Микроконтроллеры
Метки:

Написать коментарий

*
= 5 + 1

Добавить изображение

Последние статьи