Электронные системы ускорителей

СИСТЕМА КОМАНД МИКРОКОНТРОЛЛЕРОВ СЕМЕЙСТВА MCS51

1. Набор инструкций

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

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

2. Слово состояния программы

Слово состояния программы – Program Status Word (PSW) содержит статусные биты (флаги), которые отражают текущее состояние процессора. Регистр PSW размещается в адресном пространстве резидентной памяти для функциональных регистров – Special Function Register (SFR). Он содержит биты переноса (C), дополнительного переноса (AC) для двоично-десятичных операций, флаг (F0), определяемый пользователем, два бита для выбора банка регистров (RS1, RS0), флаг переполнения (OV) и бит четности (P).

Формат слова состояния программы

табл

Бит переноса дополнительно к обслуживанию арифметических операций используется как «аккумулятор» для множества булевых операций. Биты RS0 и RS1 выбирают один из четырех банков регистров. Множество инструкций ссылается на них как на R0 – R7.

Биты RS0 и RS1 выбирают один из четырех банков регистров. Множество инструкций ссылается на них как на R0 - R7.

Бит переполнения определяет значимость числа. Он устанавливается, если результат операции не может быть размещен в аккумуляторе или 8-ой разряд рассматриваться как знаковый.

Бит четности отражает количество 1 в аккумуляторе: Р=1, если аккумулятор содержит нечетное число единиц, и Р=0, если он содержит четное число единиц. Таким образом, число единиц в аккумуляторе плюс Р – всегда четное.

Один бит в PSW не определен, и он может использоваться как флаг общего назначения.

3. Режимы адресации

3.1. Прямая адресация

При прямой адресации операнд в инструкции специфицирован 8-битовым адресом. Только данные резидентной RAM или SFR могут адресоваться прямо.

3.2. Косвенная адресация

При косвенной адресации инструкция специфицирует регистр, который содержит адрес операнда. Косвенно адресовано может быть как внутренняя, так и внешняя RAM. Регистром для 8-битовых адресов может быть или указатель стека, или R0, или R1 выбранного банка регистров. Регистром для 16-битовых адресов может быть только регистр указателя 16-битовых данных DPTR.

3.3. Регистровая адресация

Банки регистров, содержащие регистры R0 – R7, могут быть доступны инструкциям, чьи коды операций имеют 3 бита для спецификации регистра. Инструкции, имеющие доступ к регистрам, делают код более эффективным, так как при этом отсутствует адресный байт. При выполнении инструкции доступен один из восьми регистров в выбранном банке, который выбирается из четырех возможных двумя битами PSW.

3.4. Инструкции со специфицированными регистрами

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

3.5. Непосредственная адресация

Код операции может содержать в качестве операнда константу. Например, MOV A,#100 загружает аккумулятор десятичным числом 100. То же число может быть в шестнадцатеричном формате – 64H.

3.6. Индексная адресация

Память программ может быть доступна только через индексную адресацию. Этот режим адресации предназначен для табличного обращения к памяти программ. 16-битовый базовый регистр (либо DPTR, либо программный счетчик РС) указывает на базу таблицы, а аккумулятор задает точку входа в нее. Входной адрес в память программ формируется добавлением данных аккумулятора к базовому адресу.

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

4. Арифметические инструкции

Арифметические инструкции приведены в табл. 1. В таблице указаны режимы адресации, которые могут использоваться с любой инструкцией, заменяя операнд byte. Например, инструкция ADD A,byte может быть записана в следующем виде:

	ADD A,7FH		(прямая адресация)
	ADD A,@R0		(косвенная адресация)
	ADD A,R7 		(регистровая адресация)
	ADD A,#127 		(непосредственная адресация)

Табл. 1. Арифметические инструкции

табл1

Предполагая, что частота системного генератора 12 МГц, один машинный цикл в режиме совместимости выполняется за 1 мкс. Все арифметические операции выполняются за 1 мкс кроме инструкции INC DPTR, которая выполняется за 2 мкс, а операции умножения и деления – за 4 мкс.

