Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Директивы языка программирования ASM-51

Поиск

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

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

При чтении программы трудно отличить константы от переменных, ведь в командах они отличаются только видом адресации. Это приводит к увеличению времени написания программы, так как каждый раз приходится решать загадку: что же подразумевалось под конкретной цифрой — переменная, константа или маска?

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

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

Правда за использование идентификатора именно в качестве переменной отвечает программист. Если он попытается использовать адрес переменной как константу, то транслятор не выдаст никакого сообщения об ошибке. Он спокойно оттранслирует оператор. При использовании назначения адресов переменных при помощи директивы equ, изменение адреса при необходимости можно сделать в одном месте программы, а не просматривать всю программу, судорожно пытаясь вспомнить, где же еще была использована эта ячейка памяти. Все необходимые изменения в машинном коде программы сделает сам транслятор!

Пример назначения имен переменных с использованием директивы equ приведен в листинге 23.4.

Листинг 23.4. Назначение имен констант и адресов переменных при помощи директивы equ

FuncSet equ 0x20

_8bit equ 0x10

 

DispDat equ P0;Шина данных ЖКИ

RDS equ P1_2;Чтение команды ЖКИ

RW equ P1_1;Сигнал выбора записи/чтения

E equ P1_0;Строб синхронизации ЖКИ

 

mov DispDat,#(FuncSet or _8bit);Выставить на шине данных

setb E;команду установки функции

clr E;и выдать стробирующий сигнал

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

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

В приведенном в листинге 23.4 примере имена FuncSet и _8bit являются константами, но это становится понятным только по использованию непосредственной адресации в команде mov.

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

Директива set. Если требуется в различных местах программы назначать одному и тому же идентификатору различные значения, то нужно пользоваться директивой set. Она используется точно так же, как директива equ, поэтому иллюстрировать это примером не будем.

Константы, назначаемые директивами equ или set, могут быть использованы только в качестве операндов команд микроконтроллера. В то же время достаточно часто требуется работа с таблицей констант, такой, как таблица перекодировки, таблицы элементарных функций или синдромы помехоустойчивых кодов. Такие константы используются не на этапе трансляции для формирования машинного кода инструкций, а при исполнении программы. Они заносятся в память программ микроконтроллера. Для помещения значений констант в память программ микроконтроллера используются директивы db и dw.

Директива db используется для занесения в память программ однобайтных констант. Пример использования директивы db приведен в листинге 23.5.

Листинг 23.5. Создание таблицы констант при помощи директивы db

Decod:

mov DPTR,#TabDecod

movc A,@A+DPTR

ret

 

TabDecod:;-abcdefg

DB 01111110b;символ ‘0’ Расположение сегментов в

DB 00110000b;символ ‘1’ семисегментном индикаторе

DB 01101101b;символ ‘2’ a

DB 01111001b;символ ‘3’ ---

DB 00110011b;символ ‘4’ f| |b

DB 01011011b;символ ‘5’ ---

DB 01011111b;символ ‘6’ e| |c

DB 01110000b;символ ‘7’ ---

DB 01111111b;символ ‘8’ d

DB 01111011b;символ ‘9’

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

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

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

Листинг 23.6. Применение директивы db для размещения строк в памяти программ микроконтроллера

mov R7,#(EndNadp-NadpSvjazUst);Занести количество символов в строке

mov DPTR,#NadpSvjazUst;Подготовиться к передаче первого символа

 

PrdSledSmv:

clr A;

movc A,@A+DPTR;Считать очередной символ надписи

inc DPTR;

 

call PrdSmv;Передать очередной символ надписи и

djnz R7,PrdSledSmv;если это был последний символ надписи

ret;то выйти из подпрограммы

 

NadpSvjazUst: db ‘Связь установлена’,10,13

EndNadp:

Директива dw позволяет заносить в память программ двухбайтные числа. В ней, как и в директиве db, можно записывать несколько чисел, разделенных запятой. Пример фрагмента программы приведен в листинге 23.7.

Листинг 23.7. Применение директивы dw

0016 0001 264 dw 1,2,0abh,'a','QW'

0018 0002

001A 00AB

001C 0061

001E 5157

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

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

Листинг. 23.8. Начальный участок программы

LOC OBJ LINE SOURCE

 

0000 78FF 1 mov R0,#255;Обнулить 255 ячеек памяти

0002 E4 2 clr A

0003 3 ClrOZU:

0003 F6 4 mov @R0,A;Обнулить очередную ячейку памяти

0004 D8FD 5 djnz R0,ClrOZU;Если все ячейки обнулены

6;то продолжить выполнение программы

Иногда нужно расположить команду по определенному адресу. Наиболее часто это требуется при использовании прерываний, когда первая команда подпрограммы-обработчика прерываний должна быть расположена точно в ячейке с определенным адресом (вектором), зависящем от источника прерывания. Векторы размещаются в начальных ячейках программной памяти и занимают 8 байтов каждый. Если эта область не используется целиком, то можно использовать команду nop для заполнения промежутков между векторами прерывания. Но лучше для назначения нужных адресов подпрограммам прерываний воспользоваться директивой org.

