Система команд микроконтроллеров MCS-51 и основы программирования на языке Ассемблер
PAGE 13
Дисциплина «Микроконтроллеры в системах управления», 3-й курс, семестр 6. Модуль 2 Тема 3
Модуль 2 Тема 3 Система команд микроконтроллеров MCS-51
и основы программирования на языке Ассемблер
3.1 Характеристика системы команды микроконтроллеров MCS-51
Микроконтроллеры семейства MCS-51 относятся к классу процессоров с аппаратным принципом управления. Это значит, что набор элементарных действий процессора по обработке данных является фиксированным и полностью определяется аппаратной структурой дешифратора команд и блока управления.
Каждому элементарному действию процессора поставлен в соответствие двоичный код так называемый код операции (КОП). Чтение кода операции из памяти программ в процессор вызывает выполнение вполне определенных действий.
Каждая команда несет в себе два “сообщения” для процессора:
- действие, которое нужно выполнить зашифровано в коде операции;
- как получить операнды для выполнения этого действия эта информация содержится в адресной части команды.
Таким образом, команда это многобитовое двоичное число, состоящее из двух информационных полей:
Количество битов, занимаемых каждым полем, может быть различным в разных командах, но в целом не менее одного байта. В некоторых командах адресная часть может отсутствовать.
Содержимое адресной части зависит от метода адресации операндов, который использован в конкретной команде. Набор методов адресации также фиксирован.
Таким образом, система команд процессора это совокупность допустимых кодов операции и способов адресации данных.
!!! Для удобства составления программ каждому двоичному коду операции поставлено в соответствие буквенное обозначение команды т.н. мнемоника команды.
Например:
- все операции пересылки данных имеют мнемонику MOV, независимо от способа адресации данных;
- все типы операций суммирования мнемоника ADD;
- все операции логического умножения мнемоника ANL;
- все виды безусловных переходов мнемоника JMP.
Адресная часть команды записывается через пробелы после мнемоники. Если операндов два, то первым указывается приемник данных, а вторым источник.
Используются четыре основных способа адресации:
Регистровая в адресной части содержится номер регистра, из которого нужно взять операнд. Речь идет о регистрах активного банка с именами R0 R7. Команды с регистровой формой адресации самые короткие.
Например, пересылка содержимого регистра R5 в регистр-аккумулятор:
Могут быть пересылки и в другую сторону, например: MOV R6, A
Суммирование содержимого аккумулятора с содержимым регистра R4.
Результат операции будет помещен в аккумулятор: (A) (A) + (R4)
Непосредственная в адресной части содержится значение операнда, которое будет помещено в ячейку-приемник (или регистр-приемник). Операнд с таким способом адресации в команде отмечается символом #.
Например: пересылка значения 28 в регистр-аккумулятор:
Пересылка значения 42 в регистр R7 эта команда сочетает в себе регистровую и непосредственную адресации:
Заметим, что команды с непосредственным способом адресации всегда двухбайтовые (есть даже один трехбайтовый вариант).
Прямая в адресной части команды содержится адрес ячейки памяти в РПД, из которой нужно взять операнд, или в которую нужно отправить значение. Адреса принято указывать в шестнадцатеричной системе счисления.
Например: пересылка значения из ячейки РПД с адресом 54H в регистр-аккумулятор:
Пересылка содержимого регистра R3 в ячейку РПД с адресом 24H. В этой команде сочетаются прямая и регистровая формы адресации:
Пересылка из ячейки РПД с адресом 15H в ячейку РПД с адресом 62H. Эта команда содержит в адресной части два байта, а в целом является трехбайтовой. Источник и приемник данных заданы через прямую адресацию. В машинном представлении команды сначала следует байт с адресом источника данных.
Косвенно-регистровая в адресной части команды содержится номер регистра, из которого нужно взять адрес операнда. Затем происходит обращение к ячейке с этим адресом для чтения или записи операнда. Речь идет об указательных регистрах активного банка с именами R0 и R1. В качестве указателя данных во внешней памяти можно использовать регистр DPTR.
Особенность таких команд в том, что адрес операнда явно не присутствует в команде. Этот адрес зависит от текущего содержимого регистра, который указан в адресной части команды.
Например: пересылка из ячейки, адрес которой содержится в регистре R0, в регистр-аккумулятор.
Если текущее содержимое регистра (R0) = 34H, а в ячейке с адресом 34H содержит число 15, то в результате выполнения такой команды в аккумулятор будет переслано значение 15.
Пересылка из ячейки РПД с адресом 47H в ячейку РПД, на которую указывает регистр R1 (т.е. адрес этой ячейки содержится в регистре R1).
В этой команде сочетаются косвенно-регистровый и прямой способы адресации. Также могут быть варианты с объединением непосредственного и прямого, непосредственного и косвенного способов адресации. Нет команд с пересылкой регистр-регистр (т.е. нельзя переслать, например, непосредственно из R3 в R5).
Также могут быть команды без адресной части. Например, команда возврата из подпрограммы RET:
3.2 Особенности выполнения команд микроконтроллером
Синхронизация действий процессора и выполнение команд обеспечиваются генератором тактовых импульсов в составе МК. Внешний резонатор ZQ (рис. 2.5-а) задает частоту тактовых импульсов FQ. Базовое значение FQ = 12 МГц, хотя можно использовать резонаторы с другими значениями (24 МГц, 11.0592 МГц).
Интервал времени, который процессор тратит на выполнение одной элементарной команды, называют машинным циклом (МЦ). В микроконтроллерах MCS-51 длительность МЦ фиксирована и составляет ТМЦ = 12 / FQ. Длительность машинного цикла определяется импульсами от внутреннего генератора тактовых импульсов (ГТИ) см. рис.2.1. Частота импульсов от ГТИ FГТИ = FQ / 12.
При FQ = 12 МГц длительность МЦ ТМЦ = 1 мкс.
Некоторые команды выполняются за два МЦ, некоторые за четыре.
Выходной сигнал ALE формируется два раза за МЦ, т.е. FALE = FQ / 6. При нормальном функционировании МК этот сигнал можно наблюдать на выводе 30.
В каждом МЦ происходит чтение одного или двух байтов команды из памяти программ в зависимости от формата команды.
Адрес ячейки памяти программ, из которой будет прочитан очередной байт команды, формируется в регистре PC (т.е. РС := РС+1) и из этого регистра выдается на шину адресации. Это действие происходит автоматически.
Действия процессора по выполнению команды показаны на рис. 3.1.
Рисунок 3.1 Цикл выполнения команды микроконтроллером
3.3 Выполнение арифметических и логических команд
Микроконтроллер MCS-51 выполняет все арифметические и логические операции через регистр-аккумулятор один из операндов должен находиться в аккумуляторе, и результат также помещается в аккумулятор. Например:
ADD A, R2 |
(A) (A) + (R2) |
ADD A, 54H |
(A) (A) + (54H) |
ADD A, #23 |
(A) (A) + 23 |
ADD A, @R1 |
(A) (A) + ((R1)) |
ANL A, 54H |
(A) (A) & (54H) |
ORL A, 54H |
(A) (A) or (54H) |
где (х) содержимое ячейки памяти или регистра с адресом или именем х.
Для логических операций возможно помещение результата в ячейку операнда:
ORL 47H, A |
(47H) (47H) or (A) |
ANL 34H, #57 |
(34H) (34H) & 57 |
В результате выполнения арифметической операции получается не только численный результат, но и набор битовых признаков, которые характеризуют этот результат. Все эти битовые признаки фиксируются в специальном регистре PSW, который принято называть регистром флагов. Регистр PSW относится к области РСФ и имеет следующую битовую структуру:
Признак |
Бит |
Назначение |
|||
С |
PSW.7 |
Флаг переноса. Изменяется аппаратно при выполнении арифметических, логических и битовых операций; фиксирует перенос из старшего разряда результата; также может быть изменён программно |
|||
AC |
PSW.6 |
Флаг вспомогательного переноса. Изменяется аппаратно при выполнении команд суммирования и вычитания в случае возникновения переноса или заёма в бите 3 аккумулятора |
|||
F0 |
PSW.5 |
Свободный флаг. Может быть изменен программно и используется по назначению, установленному программистом |
|||
RS1 RS0 |
PSW.4 PSW.3 |
Выбор банка регистров. Биты можно изменять программно для выбора активного (рабочего) банка регистров: |
|||
RS1 |
RS0 |
Активный банк |
Адреса РПД |
||
0 0 1 1 |
0 1 0 1 |
0 1 2 3 |
00Н-07Н 08Н-0FH 10H-17H 18H-1FH |
||
OV |
PSW.2 |
Флаг переполнения. Изменяется аппаратно при выполнении арифметических операций в случае арифметического переполнения аккумулятора. Дает возможность корректно выполнять действия над числами, представленными в дополнительном коде |
|||
|
PSW.1 |
Не используется. Программно недоступен |
|||
P |
PSW.0 |
Флаг паритета (флаг контроля четности). Изменяется аппаратно в каждом цикле выполнения команды, фиксирует факт нечетного количества "1" в аккумуляторе |
В различных семействах микропроцессоров набор флагов может отличаться. Например, в процессорах семейства 80х86 есть признак нулевого результата ZF.
3.4 Выполнение команд перехода (передачи управления)
Общая особенность команд перехода (иногда их называют командами передачи управления) это принудительное изменение содержимого регистра РС. Цель такого изменения перейти к выполнению команды, которая находится в памяти
не сразу после текущей команды.
Простейшая команда безусловного перехода JMP <адрес>
(команда эквивалентна оператору Паскаля goto <метка>). Пусть для примера, фрагмент программы начинается с адреса 2010h.
Пример |
Адрес |
Код команды |
РС до |
РС после |
Комментарии |
m1: MOV A, P1 |
2010h |
E5 90 |
2010h |
2012h |
Чтение с порта Р1 |
ADD A, R0 |
2012h |
28 |
2012h |
2013h |
(А) (A) + (R0) |
MOV R3, A |
2013h |
FB |
2013h |
2014h |
(R3) (A) |
LJMP m1 |
2014h |
02 20 10 |
2014h |
2010h |
(РС) 2010H |
В командах удобно адреса заменять на символьные метки
Команды условных переходов реализуют разветвления в программе выполнение групп операторов при выполнении или невыполнении различных условий.
Алгоритмически условия выглядят, например, так:
если K>N, то D=20, иначе D = 10.
На уровне машинных команд нужно сначала сформировать признаки арифметической операции, а затем проверить подходящий флаг:
- вычислить (K-N); при этом, если KN, то флаг С=0,
если K<N, то флаг С=1. - проверить флаг C и перейти к нужным командам, иначе выполнять операторы другой алгоритмической ветви.
Алгоритм |
Пример |
Адрес |
Код команды |
РС до |
РС после |
mov A, K |
2010h |
E5 30 |
2010h |
2012h |
|
subb A, N |
2012h |
95 31 |
2012h |
2014h |
|
jc m1 |
2014h |
40 06 |
2014h |
Зависит |
|
mov D, #20 |
2016h |
75 32 14 |
2016h |
2019h |
|
jmp m2 |
2019h |
02 20 1F |
2019h |
201Fh |
|
m1: mov D, #10 |
201Ch |
75 32 0A |
201Сh |
201Fh |
|
m2: … |
201Fh |
… |
Особенность выполнения команд условного перехода (в примере JC m1) в том, что при компиляции вместо метки в коде команды задается не абсолютный адрес перехода, а относительное смещение:
- при выполнении условия, т.е. если на момент выполнения команды C = 1, то результатом команды будет (PC) (PC) + 2 + <смещение>; т.е. в РС формируется адрес «прыжка»;
- при невыполнении условия, т.е. если на момент выполнения команды C = 0, то результатом команды будет (PC) (PC) + 2, т.е. адрес команды, следующей по расположению в памяти.
3.5 Стек и особенности выполнения команд, работающих со стеком
Стек - участок оперативной памяти, для работы с которым программист использует протокол последовательного доступа к данным в отличие от протокола произвольного доступа, применяемого при работе с обычными областями памяти. Принцип данного протокола описывается фразой: первый зашел последний вышел. (first input - last output FILO). Таким образом, информация, занесенная в стек в первую очередь, в соответствии с принятым протоколом доступа, может быть считана только в последнюю очередь.
В процессорt есть специальный регистр указатель стека SP (stack pointer). Этот регистр адресует ячейку памяти, которая является текущей вершиной стека. Все ячейки стека, расположенные выше вершины, считаются свободной областью стека, а расположенные ниже занятой областью. Указатель стека SP содержит адрес той ячейки стека, в которую была выполнена последняя запись.
Дно стека это ячейка памяти, которая является нижней границей стека, с этой ячейки начинается заполнение стека в процессе работы программы. При записи в стек либо считывании из стека содержимое регистра SP должно изменяться.
В системе команд любого процессора имеются две специальные команды, предназначенные для работы со стеком. Они автоматически используют и изменяют содержимое регистра SP:
Занести данные в стек PUSH Прочитать данные из стека POP
Эти команды выполняют пересылку данных между областью стека и какой-либо ячейкой РПД, указанной в команде. Схемы на рис. 3.2 и 3.3 иллюстрируют процесс выполнения команд PUSH и POP.
Рисунок 3.2 Пример выполнения команды PUSH 20h и состояние ячеек памяти:
а) до выполнения команды; б) после выполнения команды
Рисунок 3.3 Пример выполнения команды POP 30h и состояние ячеек памяти:
а) до выполнения команды; б) после выполнения команды
3.6 Выполнение команд вызова подпрограммы и возврата
Команда вызова подпрограммы это разновидность команд передачи управления, т.е. команд, при выполнении которых принудительно изменяется содержимое счетчика команд PC. Особенность состоит в том, перед изменением текущее содержимое PC автоматически сохраняется в стеке. Сохраненное содержимое регистра PC принято называть адресом возврата (или адресом точки возврата).
Команда вызова подпрограммы имеет традиционную мнемонику
CALL <адрес перехода>. Мнемоника команда возврата из подпрограммы RET. Данная команда не имеет адресной части. Указанные мнемоники использованы в системе команд практически всех микропроцессоров.
Схема на рис.3.4 иллюстрирует процесс выполнения команды CALL, а на рис.3.5 показан процесс выполнения команды возврата из подпрограммы RET.
Рисунок 3.4 Действия при выполнении команды CALL <адрес перехода>
H (high) старший байт адреса; L (low) младший байт адреса;
AdrP адрес подпрограммы; AR условное обозначение адреса возврата
При чтении всех байтов команды CALL из памяти в регистре PC формируется адрес следующей команды, который является адресом возврата (AR) в основную программу. В ходе выполнения команды CALL это значение пересылается в стек, при этом выполняется необходимое изменение содержимого регистра SP (см. принцип выполнения команды PUSH). После этого новое значение адреса (AdrP), взятое из адресной части команды CALL, записывается в регистр PC. За счет этого реализуется переход («прыжок») на подпрограмму с возможностью последующего возврата к основной программе.
Рисунок 3.5 Действия при выполнении команды RET
По команде RET содержимое ячеек в вершине стека считывается в регистр PC, и тем самым реализуется передача управления (т.е. «прыжок»). После чтения из стека содержимое регистра SP изменяется так, как при выполнении команды POP. Важно отметить, что при выполнении команды RET фактическое значение содержимого вершины стека никак не контролируется, таким образом, за правильность возврата отвечает программист.
3.7 Правила оформления программы на языке Ассемблер МК MCS-51
Программа на языке ассемблер состоит из строк, каждая из которых соответствует одной команде:
[ МЕТКА: ] <мнемоника команды> операнды [ ; комментарии ]
[ ] поле может отсутствовать.
Для указания системы счисления, в которой задается число, используют буквенные индексы после самого числа: B двоичная, Q восьмеричная, D или ничего десятичная, H шестнадцатеричная.
Программа обычно состоит из декларативной и исполнимой частей. В декларативной части объявляют имена для констант, выделяют память для переменных. В этой части не могут присутствовать исполнимые команды.
В исполнимой части программы присутствуют команды с операндами. В операндах можно использовать объявленные имена констант и переменных, а также имена всех системных регистров микроконтроллера.
Директивы определения имен
Директива EQU любому имени ставится в соответствие выражение.
Формат директивы: <имя> EQU <выражение>
Например: z1 equ 10
z2 equ z1 + 4
z3 equ z1 + z2 + 5
Имена, определенные директивой EQU, можно использовать как адрес кода, адрес данных (внутренних или внешних) или значение данных. Например:
MOV A, #z1 ; Загрузка числа 10 в аккумулятор
MOV A, z1 ; Пересылка в аккумулятор из ячейки с адресом 0AH
Директива DATA задает имя для адреса данных в РПД.
Формат директивы: <имя> DATA <адресное выражение>
Директива XDATA задает имя для адреса внешних данных (ВПД).
Формат директивы: <имя> XDATA <адресное выражение>
Директива BIT задает имя для адреса бита из области внутреннего ОЗУ с битовой адресацией.
Формат директивы: <имя> BIT <адрес бита>
Например: control DATA 2AH
f1 bit control.3 ; Адрес в виде битового селектора
f2 bit f1 + 4 ; Адресное выражение
f3 bit 60H ; Абсолютный адрес
Примеры удобного использования символических имен:
counter DATA 20H flag BIT P1.7
. . . on BIT 30H
MOV counter, 10 . . .
m1: < действия в цикле > SETB on
. . . wait: JNB flag, wait
DJNZ counter, m1 CLR on
Директивы управления сегментами программы
Эти директивы указывают, что начинается новый сегмент программы:
CSEG - начало сегмента кодов (память программ);
DSEG - начало сегмента для размещения данных в ОЗУ РПД;
XSEG - начало сегмента для размещения внешних данных (ВПД).
Управление текущим адресом сегмента
Формат директивы: ORG < адресное выражение >
Эта директива указывает, с какого адреса компилятор должен разместить в памяти команды программы или данные текущего сегмента.
Например, наличие в программе директив:
CSEG
ORG 2000h
mov a,R0
add a,r3 и т.д.
указывает компилятору, что код команды mov a,R0 и все последующие нужно разместить в памяти программ, начиная с адреса 2000h.
Директивы инициализации памяти DB, DW заполняют байт или слово (2 байты) указанным значением. Используют для размещения значений констант в сегменте кодов (т.е. в памяти программ):
[ имя: ] DB <значение> [ имя: ] DW <значение>
Директива резервирования (выделения) памяти DS для переменной в сегменте внешних или внутренних данных (ВПД или ОЗУ РПД):
[ имя: ] DS <количество байт>
Операторы периода трансляции
Для удобства записи команд и директив в языке Ассемблер допускается задавать числовые значения и адреса памяти в виде выражений, которые вычисляются. Значение такого выражения будет определено компилятором еще во время трансляции, а в код команды будет подставляться только результат этих действий. Допустимыми операциями являются: +, -, *, /, (), AND, OR, XOR, NOT, Low выделение младшего байта, High выделение старшего байта из двухбайтового выражения.
Примеры использования выражений:
1) X equ 10 ; Объявлено число X = 10
Y equ X + 2 ; Объявлено вычисляемое число Y = 12
Z equ (X + Y) * 4 ; Объявлено вычисляемое число Z = 88
2) DSEG
org 70H
V1: ds 4 ; Выделение памяти для четырехбайтовой переменной
CSEG
MOV A, V1+1 ; Чтение в ACC второго байта переменной V1
3) X equ 3704 ; Объявление двухбайтового числа
. . .
MOV R0, #Low(X) ; Запись младшего байта числа X в регистр R0
MOV R1, #High(X) ; Запись старшего байта числа X в регистр R1
В данных материалах представленные только те директивы Ассемблера, которые будут использоваться в программах для лабораторных работ.
Полный перечень команд МК MCS-51 с необходимыми комментариями и указанием особенностей использования представлен в пособии «Микроконтроллерные системы: структуры и практическое применение. Часть 1».
3.8 Технология разработки ПО для микроконтроллеров
В целом технология разработки ПО для МК похожа на проектирование ПО для традиционных компьютеров. Но для МК базовым исходным языком создания программ часто является язык Ассемблер, всегда ориентированный на МК определенного семейства (MCS-51, AVR, PIC и др.).
В случае использования языков высокого уровня (Си, Паскаль) для разработки ПО МК приходится применять специализированные компиляторы, которые учитывают регистровую архитектуру и систему команд МК конкретного семейства. Базовая технология разработки ПО МК показана на рис.3.6.
Рисунок 3.6 Технология разработки ПО МК с использованием ИСР
Загрузчик программы в МК это специальный модуль, который выполняет пересылку байтов исполнимой программы с инструментального компьютера в память МК через стандартизированные интерфейсы (например, SPI или USB), соблюдая при этом требуемый протокол физического программирования МК. Практически все современные микроконтроллеры содержат память программ, выполненную как Flash, поэтому физическая загрузка исполнимой программы может выполняться непосредственно с компьютера через COM- или LPT-порты.
Симулятор выполнения (имитатор работы МК) позволяет проводить автономное тестирование разработанной прикладной программы без физического микроконтроллера, т.е. на основе его логической модели, входящей в состав ИСР.
Современная тенденция в разработке ПО для контроллеров состоит в использовании т.н. графических инженерных языков FBD (Functional Block Diagram) и FC (Flow Chart). В этом случае прикладной проект может быть сформирован как набор схем алгоритмов. Для реализации такой возможности в состав ИСР (не всех) входят специальные графические редакторы и генератор текстовых эквивалентов графических программ.
На лабораторных работах в рамках дисциплин 3-го, 4-го и 5-го курсов будут изучены как традиционная технология на основе разработки исходного текста, так и с применением графического (визуального) программирования для МК.
Автор конспекта Джулгаков В.Г., доцент каф. 301
Система команд микроконтроллеров MCS-51 и основы программирования на языке Ассемблер