Следует отметить, что любой байт резидентной памяти данных может быть инкрементирован или декрементирован без использования аккумулятора. Инструкция INC DPTR оперирует с 16-битовым указателем данных. Указатель данных генерирует 16-битовые адреса для внешней памяти, таким образом, возможность инкрементирования в 16-битовой операции является полезной особенностью.

Инструкция MUL AB умножает данные в аккумуляторе на данные в регистре В и помещает результат в регистре В и аккумуляторе.

Инструкция DIV AB делит данные в аккумуляторе на данные в регистре В и размещает 8-битовую целую часть результата в аккумуляторе, а остаток – в регистре В.

Примечание: Инструкция DIV AB использует в программе арифметического деления обычную конверсию и операции сдвига. Операции сдвига выполняют деление на 2n сдвигом на n бит вправо. При использовании операции деления, сдвиг выполняется за 4 мкс, а сдвинутые биты размещаются в регистре В.

Инструкция DA A предназначена для двоично-десятичных операций. В двоично-десятичной арифметике после инструкций ADD и ADDC всегда необходимо выполнять операцию DA A, чтобы результат был также в двоично-десятичном коде. Заметим, что DA A не конвертирует двоичное число в двоично-десятичное число. Операция DA A дает значащий результат только как следующий шаг в дополнение операции с двумя двоично-десятичными байтами.

5. Логические инструкции

Логические инструкции приведены в табл. 2. Инструкции булевых операций (AND, OR, исключающее OR, NOT), выполняют их побитно. Таким образом, если аккумулятор содержит 00110101B, а byte содержит 01010011B, то после выполнения операции ANL A,byte в аккумуляторе будет находиться результат 00010001B.

В табл. 2 также даны режимы адресаций, которые дают доступ к операнду byte.

Таким образом, инструкция ANL A,byte может иметь следующие формы:

	ANL A,7FH 	(прямая адресация)
	ANL A,@R1 	(косвенная адресация)
	ANL A,R6  	(регистровая адресация)
	ANL A,#53H   (непосредственная адресация)

Табл. 2. Логические инструкции

табл2

Все логические инструкции, которые используют аккумулятор, выполняются за 1 мкс (при 12 МГц тактовой частоте в режиме совместимости). Другие выполняются за 2 мкс.

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

Инструкция XRL byte,#data, например, дает возможность быстро и просто инвертировать биты порта:

XRL P1,#FFH

Циклические инструкции сдвигают аккумулятор на один бит. Для левой ротации старший бит сдвигается в младший бит, для правой ротации младший бит – в старший.

Инструкция SWAP A обменивает старший и младший полубайты в аккумуляторе. Этот обмен используется в двоично-десятичной арифметике. Например, если аккумулятор содержит двоичное число меньше 100, следующий код быстро конвертирует его в двоично-десятичное число:

MOV B,#10

DIV AB

SWAP A

ADD A,B

Деление на 10 дает цифру десятков в младшем полубайте аккумулятора, а цифру единиц в регистре В. Инструкции SWAP и ADD перемещают цифру десятков в старшую половину аккумулятора, а цифру единиц в младшую.

6. Перемещение данных

6.1. Внутренняя память

В табл. 3 приведены инструкции и соответствующие режимы адресаций, используемые для перемещения данных во внутренней памяти. С 12 МГц тактовой частотой все эти инструкции выполняются в режиме совместимости за 1 мкс или 2 мкс. Инструкция MOV dest,src позволяет передачу между любыми двумя ячейками, размещенными во внутренней RAM или SFR, без использования аккумулятора.

Заметим, что в микроконтроллере стек размещен во внутренней памяти и «растет» вверх. Инструкция PUSH прежде инкрементирует указатель стека SP, а затем копирует байт в стек. Инструкции PUSH и POP используют только прямую адресацию для идентификации байта, который должен быть сохранен или восстановлен, но сам стек доступен посредством косвенной адресацией с использованием регистра SP. Это означает, что стек может превысить 128 байт, но не в пространство SFR. В контроллерах, где нет пространства выше 128 байт, если SP устанавливается больше 128, загружаемые байты становятся потерянными, а восстанавливаемые – неопределенными.

