Найти тему
Разумный мир

Микроконтроллеры для начинающих. Часть 15. Команды пересылки данных PIC

Оглавление

В предыдущей статье мы познакомились с различными флагами, которые устанавливают/сбрасывают/анализируют машинные команды. А немного ранее потратили не мало сил и времени на изучение методов адресации операндов. Пришло время начать знакомство с машинными командами.

Я прекрасно понимаю, что большинство читателей (скорее всего, подавляющее большинство) не собираются писать программы на ассемблере. Однако, в статьях на канале я не раз высказывал свое убеждение, что чрезвычайно полезно иметь, как минимум, представление о машинных командах. И аргументировал эту точку зрения, причем на реальных примерах.

Поэтому я постараюсь найти компромисс между подробностью изложения и простотой. Я не буду приводить форматы команд, расположение отдельных полей, коды команд и режимов адресации, количество тактов и циклов выполнения. Но я опишу, что каждая команда делает, а если есть какие то особенности, то расскажу о них.

Таким образом, вы получите представление о системе команд микроконтроллеров и сможете анализировать результаты работы компиляторов. Но избежите излишне глубокого погружения, если вас не слишком интересует ассемблер.

Если в комментариях к этой статье, или любой другой, будет большой интерес к подробному рассмотрению, или будет много желающих писать на ассемблере, я уделю отдельное внимание заинтересовавшим вас командам.

В последующих статьях ассемблеру, будет тоже уделено внимание, но основной упор я планирую сделать на С.

Для удобства изложения и восприятия я разобью все команды на отдельные группы и буду рассматривать их для всех моделей микроконтроллеров, которым посвящен цикл.

А начнем мы с самых простых команд, которые не делают ничего с данным, просто переносят их из одного места в другое. Это может показаться немного странным, но такая потребность возникает очень часто. И по данным статистических исследований команды пересылки данных составляют значительную часть любой программы.

Как и в большинстве процессоров основанных на аккумуляторе, в данном случае это регистр WREG, прямая пересылка данных между ячейками памяти невозможна (но есть одно исключение).

Влияние на флаги

Исходя из того, что команды пересылки просто переносят данные с места на место, можно предположить, что они должны влиять на флаги переноса, переноса между тетрадами, знака, нулевого результата. Однако, реальность оказывается несколько сложнее.

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

Во вторых, команды пересылки иногда вообще не влияют на флаги. Это может показаться неудобным, но такое поведение позволяет сохранять состояние процессора, например, при помещении данных в стек или извлечении из стека.

Поэтому при описании команд я не буду ничего говорить про флаг переноса C. А вот влияние на другие флаги указывать буду.

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

MOVLW literal

Загружает литерал, то есть, константу, в регистр WREG. Другими словами, та команда использует непосредственную адресацию. Не оказывает влияния на флаги

MOVLB literal

Загружает литерал, то есть, константу, в регистр BSR (регистр выбора банка памяти данных). Эта команда есть только в микроконтроллерах Enhanced Mid-range и PIC18. То есть там, где есть собственно регистр BSR. Не оказывает влияния на флаги

MOVLP literal

Загружает литерал, то есть, константу, в регистр PCLATH (регистр-защелка старшей части адреса памяти программ). Эта команда есть только в микроконтроллерах Enhanced Mid-range. Не оказывает влияния на флаги.

LFSR n,literal

Загружает литерал, то есть, константу, в регистр FSRn. Про регистры FSR и их использование я писал в статье про режимы адресации PIC. Эта команда есть только в PIC18. Не оказывает влияния на флаги.

Команды очистки (обнуления)

Я упустил эти команды из первоначального описания, но решил исправиться. Эти команды тоже относятся к пересылке данных, каким бы странным это не казалось. Просто они пересылают в заданную ячейку памяти или регистр одно единственное предопределенной значение - ноль.

CLRW

Обнуляет WREG. В отличии от команды MOVLW 0, которая делает то же самое, дополнительно устанавливает флаг Z. Отсутствует в PIC18.

CLRF f

CLRF f,a

Обнуляет указанную ячейку памяти. Устанавливает флаг Z.

Общие команды пересылки данных

MOVWF f

MOVWF f,a

Записывает содержимое регистра WREG в указанный регистр f, который может быть как простой ячейкой памяти (GPR), так и регистром специальной функции (SFR). Если в качестве регистра указан INDFn, то используется косвенная адресация, как вы вероятно помните. Не оказывает влияния на флаги.

Обратите внимание на вторую форму команды MOVWF f,a. Эта форма используется только для PIC18. Здесь дополнительный параметр a указывает, какой банк используется для доступа к операндам. Если a=0, то используется Access Bank. Если a=1, то используется банк, номер которого хранится в BSR.

MOV f,d

MOV f,d,a

Записывает содержимое заданного регистра f в указанное место назначения. Если d=0, то местом назначения является WREG. Если d=1, то содержимое регистра копируется в этот же самый регистр. Странное поведение в случае d=1?

На самом деле, такая форма команды позволяет просто проверить содержимое регистра f на равенство нулю. То есть, это фактически будет уже не команда пересылки, а команда проверки.