Директива org предназначена для записи в счетчик адреса сегмента значения своего операнда. То есть при помощи этой директивы можно разместить команду (или данные) в памяти микроконтроллера по произвольному адресу. Пример использования директивы org для размещения подпрограмм обработки прерываний в нужных адресах показан в листинге 23.9.

Листинг 23.9. Пример использования директивы org

reset:

ljmp main

 

;Перезагрузка таймера-----------------------------------------

ORG AT 0bh;Вектор прерывания от таймера 0

IntT0:

mov TL0, #LOW(-(F_ZQ/12)*10-2);Настроить таймер

mov TH0, #HIGH(-(F_ZQ/12)*10-2);на период 10мс

reti

 

;Начало основной программы микроконтроллера -------------------------

rseg _code

main:

mov SP,#VershSteka;Настроить указатель стека на вершину стека

lcall init;Настроить микроконтроллер

;--------------------------------------------------------------------

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

Директива using. При использовании прерываний критичным является время выполнения подпрограммы-обработчика прерываний. Его можно значительно сократить, выделив для обработки прерываний отдельный банк регистров при помощи директивы using. Номер используемого банка регистров указывается в директиве в качестве операнда. При этом реальное включение банка регистров производится записью необходимой константы в регистр PSW. Пример использования директивы using для подпрограммы обслуживания прерываний от таймера 0 приведен в листинге 23.10.

Листинг 23.10. Пример использования директивы using

USING 2;Использовать второй банк регистров

IntT0:

push PSW;Сохранить содержимое слова состояния микроконтроллера

push ACC;Сохранить содержимое аккумулятора

mov PSW,#00010000B;Включить второй банк регистров

 

mov TL0, #LOW(-(F_ZQ/12)*10-2);Настроить таймер

mov TH0, #HIGH(-(F_ZQ/12)*10-2);на период 10мс

pop ACC;Восстановить содержимое аккумулятора

pop PSW;Восстановить содержимое слова состояния микроконтроллера

reti

Остальные директивы ассемблера предназначены для управления сегментами памяти и будут рассмотрены позднее.

УПРАВЛЯЮЩИЕ КОМАНДЫ

Кроме директив, для управления процессом трансляции используются команды языка программирования. С их помощью можно управлять работой компилятора ASM-51. Команды могут задаваться как параметры в DOS-строке вызова компилятора, или как управляющие строки в исходном тексте файла.

Если знак доллара ($) стоит в самом крайнем левом поле строки, то такая строка воспринимается компилятором как управляющая. Управляющие строки должны начинаться знаком доллара и могут содержать одну или более команд, разделенных пробелами.

Примеры управляющих строк:

$PRINT(A:\PROG.LST) OBJECT(PROG.OBJ)

$LIST DEBUG XREF

Так как целью книги является дать минимальные сведения, достаточные для того, чтобы начать работать с микроконтроллерами, то в данной книге будут рассмотрены только основные команды языка программирования ASM-51.

Команда include. Это, пожалуй, наиболее часто используемая команда языка программирования ASM‑51. Она позволяет включать в состав программы участки текста из другого файла. Это удобно при многофайловом написании программы, например, для того, чтобы вынести описания внутренних регистров микроконтроллера в отдельный файл. Пример использования команды include для включения файла описания внутренних регистров микроконтроллера 89с51 выглядит следующим образом:

$INCLUDE (REG51.INC)

При использовании этой команды все содержимое включаемого файла помещается в выходной листинг программы, в результате чего становится трудно читать этот листинг. Поэтому в состав команд языка программирования ASM‑51 включены команды list/nolist.

Команды list/nolist позволяют включать и выключать листинг исходного текста соответственно. При активной команде nolist в файл листинга будут помещаться только сообщения об ошибках. Пример запрета размещения содержимого включаемого файла в листинге программы будет выглядеть следующим образом:

$NOLIST //Запретить создание листинга включаемого файла

$INCLUDE (REG51.INC)

$LIST //Разрешить создание листинга дальнейшего текста

Команда debug/nodebug позволяет помещать в объектный модуль отладочную информацию (имена и местоположение переменных, меток и операторов) или запрещать размещение отладочной информации в объектном модуле.

Команда pagelength(n) определяет максимальное число строк на странице файла листинга. Это число включает заголовок страницы. Количество строк в странице может изменяться в пределах от 10 до 65535

Команда pagewidth(n) определяет максимальное число символов в строке листинга. Количество символов в строке листинга может изменяться от 72 до 132.



Поделиться:


Последнее изменение этой страницы: 2017-02-07; просмотров: 410; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.119.124.204 (0.008 с.)