Табл. 3. Инструкции перемещения данных,
которым доступна внутренняя память

табл3

Инструкции передачи данных включают 16-битовую MOV, которая может инициализировать указатель данных DPTR для табличного обращения к памяти программ или для доступа к внешней памяти данных. Инструкция XCH A,byte обменивает данные между аккумулятором и адресованным байтом. Инструкция XCHD A,@Ri подобна предыдущей, но только обмениваются младшие полубайты.

В табл. 4 изображен простой код, который выполняет сдвиг вправо на один разряд двоично-десятичного числа, используя инструкцию XCHD.

Табл. 4. Сдвиг двоично-десятичного числа
на один разряд вправо

табл4

В этом примере указатели R1 и R0 указывают на два байта, содержащие последние четыре разряда двоично-десятичного числа. Затем цикл переходит на последний байт с адресом 2ЕН, где находятся последние два разряда сдвигаемого числа. Указатели декрементируются, и цикл повторяется для адреса 2DH.

Цикл выполняется от LOOP до CJNE для R1 = 2EH, 2DH, 2CH и 2BH. В этой точке разряд, который первоначально был сдвинут вправо, переместиться в ячейку с адресом 2AH. Так как эта ячейка должна быть слева с нулями, потерянный разряд перемещается в аккумулятор.

Примечание: Инструкция CJNE (Сравнение и переход, если не равно), управляющая циклом, будет описана позже.

6.2. Внешняя память данных

Табл. 5 содержит инструкции перемещения данных, которые осуществляют доступ к внешней памяти данных. В этом случае может применена только косвенная адресация. Для однобайтовой адресации используется @Ri, где Ri может быть R0 или R1 из выбранного банка регистров, для двухбайтовой адресации - @DPTR. Неудобство использования 16-битовой адресации при подключении нескольких Кбайт внешней памяти в том, что 16-битовые адреса используют все 8 бит порта Р2, как у адресной шины. Тогда как 8-битовые адреса позволяют использовать те же несколько Кбайт памяти без жертвования всем портом Р2, используя только его часть для указания страниц памяти по 256 байт. Все эти инструкции выполняются в режиме совместимости за 2 мкс при 12 МГц тактовой частоте.

Табл. 5. Инструкции перемещения данных,
осуществляющие доступ к внешней памяти данных

табл5

Заметим, что во всех обращениях к внешней памяти данных аккумулятор используется либо как цель, либо как источник. Стробы чтения и записи для внешней памяти активируются только в течение выполнения инструкции MOVX. Нормально, эти сигналы не активны и, если инструкция не выполняется, то не используются вовсе, и их выводы доступны как внешние линии ввода-вывода.

6.3. Таблицы обращения к памяти программ

Табл. 6 показывает две инструкции, которые пригодны для чтения таблиц доступа к памяти программ. Так как эти инструкции осуществляют доступ к памяти программ, таблицы могут только читаться и не могут обновляться. Мнемоникой инструкций является MOVC (move constant). Если обращаются к таблице во внешней памяти программ, то генерируется строб чтения PSEN.

Табл. 6. Инструкции чтения таблиц
обращения к памяти

табл6

Первая инструкция MOVC в табл. 6 может работать с таблицей, имеющей до 256 входов с номерами от 0 до 255. Номер используемого входа загружается в аккумулятор, а указатель данных задает точку, указывающую на начало таблицы. Поэтому следующая инструкция копирует содержимое из нужной ячейки таблицы в аккумулятор:

MOVC A,@A+DPTR

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

MOV A,ENTRY_NUMBER

CALL TABLE

Подпрограмма TABLE должна выглядеть, как в следующем примере:

TABLE:

MOVC A,@A+PC

RET

Сама таблица непосредственно следует после инструкции RET (return) в памяти программ. Этот тип таблицы может иметь до 255 входов, пронумерованных от 1 до 255. Номер 0 может не использоваться, так как в это время выполняется инструкция MOVC и PC содержит адрес инструкции RET. Входом, имеющий номер 0 будет сам код операции RET.

7. Булевы инструкции