Для упрощения, вместо задания параметра d числом, можно указывать букву f, что будет соответствовать d=1, или w, что будет соответствовать d=0.

mov TMR0,w ; запись содержимого TMR0 в регистр WREG

mov TMR0,f ; регистр TMR0 копируется сам в себя, то проверка на 0

Влияет на флаги Z и N (для PIC18).

Команды загрузки специальных регистров

OPTION

Записывает содержимое WREG в регистр OPTION_REG. В общем и целом, эта команда используется только для микроконтроллеров BaseLine, где регистр OPTION_REG не имеет адреса и доступен только таким вот образом. И только на запись. Не влияет на флаги.

TRIS f

Еще одна команда имеющая смысл только для BaseLine. Записывает содержимое WREG в регистр TRIS (регистр направления передачи данных) соответствующего порта. Не влияет на флаги.

Команды пересылки оптимизированные для языков высокого уровня

MOVIW

Это фактически специальный случай команды MOVF INDF,w в микроконтроллерах Enhanced Mid-range. Самой Microchip эта команда отнесена к группе команд оптимизированных для компиляторов C.

Я не стал писать об этом в статье про адресацию PIC, она и так получилась очень большой и сложной, но для Enhanced Mid-range существует режим косвенной адресации с пре- и пост- инкрементом и декрементом. А так же со смещением. Но возможна такая адресация только в командах MOVIW и MOVWI.

Данная команда помещает содержимое ячейки памяти с адресом из соответствующего FSR в регистр WREG. И она, как и MOVF, влияет на флаг Z. Эта команда есть только в Enhanced Mid-range. Возможы вот такие форматы этой команды

MOVIW ++FSRn

MOVIW --FSRn

MOVIW FSRn++

MOVIW FSRn--

MOVIW k[FSRn]

Здесь k это смещение, со знаком.

Обратите внимание, что в PIC18 этой команды нет, там ее возможности реализованы в любой команде с указанием регистров POSTDEC, POSTINC, PREINC и PLUS вместо регистра INDF. О чем я писал ранее.

MOVWI

Эта команда тоже есть только в Enhanced Mid-range. Ее действие обратно действию MOVIW, то есть, она является специальным случаем команды MOVWF INDF. За Этим исключением, все сказанное о команде MOVIW относится и к данной команде. Не влияет на флаги.

Универсальная команда пересылки

MOVFF fs,fd

Эта команда существует только в PIC18. Ее уникальность состоит в том, что она записывает содержимое ячейки памяти fs в ячейку памяти fd напрямую, минуя WREG. Причем здесь задаются только прямые адреса ячеек памяти (в границах 4К). Однако, в качестве источника или приемника может быть указан и WREG. Не влияет на флаги.

Команды чтения/записи памяти программ

Эти команды есть только в PIC18. Основное их назначение - работа с таблицей констант в памяти программ, но с возможностью их изменения. Например, текст сообщения можно хранить в памяти программ, при этом возможно изменять это сообщение (например текст приветствия или имени устройства). Однако, они могут использоваться и для загрузки в память программ обновленной версии. То есть, для реализации загрузчика.

Сразу хочу сказать, что возможность записи в память программ я сейчас не буду рассматривать. Я коснусь только чтения из таблицы (строки) констант хранящихся в памяти программ. Давайте посмотрим, как это все работает для чтения

Чтение памяти программ в PIC18. Иллюстрация моя
Чтение памяти программ в PIC18. Иллюстрация моя

Все очень похоже на использование регистра INDF при чтении памяти данных. Только здесь адрес в памяти программ хранится в 22-разрядном регистре TBLPTR. Содержимое байта, на который указывает TBLPTR помещается в специальный регистр-защелку TABLAT.

Память программ требует выравнивания команд на границе двух байт (четный адрес). Однако, для хранения констант данных такого требования нет. Поэтому и TBLPTR хранит полный адрес, нулевой бит уже не обязан быть всегда равным 0.

TBLRD

Собственно чтение байта из памяти команд выполняется командой TBLRD. При этом есть несколько ее форматов, так как возможен постинкремент, преинкремент и постдекремент содержимого TBLPTR.

TBLRD *

TBLRD *+

TBLRD +*

TBLRD *-

Фактически использование этой команды выходит за рамки "для начинающих", поэтому я сначала хотел отложить ее упоминание "на потом". Однако, простейшие варианты ее использования полезны и не на много сложнее команды RETLW, о которой будет рассказано в другой статье.

Данная команда не влияет на флаги.

TBLWT

Эта команда записывает содержимое TABLAT в память программ. Однако, для этого требуется соблюдение специальной процедуры доступа. Кроме того, данный вопрос выходит далеко за рамки статьи. Сегодня я ограничусь лишь упоминанием данной команды.

Заключение

Как видите, команды пересылки действительно очень просты даже для такого семейства микроконтроллеров, как PIC. Сегодня даже иллюстраций не потребовалось, за исключением чтения памяти программ в PIC18.

До новых встреч!