Микроконтроллеры MCS51 имеют булевый (битовый) процессор. Внутренняя память данных RAM содержит 128 адресуемых бит от 00 до 7FH в пространстве адресов байт от 20Н до 2FH, и пространство регистров специальных функций SFR также поддерживает битовую адресацию. Все линии порта тоже побитно адресуемые, и каждая из них может быть использована как отдельный однобитовый порт. Инструкции, обращающиеся к битам, – не только условные переходы, но и инструкции перемещения, установки, очистки, инвертирования, OR и AND.

Табл. 7. Булевы инструкции

табл7

Набор инструкций булева процессора показан в табл. 7. Все битовые обращения имеют прямую адресацию. Адреса бит от 00H до 7FH находятся в младшем 128 битовом пространстве, а с 80H до FFH – в пространстве SFR.

Следующий пример показывает, как легко внутренний флаг может быть передан в вывод порта.

MOV C,FLAG

MOV P1.0,C

В этом примере FLAG является именем любого адресуемого бита в 128 битовом пространстве или SFR. Линия ввода-вывода (младший бит порта Р1 в данном случае) устанавливается или очищается в зависимости от значения бита флага, который может быть или 1, или 0.

Бит переноса в PSW используется в качестве однобитового аккумулятора булева процессора. Битовые инструкции, которые ссылаются на бит переноса С, ассемблируются как инструкции специфицированные переносом (CLR C и т.п.). Бит переноса может адресоваться прямо, так как он размещается в регистре PSW, который является бит адресуемым. Булевы инструкции включают операции ANL и ORL, но не XRL (исключающее OR). Операция XRL реализуется в программном обеспечении просто. Предположим, например, что приложению требуется выполнить исключающее OR с двумя битами: C = bit1 .XRL. bit2

Программа для этого должна быть следующего вида:

MOV C,bit1

JNB bit2,ОVER

CPL C

OVER: (continue)

Вначале bit1 перемещается в С. Если bit2 = 0, тогда С содержит правильный результат. Это означает, что bit1 .XRL. bit2 = bit1, если bit2= 0. С другой стороны, если bit2 = 1, С тогда содержит дополнение правильного результата. Поэтому для выполнения операции С необходимо инвертировать (CPL C). Эта программа использует инструкцию JNB, одну из серии бит-тестируемых инструкций, которая выполняет переход, если адресуемый бит установлен (JC, JB, JBC), или если адресуемый бит не установлен (JNC, JNB). В вышеописанном случае тестируется bit2, и если bit2 = 0, инструкция CPL C пропускается.

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

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

Адрес назначения для этих переходов специфицируется для ассемблера либо меткой, либо конкретным адресом в памяти программ. Однако при ассемблировании он заменяется байтом относительного смещения. Если выполняется переход, то этот байт со знаком (в арифметическом дополнении) прибавляется к содержимому программного счетчика PC. Диапазон перехода находится в пределах от -128 до +127 байт памяти программ относительно первого байта, следующего после инструкции.

8. Инструкции переходов

В табл. 8 показаны инструкции безусловных переходов. В таблице указана одна инструкция JMP addr, но фактически их три: SJMP, LJMP и AJMP, которые различаются форматом адреса назначения. JMP является основной мнемоникой, которой может воспользоваться программист, когда он не заботится о том, каким образом адрес перехода будет закодирован. Инструкция SJMP кодирует адрес назначения с относительным смещением, как показано выше. Инструкция имеет размер в 2 байта, включая код операции и байт относительного смещения. Инструкция LJMP кодирует адрес назначения как 16-битовую константу. Инструкция имеет размер в 3 байта, включая код операции и двухбайтовый адрес. Адрес назначения может быть в любом месте 64К пространства памяти программ. Инструкция AJMP кодирует адрес назначения как 11-битовую константу. Инструкция имеет размер в 2 байта, включая код операции, который содержит 3 бита 11-битового адреса, и следующий байт, содержащий младшие 8 бит адреса назначения. Когда выполняется инструкция, эти 11 бит просто заменяют младшие 11 бит регистра PC. Старшие 5 бит остаются теми же самыми. Таким образом, адрес назначения должен быть в некотором блоке размером 2К, следующем после инструкции AJMP.

Табл. 8. Безусловные переходы

табл8

Во всех случаях программист специфицирует для ассемблера адрес назначения в виде метки или 16-битовой константы. Ассемблер переводит адрес назначения в нужный формат для данной инструкции. Если требуемый инструкцией формат не поддерживает специфицированный адрес назначения, то в листинге появится сообщение «Destination out of range» (Назначение вне области).

Инструкция JMP @A+DPTR поддерживает вычисляемые переходы. Адрес назначения вычисляется во время выполнения инструкции как сумма 16-битового регистра DPTR и аккумулятора. Обычно DPTR загружается адресом таблицы переходов, а аккумулятор является индексом в таблице. Например, если требуется 5 вариантов перехода, то в аккумулятор загружаются целые числа от 0 до 4. Программа может иметь следующий вид:

MOV DPTR,#JUMP_TABLE

MOV A,INDEX_NUMBER

RL A

JMP @A+ DPTR

Инструкция RL A конвертирует номер индекса (0 – 4) в четное число в диапазоне от 0 до 8, так как каждый вход в таблицу переходов разделен 2 байтами, как показано в следующем примере:

JUMP_TABLE: AJMP CASE_0

AJMP CASE_1

AJMP CASE_2

AJMP CASE_3

AJMP CASE_4

Табл. 8 показывает только одну инструкцию CALL addr, но есть еще две инструкции LCALL и ACALL, которые отличаются форматом определения адреса подпрограммы. Основная мнемоника CALL используется программистом, если его не заботит, каким образом кодируется адрес. Инструкция LCALL использует 16-битовый формат адреса, и подпрограмма может находиться в любом месте 64К пространстве памяти программ. Инструкция ACALL использует 11-битовый формат и подпрограмма должна быть в 2К блоке, следующем после инструкции ACALL. В любом случае программист специфицирует адрес подпрограммы для ассемблера или как метку, или как 16-битовую константу. Ассемблер сформирует адрес в правильном формате для данной инструкции.

Подпрограммы должны заканчиваться инструкцией RET, которая возвращает выполнение программы к инструкции, следующей после CALL. Инструкция RETI используется для возврата из подпрограммы обслуживания прерывания. Отличие между RET и RETI лишь в том, что RETI сообщает системе управления прерыванием об окончании обслуживания прерывания. Если прерывания нет во время выполнения RETI, то тогда RETI функционально идентична RET.

В табл. 9 приведен список условных переходов. Все они осуществляют переход на определенный адрес назначения через относительное смещение и, таким образом, ограничены областью от – 128 до +127 байт, следующей после инструкции условного перехода. Однако пользователь специфицирует ассемблеру нужный адрес назначения тем же образом, что и для других переходов: меткой или 16-битовой константой.

Табл. 9. Условные переходы

табл9

В PSW бит Zero отсутствует. Для определения этого условия инструкции JZ и JNZ тестируют аккумулятор. Инструкция DJNZ (Decrement and Jump if Not Zero – декремент и переход, если не ноль) является управляющей для циклов. Чтобы выполнить цикл N раз, надо загрузить счетчик числом N и закончить цикл DJNZ, передающим управление в начало цикла, как показано ниже для N = 10:

MOV COUNTER,#10

LOOP: (начало цикла)

*

*

(конец цикла)

DJNZ COUNTER,LOOP

(продолжение)

Инструкция CJNE (Compare and Jump if Not Equal – сравнение и переход, если не ноль) может также использоваться для управления циклом, как показано в табл. 2.4. Два байта специфицируются в поле операндов инструкции. Переход выполняется только, если два байта не равны. В примере два байта были данными в регистре R1 и константа 2AH. Начальное значение содержимого R1 было 2EH. Каждый раз при выполнении цикла R1 декрементируется, и цикл продолжается до тех пор, пока оно не станет равным 2AH.

Другое применение этой инструкции для сравнений «больше, чем», «меньше, чем». Два байта в поле операндов берутся как беззнаковые целые числа. Если первое меньше второго, тогда бит переноса Carry устанавливается в 1. Если первый больше второго, или равен, то бит переноса очищается.