Основным инструментом для профессиональной
Для
Программа MPASM может использоваться для двух целей:
Исполняемый код является для MPASM выходным кодом по умолчанию. При этом все переменные источника должны быть явно описаны в тексте программы или в файле, подключаемом с помощью директивы INCLUDE <filename>. Если при ассемблировании не выявляется ошибок, то генерируется выходной .
При использовании
Программы MPASM и MPLINK доступны через оболочку MPASM, тогда как MPLIB доступна только со своей командной строки.
Исходным файлом для .. Текст исходного файла должен соответствовать требованиям синтаксиса, приведенным далее.
MPASM [/<Option>[ /<Option>...]] <file_name>
где /<Option> означает выбор режима работы <file_name> – имя файла на ассемблирование.
Режимы работы
| Выбор | Значение по умолчанию | Описание |
|---|---|---|
| ? | N/A | Вызвать помощь |
a |
INHX8M | Генерировать абсолютный . |
c |
On | Выбрать/запретить чувствительность к регистру |
e |
On | Выбрать/запретить |
h |
N/A | Отобразить панель помощи MPASM |
l |
On | Выбрать/запретить файл листинга, генерированный из макроассемблера. |
m |
On | Вызвать/запретить макрорасширение |
o |
N/A | Установить путь для /o<path>\object.file |
p |
None | Установить тип процессора: /p<processor_type> ; |
q |
Off | Разрешить/Запретить скрытый режим (запретить вывод на экран) |
r |
Определяет тип числа по умолчанию: /r< |
|
w |
0 | Определяет уровень 0 – сообщать все, 1 – сообщать о предупреждениях и ошибках, 2 – сообщать только об ошибках. |
x |
Off | Разрешить/запретить перекрестные ссылки в файле листинга. |
Здесь и далее используются следующие соглашения по использованию символов:
[ ] – для аргументов по выбору;< > – для выделения специальных ключей <TAB>, <ESC> или дополнительного выбора;| – для взаимоисключающих аргументов (выбор ИЛИ);Выбор по умолчанию, приведенный в табл. 6.1, может быть изменен командной строкой:
/<option> разрешает выбор;/<option>+ разрешает выбор;/<option> – запрещает выбор.Исходный ассемблерный файл создается с использованием любого ASCII текстового редактора. Каждая строка исходного файла может содержать до четырех
Порядок и положение каждого типа имеет значение. Метка должна начинаться в колонке номер один. Мнемоника может начинаться в колонке два или далее. Операнды идут за мнемоникой. Комментарий может следовать за операндом, мнемоникой или меткой или может начинаться в любом столбце, если в качестве первого не пустого символа используется * или ;.
Максимальная длина строки 255 символов.
Один или несколько пробелов должны отделять метку и мнемонику или мнемонику и операнд(ы). Операнды могут отделяться запятой. Например:
List p=16C54, r=HEX
ORG 0x1FF ;Вектор сброса
GOTO START ;Возврат на начало
ORG 0x000 ;Адрес начала исполнения
;программы
START
MOVLW 0x0A ;Выполнение программы
;PIC МК
MOVLW 0x0B ;Выполнять всегда
GOTO START
END
В поле метки размещается
Метка может начинаться с символа или нижнего тире ( _ ) и содержать буквенные символы, числа, нижние тире и знак вопроса. Длина метки может быть до 32 символов.
Мнемоники представляют собой мнемонические обозначения команды, которые непосредственно транслируются в машинный код. Мнемоники ассемблерных инструкций, директивы
В этом поле определяются операнды (или операнд), участвующие в операции. Операнды должны быть отделены от мнемоники одним или более пробелами или табуляцией. Операнды отделяются друг от друга запятыми. Если операция требует фиксированного количества операндов, то все на линии после операндов игнорируется. Комментарии разрешаются в конце линии. Если мнемоники позволяют использовать различное число операндов, конец списка операндов определяется концом строки или комментарием.
Выражения используются в поле операнда и могут содержать константы, символы или любые комбинации констант и символов, разделенных арифметическими операторами. Перед каждой константой или символом может стоять + или –, что указывает на положительное или отрицательное выражение.
В
Текстовая строка – это последовательность любых допустимых ASCII символов (в десятичном диапазоне от 0 до 127), заключенная в двойные кавычки. Строка может иметь любую длину в пределах 132 колонок. При отсутствии ограничения строки она считается до конца линии. Если строка используется как буквенный операнд, она должна иметь длину в один символ, иначе будет ошибка.
Числовая константа представляет собой число, выраженное в некоторой системе счисления. Перед константой может стоять + или –. Непосредственные величины в константах рассматриваются как 32-разрядные целые без знака.
MPASM поддерживает следующие системы счисления (представления значений или
Операторы – это арифметические символы, подобные + и –, которые используются при формировании выражений. Каждый оператор имеет свой приоритет. В общем случае приоритет устанавливается слева направо, а выражения в скобках вычисляются первыми. В табл. 6.3 приведены обозначения, описания и примеры применения основных операторов MPASM.
| Тип | Синтаксис | Пример |
|---|---|---|
| Десятичная | D'<цифры>' или .<цифры> |
D'100' или .100 |
| 16-ричная | H'<цифры>' или 0x<цифры> |
H'9f' или 0x9f |
| Восьмиричная | O'<цифры>' |
O'777' |
| Двоичная | B'<цифры>' |
B'00111001' |
| Символьная | '<символ>' или A'<символ>' |
'C' или A'C' |
| Оператор | Описание | Пример |
|---|---|---|
$ |
Текущий |
goto $ + 3 |
( |
левая скобка | 1 + ( d * 4 ) |
) |
правая скобка | ( lenght + 1 ) * 255 |
| ! | операция "НЕ" (логическая инверсия) | if ! ( a - b ) |
~ |
дополнение | flags = ~ flags |
- |
инверсия (двоичное дополнение) | – 1 * lenght |
High |
выделить старший байт слова | movlw high llasid |
|
выделить младший байт слова | movlw |
|
выделить наибольший байт слова | movlw |
* |
Умножение | a = c * b |
/ |
Деление | a = b / c |
% |
Модуль | lenght = totall % 16 |
+ |
Сложение | Tot_len = lenght * 8 + 1 |
- |
Вычитание | Entry_Son = ( |
<< |
сдвиг влево | |
>> |
сдвиг вправо | |
>= |
больше либо равно | if ent >= num |
> |
больше | if ent > num |
< |
меньше | if ent < num |
<= |
меньше либо равно | if ent <= num |
== |
равно | if ent == num |
!= |
не равно | if ent != num |
|
поразрядное "И" | flags = flags err_bit |
^ |
поразрядное "ИСКЛЮЧАЮЩЕЕ ИЛИ" | flags = flags ^ err_bit |
| |
поразрядное "ИЛИ" | flags = flags | err_bit |
|
логическое "И" | if ( |
|| |
логическое "ИЛИ" | if ( |
= |
установить равным... | entry_index = 0 |
++ |
увеличить на 1 (инкремент) | i ++ |
— |
уменьшить на 1 (декремент) | i — |
Операторы high, и используются для получения одного байта из многобайтного значения, соответствующего метке. Применяются для управления расчетом точек динамического перехода при чтении таблиц и записи программ.
Операторы инкремента и декремента могут применяться к переменной только в качестве единственного оператора в строке. Они не могут быть встроенным фрагментом более сложного выражения.
Поле комментария может использоваться программистом для текстового или символьного пояснения логической организации программы. Поле комментария полностью игнорируется * или ; ). Комментарии в конце строки должны быть отделены от остатка строки одним или более пробелами или табуляцией.
Существует ряд расширений файлов, применяемых по умолчанию MPASM и связанными утилитами. Назначения таких расширений приведены в табл. 6.4.
| Расширение | Назначение |
|---|---|
| . |
Входной файл <source_name>. |
| .OBJ | Выходной файл перемещаемого объектного кода из MPASM <source_name>.OBJ |
| .LST | Выходной файл листинга, генерируемый <source_name>.LST |
| . |
Выходной <source_name>. |
| .MAP | Выходной файл распределения памяти из MPASM: <source_name>.MAP |
| . |
Выходной файл объектного кода в шестнадцатиричном представлении из MPASM: <source_name>. |
| .HXL/.HXH | Выходной файл объектного кода в шестнадцатиричном представлении c раздельным представлением младших и старших байт: <source_name>.HXL, <source_name>.HXH |
| .LIB | Библиотечный файл, созданный MPLIB и привязанный компоновщиком MPLINK: <source_name>.LIB |
| .LNK | Выходной файл компоновщика: <source_name>.LNK |
| . |
Выходной символьный файл или файл отладчика. Формируются MPASM или MPLINK: <source_name>. |
Листинг представляет собой текстовый файл в формате ASCII, который содержит машинные коды, сгенерированные в соответствии с каждой ассемблерной командой, директивой
В состав листинга входят также
Директивы языка – это ассемблерные команды, которые встречаются в исходном коде, но не транслируются прямо в исполняемые коды. Они используются
Существует четыре основных типа директив в MPASM:
Директивы данных управляют распределением памяти и обеспечивают доступ к символическим обозначениям данных.
Директивы листинга управляют листингом файла MPASM и форматом. Они определяют спецификацию заголовков, генерацию страниц и другие функции управления листингом.
Директивы управления позволяют произвести
Макро-директивы управляют исполнением и распределением данных в пределах определений макротела.
Ниже приводится описание некоторых директив
CODE – начало секции объектного кода
Синтаксис:
[<label>] code [ROM address>]
Используется при генерации объектных модулей. Объявляет начало секции программного кода. Если <label> не указана, секция будет названа code. Стартовый адрес устанавливается равным указанному значению или нулю, если адрес не был указан.
Пример:
RESET code H'01FF'
goto START
#DEFINE – определить метку замены текста
Синтаксис:
#define <name> [<string>]
Директива задает строку <string>, замещающую метку <name> всякий раз, когда та будет встречаться в исходном тексте.
Символы, которые определены директивой #DEFINE, не могут быть просмотрены EQU.
Пример
#define length 20 #define control 0x19,7 #define position (X,Y,Z) (y-(2 * Z +X)). test_label dw position(1, length, 512) bsf control ; установить в 1 бит 7 в f19
END – конец программного блока
Синтаксис:
end
Определяет конец программы. После остановки программы
Пример:
start ;исполняемый код ; end ; конец программы
EQU – определить ассемблерную константу
Синтаксис:
<label> equ <expr>
Здесь <expr> – это правильное MPASM выражение. Значение выражения присваивается метке <label>.
Пример:
four equ 4 ; присваивает численное значение
; метке four
INCLUDE – включить дополнительный исходный файл
Синтаксис:
include <<include_file>> include "<include_file>"
Определяемый файл считывается как источник кода. По окончании <include_file> может быть заключен в кавычки или угловые скобки. Если указан полный путь к файлу, то поиск будет происходить только по этому пути. В противном случае порядок поиска следующий: текущий рабочий каталог, каталог, в котором находится исходник, каталог MPASM.
Пример:
include "c:\sys\sysdefs.inc" ; system defs include <addmain.asm> ; register defs
LIST – установить параметры листинга
Синтаксис:
list [<list_option>, , <list_option>]
Директива <list> разрешает вывод листинга, если он до этого был запрещен. Кроме того, один из параметров листинга может быть изменен для управления процессом ассемблирования в соответствии с табл. 6.5.
| Параметр | Значение по умолчанию | Описание |
|---|---|---|
C=nnn |
80 | Количество символов в строке |
n=nnn |
59 | Количество строк на странице |
t=ON|OFF |
OFF | Укорачивать строки листинга |
p=<type> |
None | Установить тип процессора: PIC16C54, PIC16C84, PIC16F84, PIC17C42 и др. |
r=< |
Установить систему счисления по умолчанию: |
|
w=<level> |
0 | Установить уровень сообщений диагностики в файле листинга: 0 – выводить все сообщения; 1 – выводить предупреждения и ошибки; 2 – выводить только ошибки. |
x=ON|OFF |
OFF | Включить или выключить макрорасширения. |
NOLIST – выключить выход листинга
Синтаксис:
NOLIST
ORG – установить начальный адрес программы
Синтаксис:
<label> org <expr>
Устанавливает начальный адрес программы для последующего кода в соответствии с адресом в <expr>. MPASM выводит перемещаемый объектный код, а MPLINK разместит код по определенному адресу. Если метка <label> определена, то ей будет присвоена величина <expr>. По умолчанию начальный адрес имеет нулевое значение. Директива может не использоваться, если создается объектный модуль.
Пример:
int_1 org 0x20; Переход по вектору 20 int_2 org int_1+0x10; Переход по вектору 30
PROCESSOR – установить тип процессора
Синтаксис:
processor <processor_type>
Устанавливает тип используемого процессора <processor_type>: [16C54 | 16C55 | 16C56 | 16C57 | 16C71 | 16C84 | 16F84 | 17C42]. Общие процессорные семейства могут быть выбраны как: [16C5X | 16CXX | 17CXX]
Для поддержания совместимости с новыми изделиями выбирается максимум доступной памяти.
SET – определить ассемблерную переменную
Синтаксис:
<label> set <expr>
Директива SET функционально эквивалентна директиве EQU, за исключением того, что величина, определяемая SET, может быть изменена директивой SET.
Пример:
area set 0 width set 0x12 length set 0x14 area set length * width length set length + 1
TITLE – Определить программный заголовок
Синтаксис:
title "<title_text>"
Эта директива устанавливает текст, который используется в верхней строке страницы листинга. <title_text> - это печатная ASCII последовательность, заключенная в двойные скобки. Она может быть до 60 символов длиной.
Пример
title "operational code, rev 5.0"
Абсолютный (неперемещаемый) код программы генерируется непосредственно при ассемблировании и располагается в программной памяти в порядке следования операторов программы.
При генерации перемещаемого кода каждая секция программного кода должна предваряться директивой CODE. Окончательное размещение программных кодов, расстановку физических адресов переходов выполняет компоновщик MPLINK.
Компоновщик MPLINK выполняет следующие задачи:
Для более подробного изучения работы компоновщика следует обратиться к специальной литературе.
Менеджер библиотек позволяет создавать и модифицировать файлы библиотек. Библиотечный файл является коллекцией объектных модулей, которые размещены в одном файле. MPLIB использует объектные модули с именем типа "filename.o" формата
Использование библиотечных файлов упрощает компоновку программы, делает ее более структурированной и облегчает ее модификацию.
MPSIM запускается из командной строки DOS, конфигурируется пользователем и непосредственно применяет выходные данные
Перед использованием <file_name>. и получить файл объектного кода в формате INHX8M, создаваемый MPASM по умолчанию:
MPASM <file_name>.asm <RETURN>
Чтобы запустить
MPSIM<RETURN>.
Вид экрана, получаемого при запуске MPSIM, показан на рис. 6.2. Экран разделен на три части, или окна. В верхнем окне показано текущее состояние моделирования, включая моделируемую программу, тип МК, число выполненных командных циклов и затраченное на них время. Среднее окно используется для вывода содержимого регистров пользователя. Набор регистров и формат выводимых на экран данных определяются файлом MPSIM.INI, который далее будет описан подробнее. Нижнее окно содержит приглашение на ввод команд, а также текущие операции и результат их выполнения.
При запуске MPSIM.INI. Этот текстовой файл создается пользователем и используется для задания всех задействованных в программе параметров.
(рис 6.2) Вид рабочего окна симулятора MPSIM.Один из примеров файла MPSIM.INI приведен ниже.
; MPSIM file for user4 P84 ;использование МК семейства PIC16C84 SR X ;представление данных в 16-ричном формате ZR ;сброс регистров МК в нуль ZT ;сброс таймера в нуль RE ;сброс времени выполнения команды и счетчика циклов V W,X,2 ;вывод регистра W в hex формате на два знакоместа AD F1,X,2 ;вывод на экран регистра TMR0 в hex формате на два знакоместа AD F2,X,3 ;вывод на экран регистра PCL в hex формате на три знакоместа AD F3,B,8 ;вывод на экран регистра STATUS в bin формате на восемь знакомест AD IOA,X,2 ;вывод на экран регистра TRISA в hex формате на два знакоместа AD F5,X,2 ;вывод на экран регистра порта A в hex формате на два знакоместа SC 1 ;установка тактовой частоты 1 МГц RS ;сброс МК LO user4
В представленном файле указаны: тип MPSIM.INI, который определяет начальное MPSIM.JRN, в котором сохраняются все сведения о нажатии клавиш в процессе работы.
В файле MPSIM.INI допускается вводить комментарии, которые даются после знака ";", но не допускается использование пустых строк.
Основные команды, применяемые в MPSIM.JRN, который используется при создании расширенного файла MPSIM.INI. Данный файл можно задействовать для выявления ошибок и обеспечения нормального выполнения программы после исправления кода.
| Команда | Параметр | Комментарии |
|---|---|---|
AB |
- | Прерывание текущей сессии |
AD |
Reg[, |
Вывод содержимого регистра на экран в указанном формате и заданной системе счисления X, B или D |
B |
[addr] |
Установка точки останова по текущему или указанному адресу |
C |
[#break] |
Продолжение выполнения программы с пропуском указанного количества следующих точек останова |
|
- | Вывод на экран всех активных точек останова |
DI |
[addr1[,addr2]] |
Вывод на экран фрагмента памяти программ |
DR |
- | Вывод содержимого всех регистров |
DW |
[E|D] |
Разрешение/запрещение функционирования |
E |
[addr] |
Выполнение программы с текущего или указанного адреса |
F |
Reg |
Вывод на экран содержимого регистра и возможность его редактирования пользователем |
GE |
filename |
Получение и выполнение командного файла. Это способ загрузки командного файла .INI |
GO |
- | Запуск МК и начало выполнения программы |
IP |
[time|step] |
Ввод входных воздействий в соответствии со значением параметра step в файле |
LO |
filename |
Загрузка в MPSIM файлов . |
M |
addr |
Вывод на экран содержимого памяти программ, начиная с адреса "addr" и возможность его редактирования. Ввод "Q" завершает команду. |
P |
device |
Выбор типа моделируемого МК |
Q |
- | Выход из MPSIM и запись команд в файл .JRN |
RE |
- | Сброс времени выполнения и счетчика циклов |
RS |
- | Сброс моделируемого МК |
SE |
|
Вывод на экран состояния указанного вывода или порта и возможность его изменения |
SR |
O|X|D |
Установка системы счисления по умолчанию |
SS |
[addr] |
Пошаговое исполнение, начиная с указанного адреса. При отсутствии адреса – исполнение идет с текущего места |
ST |
filename |
Загрузка файла стимуляции |
W |
Отображение состояния регистра W с возможностью его модификации |
|
ZM |
addr1,addr2 |
Очистка памяти программ с адреса addr1 по addr2 |
ZR |
- | Сброс всех регистров МК |
ZT |
- | Сброс таймера/счетчика МК |
Для моделирования внешних тестовых событий (воздействий) на моделируемый МК используются файлы стимуляции с расширением .STI. Эти файлы используются MPSIM для того, чтобы обеспечить подачу однократных и повторяющихся входных сигналов в процессе выполнения программы. При этом можно наблюдать на экране, как МК реагирует на сигналы.
В качестве примера ниже приведен файл для A.
! test1.STI STEP RA1 1 1 !Установка на входе RA1 состояния "1" 200 0 !Поступление на вход RA1 сигнала "0" 1000 1 !Переход сигнала на входе RA1 в "1" 1200 0 !Повторная подача нулевого сигнала
Файл воздействия состоит из
Для того чтобы написать первые учебные программы и проверить их функционирование, желательно иметь относительно несложный макет, содержащий самые распространенные периферийные устройства. Схема подобного макета, используемого при выполнении лабораторных работ студентами, приведена на рис. 6.3.
Макет питается от источника стабилизированного напряжения +5В. Тактовая частота МК задается RC-цепью и составляет около 2 МГц. К линии RA0 порта А подключен биполярный транзистор в ключевом режиме, нагруженный на динамик ВА1. Звучание динамика обеспечивается подачей на выход RA0 изменяющегося сигнала в звуковом диапазоне. К линии RA1 порта А подключен светодиод VD2, светящийся при высоком напряжении на выходе. Тумблеры SA1 и SA2, а также кнопки SB1 и SB2 подключены, соответственно, к линиям RA2 и RA3 порта А, а также к линии RA4 порта А и линии RB0 порта В. Исходное состояние кнопок – разомкнутое, что обеспечивает подачу на соответствующие входы МК высокого уровня сигнала.
Линии RB1 – RB7 порта B обслуживают семисегментный индикатор HL1 с общим анодом. Поэтому свечение сегмента индикатора обеспечивается при низком уровне сигнала на соответствующем выходе порта B. Макет также содержит средства программирования и связи с компьютером, которые на схеме не показаны.
(рис 6.3) Схема лабораторного макета.
Прежде чем переходить к созданию простейших пользовательских программ, необходимо описать используемые в дальнейшем переменные и настроить МК на работу с выбранным макетом. С этой целью мы напишем и подробно рассмотрим листинг исходной программы init., в состав которой будут включаться все остальные программы пользователя.
;******************************************************
;*листинг исходной программы
;******************************************************
LIST P=16C84, R=HEX ;директива, определяющая тип
;процессора и систему счисления
;по умолчанию
;******************************************************
;*описание используемых переменных и назначения адресов
;*ячеек для хранения переменных пользователя
;******************************************************
; INTCON EQU 0x0B
; OPTION EQU 0x81
; TMR0 EQU 0x01
; INTF EQU 1
; T0IF EQU 5
PCL EQU 0x02
STATUS EQU 0x03
RP0 EQU 5
PORTA EQU 0x05
PORTB EQU 0x06
TRISA EQU 0x05
TRISB EQU 0x06
W EQU 0
F EQU 1
TEMPA EQU 0x0C
TEMPB EQU 0x0D
COUNT1 EQU 0x0E
COUNT2 EQU 0x0F
COUNT3 EQU 0x10
;******************************************************
;*определение меток замены текста
;******************************************************
#DEFINE Z STATUS,2 ;бит нулевого результата
#DEFINE BA1 PORTA,0 ;динамик BA1
#DEFINE VD2 PORTA,1 ;светодиод VD2
#DEFINE SA1 PORTA,2 ;тумблер SA1
#DEFINE SA2 PORTA,3 ;тумблер SA2
#DEFINE SB1 PORTA,4 ;кнопка SB1
#DEFINE SB2 PORTB,0 ;кнопка SB2
#DEFINE HL1_A PORTB,1 ;индикатор-сегмент A
#DEFINE HL1_B PORTB,2 ;индикатор-сегмент B
#DEFINE HL1_C PORTB,3 ;индикатор-сегмент C
#DEFINE HL1_D PORTB,4 ;индикатор-сегмент D
#DEFINE HL1_E PORTB,5 ;индикатор-сегмент D
#DEFINE HL1_F PORTB,6 ;индикатор-сегмент E
#DEFINE HL1_G PORTB,7 ;индикатор-сегмент F
;******************************************************
;*исполняемая программа
;******************************************************
ORG 0x000 ;установка начального адреса по
;сбросу
GOTO BEGIN ;переход на начало программы
ORG 0x005 ;установка начального адреса
;размещения программы
BEGIN
CALL INIT_PORTS ;вызов подпрограммы
;инициализации портов МК
;*****************************************************
;*программа пользователя
;
;*****************************************************
;
INIT_PORTS ;подпрограмма инициализации
;портов
MOVLW 0xFF ;установка линий портов
MOVWF PORTA ;A и B в единичное
MOVWF PORTB ;состояние
BSF STATUS,RP0 ;переход на банк 1
MOVLW 0x1C ;настройка линий RA0 и
MOVWF TRISA ;RA1 порта A на вывод –
;остальных – на ввод
MOVLW 0x01 ;настройка линии RB0
MOVWF TRISB ;порта B на ввод -
;остальных – на вывод
BCF STATUS,RP0 ;возврат в банк 0
RETURN ;возврат из подпрограммы
;
END ;конец программы
Рассмотрим работу этой программы. Вначале она указывает EQU определяют ассемблерные константы, используемые в этой и последующих программах. Они позволяют использовать в тексте программы более удобные мнемонические метки, привязанные к структуре конкретного МК, вместо корректных, но более сложных ассемблерных выражений. Указатели TEMPA, TEMPB, COUNT1 и COUNT2 назначают адреса ячеек памяти для хранения промежуточных данных (текущих состояний, переменных циклов и т.п.).
Ассемблерные директивы #define задают строку, замещающую соответствующую метку, каждый раз, когда та будет встречаться в исходном тексте. В нашем случае эти директивы позволяют использовать символические имена, привязанные к схеме макета, вместо физических адресов соответствующих разрядов портов и регистров. При этом необходимо иметь в виду, что символы, которые определены директивой #DEFINE, не могут быть просмотрены
Директива ORG 0x00 устанавливает стартовый адрес программного кода равным 0, т.е. соответствующим начальному состоянию GOTO BEGIN вместе с ассемблерной директивой ORG 0x005 и меткой BEGIN обеспечивают переход на адрес памяти программ 0x005, начиная с которого и размещается основная часть программы. Это необходимо для того, чтобы обойти адрес 0x004, используемый в качестве вектора прерывания, и тем самым зарезервировать его для возможных будущих применений.
Затем с помощью команды CALL INIT_PORTS производится вызов подпрограммы инициализации портов. Вначале подпрограмма инициализации устанавливает в высокое (единичное) состояние выходные триггеры данных. Эта операция рекомендуется разработчиком МК для того, чтобы исключить неопределенность в состояниях регистров портов. Затем командой BSF STATUS,RP0 производится переключение на банк 1 памяти данных, где расположены TRISA и TRISB. С помощью команд MOVLW 0x1C и MOVWF TRISA линии RA0 и RA1 порта A настраиваются на вывод, а остальные – на ввод. Команды MOVLW 0x01 и MOVWF TRISB настраивают линию RB0 порта B на ввод, а остальные – на вывод. С помощью команды BCF STATUS,RP0 производится возврат в банк 0, где располагаются необходимые для работы программы регистры и порты.
Поскольку в процессе работы с макетом перенастройка портов не производится, и введенных переменных достаточно для работы всех рассматриваемых учебных задач, они будут далее рассматриваться включенными по умолчанию в состав исходной программы init.. При написании учебных задач будет по возможности использоваться метод структурного программирования, при котором прикладная программа строится из некоторого набора программных модулей, каждый из которых реализует определенную процедуру обработки данных. При этом каждый из программных модулей имеет только одну точку входа и одну точку выхода. Введенные однажды программные модули могут использоваться под своим именем в других прикладных программах.
Начнем программирование учебных задач с написания программы, которая считывает состояние кнопки SB1 и выводит его на светодиодный индикатор VD2 так, что не нажатому состоянию кнопки (высокому уровню сигнала на входе RA4 ) соответствует светящееся состояние светодиода, и наоборот.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_RA
CALL SB1_VD2 ;вызов подпрограммы SB1_VD2
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
GET_RA ;подпрограмма чтения состояния
;порта A
MOVF PORTA,W ;чтение состояния порта A в W
MOVWF TEMPA ;пересылка W в TEMPA
RETURN ;возврат из подпрограммы
;
SB1_VD2 ;подпрограмма вывода на светодиод
;VD2 состояния кнопки SB1 (разряда 4
;регистра TEMPA)
BTFSS TEMPA,4 ;пропустить команду, если
;TEMPA,4=1 (кнопка не нажата)
GOTO P0 ;перейти на P0
BSF VD2 ;зажечь светодиод VD2
P0
BTFSC TEMPA,4 ;пропустить команду, если
;TEMPA,4=0 (кнопка нажата)
GOTO P1 ;перейти на P1
BCF VD2 ;погасить светодиод
P1
RETURN
;
Основная программа содержит замкнутый цикл LOOP – GOTO LOOP, необходимый для периодического повторения цикла контроля состояния кнопки и вывода его на индикатор. Команда CLRWDT исключает влияние возможного сброса по переполнению GET_RA и SB1_VD2. Первая из них ( GET_RA ) вначале считывает текущее состояние порта A, которое помещается в рабочий регистр W. Поскольку рабочий регистр может потребоваться при исполнении других команд, его состояние записывается в регистр TEMPA, используемый здесь для временного хранения состояния порта A. Таким образом, после возврата из подпрограммы GET_RA в разряде 4 регистра TEMPA содержится информация о состоянии кнопки SB1: "1" – не нажата, "0" – нажата.
Подпрограмма SB1_VD2 анализирует состояние разряда 4 регистра TEMPA и, в зависимости от него, зажигает или гасит светодиод. В системе команд МК PIC16F84 нет команд BTFSS и BTFSC ). В частности, команда BTFSS TEMP,4 пропускает исполнение команды GOTO P0, если TEMP,4 = 1 (кнопка не нажата). Тем самым реализуется команда BSF VD2, которая зажигает светодиод VD2. Затем анализируется условие TEMP,4 = 0 (кнопка нажата) и, если оно имеет место, светодиод гасится.
Возможна более простая реализация заданного алгоритма, поскольку нажатое состояние кнопки исключает не нажатое (и наоборот), но представленный вариант более нагляден.
Рассмотрим более сложный вариант программы, предусматривающий зажигание светодиода VD2 только при следующем состоянии тумблеров и кнопок макета: SA1 = 1, SA2 = 1, SB1 = 1 и SB2 = 0.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_RA
CALL GET_RB ;вызов подпрограммы GET_RB
CALL ZAG_1110 ;вызов подпрограммы ZAG_1110
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
GET_RB ;подпрограмма чтения состояния
;порта B
MOVF PORTB,W ;чтение состояния порта B в W
MOVWF TEMPB ;пересылка W в TEMPB
RETURN
;
ZAG_1110 ;зажигает светодиод VD2 только при
;следующем состоянии тумблеров и
;кнопок макета:
;SA1 = SA2 = SB1 = 1 и SB2 = 0
BTFSS TEMPA,2 ;пропустить команду, если
GOTO P0 ;TEMPA,2=1
BTFSS TEMPA,3 ;пропустить команду, если
GOTO P0 ;TEMPA,3=1
BTFSS TEMPA,4 ;пропустить команду, если
GOTO P0 ;TEMPA,4=1
BTFSC TEMPB,0 ;пропустить команду, если
GOTO P0 ;TEMPB,0=0
BSF VD2 ;зажечь светодиод VD2
GOTO P1
P0
BCF VD2 ;погасить светодиод VD2
P1
RETURN
;
INCLUDE GET_RA.ASM
;
Подпрограммы GET_RA и GET_RB помещают в регистры TEMPA и TEMPB текущие состояния портов A и B, соответственно. Подпрограмма ZAG_1110 анализирует состояния разрядов 2,3 и 4 регистра TEMPA и разряда 0 регистра TEMPB, и при условии TEMPA,2,3,4 = 1,1,1 и TEMPB,0 = 0, зажигает светодиод VD2. При невыполнении хотя бы одного из этих условий светодиод гасится.
Использование директивы INCLUDE GET_PORTA. позволяет включать уже отлаженные модули подпрограмм в текущую программу. Для того чтобы этой возможностью можно было воспользоваться, необходимо сохранять отлаженные модули в виде отдельных ассемблерных файлов.
Попробуем теперь использовать семисегментный индикатор для контроля состояния тумблеров макета. Вначале напишем программу, которая выводит на индикатор HL семисегментное изображение любого двоичного числа от 0b до 1111b в шестнадцатиричном представлении.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
MOVLW 0x0A ;пересылка константы 0A в W
CALL SEV_SEG ;вызов подпрограммы SEVEN_SEG
MOVWF PORTB ;пересылка W в PORTB
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
SEV_SEG ;подпрограмма обслуживания
;семисегментного индикатора
ANDLW 0x0F ;маскирование 4-х младших разрядов
;W и обнуление 4-х старших
ADDWF PCL,F ;сложение W с PCL и пересылка
;результата в PCL
RETLW 0x80 ;возврат из подпрограммы с 80 в W
RETLW 0xF2 ;возврат из подпрограммы с F2 в W
RETLW 0x48 ;возврат из подпрограммы с 48 в W
RETLW 0x60 ;возврат из подпрограммы с 60 в W
RETLW 0x32 ;возврат из подпрограммы с 32 в W
RETLW 0x25 ;возврат из подпрограммы с 25 в W
RETLW 0x04 ;возврат из подпрограммы с 04 в W
RETLW 0xF0 ;возврат из подпрограммы с F0 в W
RETLW 0x00 ;возврат из подпрограммы с 00 в W
RETLW 0x20 ;возврат из подпрограммы с 20 в W
RETLW 0x10 ;возврат из подпрограммы с 10 в W
RETLW 0x06 ;возврат из подпрограммы с 06 в W
RETLW 0x8C ;возврат из подпрограммы с 8C в W
RETLW 0x42 ;возврат из подпрограммы с 42 в W
RETLW 0x0C ;возврат из подпрограммы с 0C в W
RETLW 0x1C ;возврат из подпрограммы с 1C в W
;
Программа начинает свою работу с пересылки константы 0x0A в рабочий регистр W. Затем производится вызов подпрограммы обслуживания семисегментного индикатора SEV_SEG. Работа подпрограммы SEV_SEG начинается с маскирования 4-х младших разрядов W и обнуления 4-х старших. Тем самым из анализа исключаются старшие разряды передаваемого из рабочего регистра W числа. Затем маскированное содержимое регистра W добавляется к текущему состоянию младшего байта , и результат помещается в . Таким образом, производится дополнительное смещение W=0, то содержимое RETLW 0x80, которая вызовет возврат из подпрограммы с записью 0x80 = B'10000000' в регистр W. Если, как было в при
веденной программе, W=0A, то к содержимому будет добавлено число 0x0A, и произойдет дополнительное смещение на 10 шагов. В результате будет выполнена команда RETLW 0x10, которая вызовет возврат из подпрограммы с записью 0x10 = B'0001000' в регистр W.
После возврата из подпрограммы производится пересылка W в PORTB и отображение его состояния на семисегментном индикаторе HL. В частности, если W = 0, то при выводе 1000000b на порт B семисегментный индикатор покажет 0, а при W = A покажет A.Таким образом, может быть отображено любое 4-разрядное двоичное число.
Метод прямого управления счетчиком команд, использованный в подпрограмме SEV_SEG, может применяться для реализации табличной конвертации чисел. При этом необходимо иметь в виду, что данный метод не позволяет конвертировать более 256 значений в одной таблице. Кроме того, программа табличной конвертации должна целиком располагаться внутри 256-байтного блока во избежание переполнения младшего байта
Используя подпрограмму SEV_SEG, напишем теперь программу, которая читает состояния тумблеров SA1 и SA2 и выводит на индикатор соответствующее число.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_RA
RRF TEMPA,F ;сдвиг вправо на один разряд
;через перенос
RRF TEMPA,W ;сдвиг вправо на один разряд
;через перенос
ANDLW 0x03 ;маска на два младших разряда
CALL SEV_SEG ;вызов подпрограммы SEVEN_SEG
MOVWF PORTB ;пересылка W в PORTB
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
INCLUDE GET_RA.ASM
INCLUDE SEV_SEG.ASM
;
Подпрограмма GET_RA помещает в регистр TEMPA текущее состояние порта A. Таким образом, в разрядах 2 и 3 регистра TEMPA хранится текущее состояние тумблеров SA1 и SA2. Для того чтобы биты состояния тумблеров заняли позиции 0 и 1 регистра TEMPA, производится два сдвига вправо через перенос, причем результат второго сдвига помещается в регистр W. Затем накладывается маска на два младших разряда рабочего регистра и производится вызов подпрограммы SEV_SEG. После выхода из подпрограммы результат подается на порт B и отображается на индикаторе.
Рассмотрим теперь программы, работающие в реальном масштабе времени, т.е. выдающие сигналы определенной длительности и частоты следования, либо учитывающие временные параметры входных сигналов. Основным элементом таких программ является подпрограмма формирования временной задержки. Рассмотрим один из возможных вариантов такой подпрограммы с использованием программных методов формирования задержки, т.е. без применения встроенного таймера.
;основная программа
MOVLW 0xL ;пересылка константы H'L' в W
CALL DELAY ;вызов подпрограммы DELAY
;
DELAY ;подпрограмма формирования
;задержки времени
MOVWF COUNT1 ;загрузка W в регистр COUNT1
LOOPD
DECFSZ COUNT1,F ;декремент COUNT1
GOTO LOOPD ;повторение цикла H'L' раз
RETURN ;возврат из подпрограммы
;
Основная программа производит вызов подпрограммы с некоторой константой L в рабочем регистре W, определяющей число внутренних циклов подпрограммы. Подпрограмма начинает свою работу с загрузки содержимого рабочего регистра в регистр пользователя COUNT1. Команда DECFSZ COUNT1,F уменьшает на единицу содержимое регистра COUNT1 и проверяет его на равенство нулю. Нулевое состояние регистра COUNT1 приводит к выходу из цикла и возврату из подпрограммы. Для исполнения каждого внутреннего цикла требуется три машинных цикла МК (1 цикл на исполнение команды DECFSZ при ненулевом результате и 2 цикла на каждую команду GOTO ). Выход из подпрограммы потребует 4-х циклов (2 цикла на исполнение команды DECFSZ при нулевом результате и 2 цикла на RETURN ). Если добавить к этому еще 4 цикла, необходимых для загрузки константы в рабочий регистр
, вызова подпрограммы и загрузки регистра пользователя COUNT1, то общее время исполнения подпрограммы (задержка) составит
TD = 4 + 3*(L – 1) + 4 = 5 + 3*L циклов,
где L – константа, переданная через рабочий регистр в подпрограмму .
При тактовой частоте fosc = 2МГц время цикла равно tц = 2 мкс, поэтому при загрузке L = H'00' = .0 максимальный формируемый интервал времени составит 1,55 мс. Такой результат связан с тем, что команда DECFSZ сначала декрементирует содержимое регистра ( H'00' – 1 = H'FF' ), а затем уже анализирует результат.
Минимальный формируемый интервал времени составит при тех же условиях 5 циклов или 10 мкс. Для получения такого интервала необходимо перед вызовом подпрограммы загрузить в рабочий регистр число 0x01.
Для расширения верхней границы формируемых временных интервалов, а также с целью повышения удобства работы с подпрограммой, можно добавить в цикл LOOPD одну или несколько дополнительных команд, в качестве которых чаще всего используется команда . Для примера рассмотрим подпрограмму формирования задержки времени DELAY_C
;
DELAY_C ;подпрограмма формирования
;задержки времени (вариант C)
MOVWF MOVWF COUNT1 ;загрузка W в регистр COUNT1
LOOPD
NOP ;пустая команда
DECFSZ COUNT1,F ;декремент COUNT1
GOTO LOOPD ;повторение цикла H'L' раз
RETURN ;возврат из подпрограммы
;
Общее время исполнения подпрограммы DELAY_C, включая ее вызов, составит
TD = 4 + 4*(L – 1) + 4 = 4 + 4*L циклов.
При тактовой частоте fosc = 2МГц и загрузке константы L = H'F9' = .249 формируемый интервал времени составит ровно 2 мс. Уменьшение константы на единицу уменьшает формируемый временной интервал на 8 мкс. В частности, при L = .124 образуется задержка в 1 мс.
Для формирования больших задержек времени, лежащих в диапазоне долей и единиц секунд, такой подход неудобен. В этом случае используются
;основная программа
MOVLW 0xL ;пересылка константы H'L' в W
CALL DELAY_D ;вызов подпрограммы DELAY_D
;
DELAY_D ;подпрограмма формирования
;большой задержки времени (вариант D)
MOVWF COUNT2 ;загрузка W в регистр COUNT2
CLRF COUNT1 ;сброс содержимого регистра COUNT1
LOOPD
DECFSZ COUNT1,F ;декремент COUNT1
GOTO LOOPD ;повторение цикла 256 раз
CLRWDT ;сброс сторожевого таймера
DECFSZ COUNT2,F ;декремент COUNT2
GOTO LOOPD ;повторение цикла H'L' раз
RETURN ;возврат из подпрограммы
;
Время исполнения внутреннего цикла подпрограммы DELAY_D составляет 3*256 + 4 машинных циклов МК, поэтому общая задержка составит
TD = 5 + (3*256 + 4)*L циклов.
При тактовой частоте fosc = 2МГц время цикла равно tц = 2 мкс, поэтому при загрузке L = H'00' = .0 максимальный формируемый интервал времени составит около 0,4 с.
Поскольку формируемый интервал времени достаточно велик, во внешний цикл включена команда сброса
Интервал времени 0,4 с не совсем удобен для получения задержек времени, кратных секунде, поэтому рассмотрим еще один вариант подпрограммы формирования больших задержек времени с дополнительной командой во внутреннем цикле.
;
DELAY_E ;подпрограмма формирования
;большой задержки времени (вариант E)
MOVWF COUNT2 ;загрузка W в регистр COUNT2
CLRF COUNT1 ;сброс содержимого регистра COUNT1
LOOPD
NOP ;пустая команда
DECFSZ COUNT1,F ;декремент COUNT1
GOTO LOOPD ;повторение цикла 256 раз
CLRWDT ;сброс сторожевого таймера
DECFSZ COUNT2,F ;декремент COUNT2
GOTO LOOPD ;повторение цикла H'L' раз
RETURN ;возврат из подпрограммы
;
Время исполнения внутреннего цикла подпрограммы DELAY_E составляет 4*256 + 4 машинных циклов МК, поэтому общая задержка составит
TD = 5 + (4*256 + 4)*L циклов.
При тактовой частоте fosc = 2МГц и при загрузке L = H'F3' = .243 формируемый интервал времени составит около 0,5 с при погрешности не более 0,2%. Если необходима более высокая точность, можно вставить необходимое количество пустых операций во внешний цикл формирования задержки.
Рассмотрим далее несколько программ с использованием подпрограмм формирования задержки времени. Начнем с написания программы, которая подает звуковой сигнал на динамик BA1 при нажатии на кнопку SB1. Динамик будет звучать только в том случае, если на выход RA0 будет подан периодически изменяющийся сигнал. Для того чтобы звук был хорошо слышен, его частота должна находиться вблизи максимума слышимости человеческого уха. Выберем частоту звучания равной 1 КГц, что соответствует периоду следования импульсов сигнала 1 мс.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_PORTA
CALL SB1_BA1 ;вызов подпрограммы SB1_BA1
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
SB1_BA1 ;подпрограмма подачи звука на
;динамик BA1 при нажатии на кнопку
;SB1
BTFSC TEMPA,4 ;пропустить команду, если
;TEMPA,4=0 (кнопка нажата)
GOTO B0 ;перейти на B0
BSF BA1 ;подача высокого уровня на RA0
MOVLW 0x3E ;пересылка константы
;H'3E' = .62 в W
CALL DELAY_C ;вызов подпрограммы DELAY_C
BCF BA1 ;подача низкого уровня на RA0
MOVLW 0x3E ;пересылка константы
;H'3E' = .62 в W
CALL DELAY_C ;вызов подпрограммы DELAY_C
B0
RETURN
;
INCLUDE GET_RA.ASM
INCLUDE DELAY_C.ASM
;
Как и раньше, подпрограмма GET_RA считывает текущее состояние порта A, которое затем передается в регистр TEMPA. Подпрограмма SB1_BA1 анализирует состояние разряда 4 регистра TEMPA и, в зависимости от результата, озвучивает динамик BA1 или нет. Необходимая выдержка линии RA0 в единичном и нулевом состояниях обеспечивается подпрограммой DELAY_C с параметром L = H'3E' = .62. Это соответствует времени задержки около 0,5 мс, что и дает в результате необходимую частоту следования сигнала 1 Кгц.
Рассмотрим далее программу, которая заставляет мигать светодиод VD2 при нажатии на кнопку SB1. Для того чтобы мигания были хорошо видны, выберем их частоту равной 1 Гц.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_RA
CALL SB1_VD2M ;вызов подпрограммы
;SB1_VD2M
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
SB1_VD2M ;подпрограмма мигания светодиода
;VD2 при нажатии на кнопку SB1
BTFSC TEMPA,4 ;пропустить команду, если
;TEMPA,4=0 (кнопка нажата)
GOTO V0 ;перейти на V0
BSF VD2 ;зажечь светодиод VD2
MOVLW 0xF3 ;пересылка константы
;H'F3' = .243 в W
CALL DELAY_E ;вызов подпрограммы DELAY_E
BCF VD2 ;погасить светодиод
MOVLW 0xF3 ;пересылка константы
;H'F3' = .243 в W
CALL DELAY_E ;вызов подпрограммы DELAY_E
V0
BTFSS TEMPA,4 ;пропустить команду, если
;TEMPA,4=1 (кнопка не нажата)
GOTO V1 ;перейти на V1
BCF VD2 ;погасить светодиод
V1
RETURN
;
INCLUDE GET_RA.ASM
INCLUDE DELAY_E.ASM
;
Программа работает почти так же, как и предыдущая. Первое отличие заключается в том, что светодиод принудительно гасится при не нажатой кнопке. Второе отличие заключается в величине интервала времени, который составляет здесь 0,5 с и формируется подпрограммой DELAY_E.
Подпрограммы формирования задержки времени могут быть также полезны при работе с такими внешними источниками сигналов, как тумблеры, кнопки, переключатели и т.п. Дело в том, что все механические коммутаторы имеют одно негативное свойство, известное как "дребезг" контактов, которое обусловлено механическими колебаниями контактов при их замыкании и размыкании. Длительность колебаний составляет обычно несколько миллисекунд, в течение которых на вход МК может поступать пачка импульсов вместо идеального перепада.
Аппаратные способы борьбы с "дребезгом" контактов основаны на использовании
В качестве примера рассмотрим "бездребезговый" вариант подпрограммы чтения состояния порта A.
;
GET_RAD ;подпрограмма чтения состояния
;порта A в регистр TEMPA
;с подавлением "дребезжания"
DD
MOVF PORTA,W ;чтение состояния порта A в W
ANDLW 0x1C ;наложение маски b'00011100'
;на неиспользуемые биты W
MOVWF TEMPA ;пересылка W в TEMPA
CLRWDT ;сброс сторожевого таймера WDT
MOVLW 0x0A ;пересылка константы
;H'0A' = .10 в W
CALL DELAY_E ;вызов подпрограммы DELAY_E
MOVF PORTA,W ;чтение состояния порта A в W
ANDLW 0x1C ;наложение на W маски b'00011100'
SUBWF TEMPA,W ;вычитание W из TEMPA
BTFSS Z ;пропустить команду, если результат
;нулевой
GOTO DD ;перейти на метку DD
RETURN
;
INCLUDE DELAY_E.ASM
;
Суть работы подпрограммы заключается в повторном чтении состояния порта A спустя некоторое время после предыдущего и сравнении его с прежним значением. Константа H'0A' = .10, пересылаемая в регистр W перед вызовом подпрограммы DELAY_E, обеспечивает значение задержки времени около 20 мс - этого, как правило, достаточно для завершения переходных процессов при переключении механических коммутаторов. Маскирование неиспользуемых разрядов порта повышает надежность работы подпрограммы. Сброс A.
Рассмотрим теперь работу программы, которая использует некоторые из разработанных ранее подпрограмм. Пусть целью работы программы является подсчет числа нажатий на кнопку SB1 с выводом результата на семисегментный индикатор в шестнадцатиричном коде.
;основная программа
CLRF COUNT3 ;сброс счетчика нажатий
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RAD ;вызов подпрограммы GET_RAD
BTFSC TEMPA,4 ;проверка нажатия SB1
GOTO LOOP ;если не нажата – возврат
;на метку LOOP
INCF COUNT3,F ;инкремент счетчика
MOVF COUNT3,W ;пересылка содержимого
;счетчика в рабочий регистр
CALL SEV_SEG ;вызов подпрограммы SEV_SEG
MOVWF PORTB ;пересылка W в PORTB
TEST
CALL GET_RAD ;вызов подпрограммы GET_RAD
BTFSS TEMPA,4 ;проверка нажатия SB1
GOTO TEST ;если еще нажата – возврат
;на метку TEST
GOTO LOOP ;возврат на метку LOOP
;
INCLUDE GET_RAD.ASM
INCLUDE SEV_SEG.ASM
;
Приведенные в главе программы не охватывают и малой доли возможностей, которые предоставляет даже такой простой макет, как изображенный на рис. 6.3. Однако их освоение, надеюсь, будет полезным для начинающих пользователей
Основным инструментом для профессиональной
Для
Программа MPASM может использоваться для двух целей:
Исполняемый код является для MPASM выходным кодом по умолчанию. При этом все переменные источника должны быть явно описаны в тексте программы или в файле, подключаемом с помощью директивы INCLUDE <filename>. Если при ассемблировании не выявляется ошибок, то генерируется выходной .
При использовании
Программы MPASM и MPLINK доступны через оболочку MPASM, тогда как MPLIB доступна только со своей командной строки.
Исходным файлом для .. Текст исходного файла должен соответствовать требованиям синтаксиса, приведенным далее.
MPASM [/<Option>[ /<Option>...]] <file_name>
где /<Option> означает выбор режима работы <file_name> – имя файла на ассемблирование.
Режимы работы
| Выбор | Значение по умолчанию | Описание |
|---|---|---|
| ? | N/A | Вызвать помощь |
a |
INHX8M | Генерировать абсолютный . |
c |
On | Выбрать/запретить чувствительность к регистру |
e |
On | Выбрать/запретить |
h |
N/A | Отобразить панель помощи MPASM |
l |
On | Выбрать/запретить файл листинга, генерированный из макроассемблера. |
m |
On | Вызвать/запретить макрорасширение |
o |
N/A | Установить путь для /o<path>\object.file |
p |
None | Установить тип процессора: /p<processor_type> ; |
q |
Off | Разрешить/Запретить скрытый режим (запретить вывод на экран) |
r |
Определяет тип числа по умолчанию: /r< |
|
w |
0 | Определяет уровень 0 – сообщать все, 1 – сообщать о предупреждениях и ошибках, 2 – сообщать только об ошибках. |
x |
Off | Разрешить/запретить перекрестные ссылки в файле листинга. |
Здесь и далее используются следующие соглашения по использованию символов:
[ ] – для аргументов по выбору;< > – для выделения специальных ключей <TAB>, <ESC> или дополнительного выбора;| – для взаимоисключающих аргументов (выбор ИЛИ);Выбор по умолчанию, приведенный в табл. 6.1, может быть изменен командной строкой:
/<option> разрешает выбор;/<option>+ разрешает выбор;/<option> – запрещает выбор.Исходный ассемблерный файл создается с использованием любого ASCII текстового редактора. Каждая строка исходного файла может содержать до четырех
Порядок и положение каждого типа имеет значение. Метка должна начинаться в колонке номер один. Мнемоника может начинаться в колонке два или далее. Операнды идут за мнемоникой. Комментарий может следовать за операндом, мнемоникой или меткой или может начинаться в любом столбце, если в качестве первого не пустого символа используется * или ;.
Максимальная длина строки 255 символов.
Один или несколько пробелов должны отделять метку и мнемонику или мнемонику и операнд(ы). Операнды могут отделяться запятой. Например:
List p=16C54, r=HEX
ORG 0x1FF ;Вектор сброса
GOTO START ;Возврат на начало
ORG 0x000 ;Адрес начала исполнения
;программы
START
MOVLW 0x0A ;Выполнение программы
;PIC МК
MOVLW 0x0B ;Выполнять всегда
GOTO START
END
В поле метки размещается
Метка может начинаться с символа или нижнего тире ( _ ) и содержать буквенные символы, числа, нижние тире и знак вопроса. Длина метки может быть до 32 символов.
Мнемоники представляют собой мнемонические обозначения команды, которые непосредственно транслируются в машинный код. Мнемоники ассемблерных инструкций, директивы
В этом поле определяются операнды (или операнд), участвующие в операции. Операнды должны быть отделены от мнемоники одним или более пробелами или табуляцией. Операнды отделяются друг от друга запятыми. Если операция требует фиксированного количества операндов, то все на линии после операндов игнорируется. Комментарии разрешаются в конце линии. Если мнемоники позволяют использовать различное число операндов, конец списка операндов определяется концом строки или комментарием.
Выражения используются в поле операнда и могут содержать константы, символы или любые комбинации констант и символов, разделенных арифметическими операторами. Перед каждой константой или символом может стоять + или –, что указывает на положительное или отрицательное выражение.
В
Текстовая строка – это последовательность любых допустимых ASCII символов (в десятичном диапазоне от 0 до 127), заключенная в двойные кавычки. Строка может иметь любую длину в пределах 132 колонок. При отсутствии ограничения строки она считается до конца линии. Если строка используется как буквенный операнд, она должна иметь длину в один символ, иначе будет ошибка.
Числовая константа представляет собой число, выраженное в некоторой системе счисления. Перед константой может стоять + или –. Непосредственные величины в константах рассматриваются как 32-разрядные целые без знака.
MPASM поддерживает следующие системы счисления (представления значений или
Операторы – это арифметические символы, подобные + и –, которые используются при формировании выражений. Каждый оператор имеет свой приоритет. В общем случае приоритет устанавливается слева направо, а выражения в скобках вычисляются первыми. В табл. 6.3 приведены обозначения, описания и примеры применения основных операторов MPASM.
| Тип | Синтаксис | Пример |
|---|---|---|
| Десятичная | D'<цифры>' или .<цифры> |
D'100' или .100 |
| 16-ричная | H'<цифры>' или 0x<цифры> |
H'9f' или 0x9f |
| Восьмиричная | O'<цифры>' |
O'777' |
| Двоичная | B'<цифры>' |
B'00111001' |
| Символьная | '<символ>' или A'<символ>' |
'C' или A'C' |
| Оператор | Описание | Пример |
|---|---|---|
$ |
Текущий |
goto $ + 3 |
( |
левая скобка | 1 + ( d * 4 ) |
) |
правая скобка | ( lenght + 1 ) * 255 |
| ! | операция "НЕ" (логическая инверсия) | if ! ( a - b ) |
~ |
дополнение | flags = ~ flags |
- |
инверсия (двоичное дополнение) | – 1 * lenght |
High |
выделить старший байт слова | movlw high llasid |
|
выделить младший байт слова | movlw |
|
выделить наибольший байт слова | movlw |
* |
Умножение | a = c * b |
/ |
Деление | a = b / c |
% |
Модуль | lenght = totall % 16 |
+ |
Сложение | Tot_len = lenght * 8 + 1 |
- |
Вычитание | Entry_Son = ( |
<< |
сдвиг влево | |
>> |
сдвиг вправо | |
>= |
больше либо равно | if ent >= num |
> |
больше | if ent > num |
< |
меньше | if ent < num |
<= |
меньше либо равно | if ent <= num |
== |
равно | if ent == num |
!= |
не равно | if ent != num |
|
поразрядное "И" | flags = flags err_bit |
^ |
поразрядное "ИСКЛЮЧАЮЩЕЕ ИЛИ" | flags = flags ^ err_bit |
| |
поразрядное "ИЛИ" | flags = flags | err_bit |
|
логическое "И" | if ( |
|| |
логическое "ИЛИ" | if ( |
= |
установить равным... | entry_index = 0 |
++ |
увеличить на 1 (инкремент) | i ++ |
— |
уменьшить на 1 (декремент) | i — |
Операторы high, и используются для получения одного байта из многобайтного значения, соответствующего метке. Применяются для управления расчетом точек динамического перехода при чтении таблиц и записи программ.
Операторы инкремента и декремента могут применяться к переменной только в качестве единственного оператора в строке. Они не могут быть встроенным фрагментом более сложного выражения.
Поле комментария может использоваться программистом для текстового или символьного пояснения логической организации программы. Поле комментария полностью игнорируется * или ; ). Комментарии в конце строки должны быть отделены от остатка строки одним или более пробелами или табуляцией.
Существует ряд расширений файлов, применяемых по умолчанию MPASM и связанными утилитами. Назначения таких расширений приведены в табл. 6.4.
| Расширение | Назначение |
|---|---|
| . |
Входной файл <source_name>. |
| .OBJ | Выходной файл перемещаемого объектного кода из MPASM <source_name>.OBJ |
| .LST | Выходной файл листинга, генерируемый <source_name>.LST |
| . |
Выходной <source_name>. |
| .MAP | Выходной файл распределения памяти из MPASM: <source_name>.MAP |
| . |
Выходной файл объектного кода в шестнадцатиричном представлении из MPASM: <source_name>. |
| .HXL/.HXH | Выходной файл объектного кода в шестнадцатиричном представлении c раздельным представлением младших и старших байт: <source_name>.HXL, <source_name>.HXH |
| .LIB | Библиотечный файл, созданный MPLIB и привязанный компоновщиком MPLINK: <source_name>.LIB |
| .LNK | Выходной файл компоновщика: <source_name>.LNK |
| . |
Выходной символьный файл или файл отладчика. Формируются MPASM или MPLINK: <source_name>. |
Листинг представляет собой текстовый файл в формате ASCII, который содержит машинные коды, сгенерированные в соответствии с каждой ассемблерной командой, директивой
В состав листинга входят также
Директивы языка – это ассемблерные команды, которые встречаются в исходном коде, но не транслируются прямо в исполняемые коды. Они используются
Существует четыре основных типа директив в MPASM:
Директивы данных управляют распределением памяти и обеспечивают доступ к символическим обозначениям данных.
Директивы листинга управляют листингом файла MPASM и форматом. Они определяют спецификацию заголовков, генерацию страниц и другие функции управления листингом.
Директивы управления позволяют произвести
Макро-директивы управляют исполнением и распределением данных в пределах определений макротела.
Ниже приводится описание некоторых директив
CODE – начало секции объектного кода
Синтаксис:
[<label>] code [ROM address>]
Используется при генерации объектных модулей. Объявляет начало секции программного кода. Если <label> не указана, секция будет названа code. Стартовый адрес устанавливается равным указанному значению или нулю, если адрес не был указан.
Пример:
RESET code H'01FF'
goto START
#DEFINE – определить метку замены текста
Синтаксис:
#define <name> [<string>]
Директива задает строку <string>, замещающую метку <name> всякий раз, когда та будет встречаться в исходном тексте.
Символы, которые определены директивой #DEFINE, не могут быть просмотрены EQU.
Пример
#define length 20 #define control 0x19,7 #define position (X,Y,Z) (y-(2 * Z +X)). test_label dw position(1, length, 512) bsf control ; установить в 1 бит 7 в f19
END – конец программного блока
Синтаксис:
end
Определяет конец программы. После остановки программы
Пример:
start ;исполняемый код ; end ; конец программы
EQU – определить ассемблерную константу
Синтаксис:
<label> equ <expr>
Здесь <expr> – это правильное MPASM выражение. Значение выражения присваивается метке <label>.
Пример:
four equ 4 ; присваивает численное значение
; метке four
INCLUDE – включить дополнительный исходный файл
Синтаксис:
include <<include_file>> include "<include_file>"
Определяемый файл считывается как источник кода. По окончании <include_file> может быть заключен в кавычки или угловые скобки. Если указан полный путь к файлу, то поиск будет происходить только по этому пути. В противном случае порядок поиска следующий: текущий рабочий каталог, каталог, в котором находится исходник, каталог MPASM.
Пример:
include "c:\sys\sysdefs.inc" ; system defs include <addmain.asm> ; register defs
LIST – установить параметры листинга
Синтаксис:
list [<list_option>, , <list_option>]
Директива <list> разрешает вывод листинга, если он до этого был запрещен. Кроме того, один из параметров листинга может быть изменен для управления процессом ассемблирования в соответствии с табл. 6.5.
| Параметр | Значение по умолчанию | Описание |
|---|---|---|
C=nnn |
80 | Количество символов в строке |
n=nnn |
59 | Количество строк на странице |
t=ON|OFF |
OFF | Укорачивать строки листинга |
p=<type> |
None | Установить тип процессора: PIC16C54, PIC16C84, PIC16F84, PIC17C42 и др. |
r=< |
Установить систему счисления по умолчанию: |
|
w=<level> |
0 | Установить уровень сообщений диагностики в файле листинга: 0 – выводить все сообщения; 1 – выводить предупреждения и ошибки; 2 – выводить только ошибки. |
x=ON|OFF |
OFF | Включить или выключить макрорасширения. |
NOLIST – выключить выход листинга
Синтаксис:
NOLIST
ORG – установить начальный адрес программы
Синтаксис:
<label> org <expr>
Устанавливает начальный адрес программы для последующего кода в соответствии с адресом в <expr>. MPASM выводит перемещаемый объектный код, а MPLINK разместит код по определенному адресу. Если метка <label> определена, то ей будет присвоена величина <expr>. По умолчанию начальный адрес имеет нулевое значение. Директива может не использоваться, если создается объектный модуль.
Пример:
int_1 org 0x20; Переход по вектору 20 int_2 org int_1+0x10; Переход по вектору 30
PROCESSOR – установить тип процессора
Синтаксис:
processor <processor_type>
Устанавливает тип используемого процессора <processor_type>: [16C54 | 16C55 | 16C56 | 16C57 | 16C71 | 16C84 | 16F84 | 17C42]. Общие процессорные семейства могут быть выбраны как: [16C5X | 16CXX | 17CXX]
Для поддержания совместимости с новыми изделиями выбирается максимум доступной памяти.
SET – определить ассемблерную переменную
Синтаксис:
<label> set <expr>
Директива SET функционально эквивалентна директиве EQU, за исключением того, что величина, определяемая SET, может быть изменена директивой SET.
Пример:
area set 0 width set 0x12 length set 0x14 area set length * width length set length + 1
TITLE – Определить программный заголовок
Синтаксис:
title "<title_text>"
Эта директива устанавливает текст, который используется в верхней строке страницы листинга. <title_text> - это печатная ASCII последовательность, заключенная в двойные скобки. Она может быть до 60 символов длиной.
Пример
title "operational code, rev 5.0"
Абсолютный (неперемещаемый) код программы генерируется непосредственно при ассемблировании и располагается в программной памяти в порядке следования операторов программы.
При генерации перемещаемого кода каждая секция программного кода должна предваряться директивой CODE. Окончательное размещение программных кодов, расстановку физических адресов переходов выполняет компоновщик MPLINK.
Компоновщик MPLINK выполняет следующие задачи:
Для более подробного изучения работы компоновщика следует обратиться к специальной литературе.
Менеджер библиотек позволяет создавать и модифицировать файлы библиотек. Библиотечный файл является коллекцией объектных модулей, которые размещены в одном файле. MPLIB использует объектные модули с именем типа "filename.o" формата
Использование библиотечных файлов упрощает компоновку программы, делает ее более структурированной и облегчает ее модификацию.
MPSIM запускается из командной строки DOS, конфигурируется пользователем и непосредственно применяет выходные данные
Перед использованием <file_name>. и получить файл объектного кода в формате INHX8M, создаваемый MPASM по умолчанию:
MPASM <file_name>.asm <RETURN>
Чтобы запустить
MPSIM<RETURN>.
Вид экрана, получаемого при запуске MPSIM, показан на рис. 6.2. Экран разделен на три части, или окна. В верхнем окне показано текущее состояние моделирования, включая моделируемую программу, тип МК, число выполненных командных циклов и затраченное на них время. Среднее окно используется для вывода содержимого регистров пользователя. Набор регистров и формат выводимых на экран данных определяются файлом MPSIM.INI, который далее будет описан подробнее. Нижнее окно содержит приглашение на ввод команд, а также текущие операции и результат их выполнения.
При запуске MPSIM.INI. Этот текстовой файл создается пользователем и используется для задания всех задействованных в программе параметров.
(рис 6.2) Вид рабочего окна симулятора MPSIM.Один из примеров файла MPSIM.INI приведен ниже.
; MPSIM file for user4 P84 ;использование МК семейства PIC16C84 SR X ;представление данных в 16-ричном формате ZR ;сброс регистров МК в нуль ZT ;сброс таймера в нуль RE ;сброс времени выполнения команды и счетчика циклов V W,X,2 ;вывод регистра W в hex формате на два знакоместа AD F1,X,2 ;вывод на экран регистра TMR0 в hex формате на два знакоместа AD F2,X,3 ;вывод на экран регистра PCL в hex формате на три знакоместа AD F3,B,8 ;вывод на экран регистра STATUS в bin формате на восемь знакомест AD IOA,X,2 ;вывод на экран регистра TRISA в hex формате на два знакоместа AD F5,X,2 ;вывод на экран регистра порта A в hex формате на два знакоместа SC 1 ;установка тактовой частоты 1 МГц RS ;сброс МК LO user4
В представленном файле указаны: тип MPSIM.INI, который определяет начальное MPSIM.JRN, в котором сохраняются все сведения о нажатии клавиш в процессе работы.
В файле MPSIM.INI допускается вводить комментарии, которые даются после знака ";", но не допускается использование пустых строк.
Основные команды, применяемые в MPSIM.JRN, который используется при создании расширенного файла MPSIM.INI. Данный файл можно задействовать для выявления ошибок и обеспечения нормального выполнения программы после исправления кода.
| Команда | Параметр | Комментарии |
|---|---|---|
AB |
- | Прерывание текущей сессии |
AD |
Reg[, |
Вывод содержимого регистра на экран в указанном формате и заданной системе счисления X, B или D |
B |
[addr] |
Установка точки останова по текущему или указанному адресу |
C |
[#break] |
Продолжение выполнения программы с пропуском указанного количества следующих точек останова |
|
- | Вывод на экран всех активных точек останова |
DI |
[addr1[,addr2]] |
Вывод на экран фрагмента памяти программ |
DR |
- | Вывод содержимого всех регистров |
DW |
[E|D] |
Разрешение/запрещение функционирования |
E |
[addr] |
Выполнение программы с текущего или указанного адреса |
F |
Reg |
Вывод на экран содержимого регистра и возможность его редактирования пользователем |
GE |
filename |
Получение и выполнение командного файла. Это способ загрузки командного файла .INI |
GO |
- | Запуск МК и начало выполнения программы |
IP |
[time|step] |
Ввод входных воздействий в соответствии со значением параметра step в файле |
LO |
filename |
Загрузка в MPSIM файлов . |
M |
addr |
Вывод на экран содержимого памяти программ, начиная с адреса "addr" и возможность его редактирования. Ввод "Q" завершает команду. |
P |
device |
Выбор типа моделируемого МК |
Q |
- | Выход из MPSIM и запись команд в файл .JRN |
RE |
- | Сброс времени выполнения и счетчика циклов |
RS |
- | Сброс моделируемого МК |
SE |
|
Вывод на экран состояния указанного вывода или порта и возможность его изменения |
SR |
O|X|D |
Установка системы счисления по умолчанию |
SS |
[addr] |
Пошаговое исполнение, начиная с указанного адреса. При отсутствии адреса – исполнение идет с текущего места |
ST |
filename |
Загрузка файла стимуляции |
W |
Отображение состояния регистра W с возможностью его модификации |
|
ZM |
addr1,addr2 |
Очистка памяти программ с адреса addr1 по addr2 |
ZR |
- | Сброс всех регистров МК |
ZT |
- | Сброс таймера/счетчика МК |
Для моделирования внешних тестовых событий (воздействий) на моделируемый МК используются файлы стимуляции с расширением .STI. Эти файлы используются MPSIM для того, чтобы обеспечить подачу однократных и повторяющихся входных сигналов в процессе выполнения программы. При этом можно наблюдать на экране, как МК реагирует на сигналы.
В качестве примера ниже приведен файл для A.
! test1.STI STEP RA1 1 1 !Установка на входе RA1 состояния "1" 200 0 !Поступление на вход RA1 сигнала "0" 1000 1 !Переход сигнала на входе RA1 в "1" 1200 0 !Повторная подача нулевого сигнала
Файл воздействия состоит из
Для того чтобы написать первые учебные программы и проверить их функционирование, желательно иметь относительно несложный макет, содержащий самые распространенные периферийные устройства. Схема подобного макета, используемого при выполнении лабораторных работ студентами, приведена на рис. 6.3.
Макет питается от источника стабилизированного напряжения +5В. Тактовая частота МК задается RC-цепью и составляет около 2 МГц. К линии RA0 порта А подключен биполярный транзистор в ключевом режиме, нагруженный на динамик ВА1. Звучание динамика обеспечивается подачей на выход RA0 изменяющегося сигнала в звуковом диапазоне. К линии RA1 порта А подключен светодиод VD2, светящийся при высоком напряжении на выходе. Тумблеры SA1 и SA2, а также кнопки SB1 и SB2 подключены, соответственно, к линиям RA2 и RA3 порта А, а также к линии RA4 порта А и линии RB0 порта В. Исходное состояние кнопок – разомкнутое, что обеспечивает подачу на соответствующие входы МК высокого уровня сигнала.
Линии RB1 – RB7 порта B обслуживают семисегментный индикатор HL1 с общим анодом. Поэтому свечение сегмента индикатора обеспечивается при низком уровне сигнала на соответствующем выходе порта B. Макет также содержит средства программирования и связи с компьютером, которые на схеме не показаны.
(рис 6.3) Схема лабораторного макета.
Прежде чем переходить к созданию простейших пользовательских программ, необходимо описать используемые в дальнейшем переменные и настроить МК на работу с выбранным макетом. С этой целью мы напишем и подробно рассмотрим листинг исходной программы init., в состав которой будут включаться все остальные программы пользователя.
;******************************************************
;*листинг исходной программы
;******************************************************
LIST P=16C84, R=HEX ;директива, определяющая тип
;процессора и систему счисления
;по умолчанию
;******************************************************
;*описание используемых переменных и назначения адресов
;*ячеек для хранения переменных пользователя
;******************************************************
; INTCON EQU 0x0B
; OPTION EQU 0x81
; TMR0 EQU 0x01
; INTF EQU 1
; T0IF EQU 5
PCL EQU 0x02
STATUS EQU 0x03
RP0 EQU 5
PORTA EQU 0x05
PORTB EQU 0x06
TRISA EQU 0x05
TRISB EQU 0x06
W EQU 0
F EQU 1
TEMPA EQU 0x0C
TEMPB EQU 0x0D
COUNT1 EQU 0x0E
COUNT2 EQU 0x0F
COUNT3 EQU 0x10
;******************************************************
;*определение меток замены текста
;******************************************************
#DEFINE Z STATUS,2 ;бит нулевого результата
#DEFINE BA1 PORTA,0 ;динамик BA1
#DEFINE VD2 PORTA,1 ;светодиод VD2
#DEFINE SA1 PORTA,2 ;тумблер SA1
#DEFINE SA2 PORTA,3 ;тумблер SA2
#DEFINE SB1 PORTA,4 ;кнопка SB1
#DEFINE SB2 PORTB,0 ;кнопка SB2
#DEFINE HL1_A PORTB,1 ;индикатор-сегмент A
#DEFINE HL1_B PORTB,2 ;индикатор-сегмент B
#DEFINE HL1_C PORTB,3 ;индикатор-сегмент C
#DEFINE HL1_D PORTB,4 ;индикатор-сегмент D
#DEFINE HL1_E PORTB,5 ;индикатор-сегмент D
#DEFINE HL1_F PORTB,6 ;индикатор-сегмент E
#DEFINE HL1_G PORTB,7 ;индикатор-сегмент F
;******************************************************
;*исполняемая программа
;******************************************************
ORG 0x000 ;установка начального адреса по
;сбросу
GOTO BEGIN ;переход на начало программы
ORG 0x005 ;установка начального адреса
;размещения программы
BEGIN
CALL INIT_PORTS ;вызов подпрограммы
;инициализации портов МК
;*****************************************************
;*программа пользователя
;
;*****************************************************
;
INIT_PORTS ;подпрограмма инициализации
;портов
MOVLW 0xFF ;установка линий портов
MOVWF PORTA ;A и B в единичное
MOVWF PORTB ;состояние
BSF STATUS,RP0 ;переход на банк 1
MOVLW 0x1C ;настройка линий RA0 и
MOVWF TRISA ;RA1 порта A на вывод –
;остальных – на ввод
MOVLW 0x01 ;настройка линии RB0
MOVWF TRISB ;порта B на ввод -
;остальных – на вывод
BCF STATUS,RP0 ;возврат в банк 0
RETURN ;возврат из подпрограммы
;
END ;конец программы
Рассмотрим работу этой программы. Вначале она указывает EQU определяют ассемблерные константы, используемые в этой и последующих программах. Они позволяют использовать в тексте программы более удобные мнемонические метки, привязанные к структуре конкретного МК, вместо корректных, но более сложных ассемблерных выражений. Указатели TEMPA, TEMPB, COUNT1 и COUNT2 назначают адреса ячеек памяти для хранения промежуточных данных (текущих состояний, переменных циклов и т.п.).
Ассемблерные директивы #define задают строку, замещающую соответствующую метку, каждый раз, когда та будет встречаться в исходном тексте. В нашем случае эти директивы позволяют использовать символические имена, привязанные к схеме макета, вместо физических адресов соответствующих разрядов портов и регистров. При этом необходимо иметь в виду, что символы, которые определены директивой #DEFINE, не могут быть просмотрены
Директива ORG 0x00 устанавливает стартовый адрес программного кода равным 0, т.е. соответствующим начальному состоянию GOTO BEGIN вместе с ассемблерной директивой ORG 0x005 и меткой BEGIN обеспечивают переход на адрес памяти программ 0x005, начиная с которого и размещается основная часть программы. Это необходимо для того, чтобы обойти адрес 0x004, используемый в качестве вектора прерывания, и тем самым зарезервировать его для возможных будущих применений.
Затем с помощью команды CALL INIT_PORTS производится вызов подпрограммы инициализации портов. Вначале подпрограмма инициализации устанавливает в высокое (единичное) состояние выходные триггеры данных. Эта операция рекомендуется разработчиком МК для того, чтобы исключить неопределенность в состояниях регистров портов. Затем командой BSF STATUS,RP0 производится переключение на банк 1 памяти данных, где расположены TRISA и TRISB. С помощью команд MOVLW 0x1C и MOVWF TRISA линии RA0 и RA1 порта A настраиваются на вывод, а остальные – на ввод. Команды MOVLW 0x01 и MOVWF TRISB настраивают линию RB0 порта B на ввод, а остальные – на вывод. С помощью команды BCF STATUS,RP0 производится возврат в банк 0, где располагаются необходимые для работы программы регистры и порты.
Поскольку в процессе работы с макетом перенастройка портов не производится, и введенных переменных достаточно для работы всех рассматриваемых учебных задач, они будут далее рассматриваться включенными по умолчанию в состав исходной программы init.. При написании учебных задач будет по возможности использоваться метод структурного программирования, при котором прикладная программа строится из некоторого набора программных модулей, каждый из которых реализует определенную процедуру обработки данных. При этом каждый из программных модулей имеет только одну точку входа и одну точку выхода. Введенные однажды программные модули могут использоваться под своим именем в других прикладных программах.
Начнем программирование учебных задач с написания программы, которая считывает состояние кнопки SB1 и выводит его на светодиодный индикатор VD2 так, что не нажатому состоянию кнопки (высокому уровню сигнала на входе RA4 ) соответствует светящееся состояние светодиода, и наоборот.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_RA
CALL SB1_VD2 ;вызов подпрограммы SB1_VD2
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
GET_RA ;подпрограмма чтения состояния
;порта A
MOVF PORTA,W ;чтение состояния порта A в W
MOVWF TEMPA ;пересылка W в TEMPA
RETURN ;возврат из подпрограммы
;
SB1_VD2 ;подпрограмма вывода на светодиод
;VD2 состояния кнопки SB1 (разряда 4
;регистра TEMPA)
BTFSS TEMPA,4 ;пропустить команду, если
;TEMPA,4=1 (кнопка не нажата)
GOTO P0 ;перейти на P0
BSF VD2 ;зажечь светодиод VD2
P0
BTFSC TEMPA,4 ;пропустить команду, если
;TEMPA,4=0 (кнопка нажата)
GOTO P1 ;перейти на P1
BCF VD2 ;погасить светодиод
P1
RETURN
;
Основная программа содержит замкнутый цикл LOOP – GOTO LOOP, необходимый для периодического повторения цикла контроля состояния кнопки и вывода его на индикатор. Команда CLRWDT исключает влияние возможного сброса по переполнению GET_RA и SB1_VD2. Первая из них ( GET_RA ) вначале считывает текущее состояние порта A, которое помещается в рабочий регистр W. Поскольку рабочий регистр может потребоваться при исполнении других команд, его состояние записывается в регистр TEMPA, используемый здесь для временного хранения состояния порта A. Таким образом, после возврата из подпрограммы GET_RA в разряде 4 регистра TEMPA содержится информация о состоянии кнопки SB1: "1" – не нажата, "0" – нажата.
Подпрограмма SB1_VD2 анализирует состояние разряда 4 регистра TEMPA и, в зависимости от него, зажигает или гасит светодиод. В системе команд МК PIC16F84 нет команд BTFSS и BTFSC ). В частности, команда BTFSS TEMP,4 пропускает исполнение команды GOTO P0, если TEMP,4 = 1 (кнопка не нажата). Тем самым реализуется команда BSF VD2, которая зажигает светодиод VD2. Затем анализируется условие TEMP,4 = 0 (кнопка нажата) и, если оно имеет место, светодиод гасится.
Возможна более простая реализация заданного алгоритма, поскольку нажатое состояние кнопки исключает не нажатое (и наоборот), но представленный вариант более нагляден.
Рассмотрим более сложный вариант программы, предусматривающий зажигание светодиода VD2 только при следующем состоянии тумблеров и кнопок макета: SA1 = 1, SA2 = 1, SB1 = 1 и SB2 = 0.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_RA
CALL GET_RB ;вызов подпрограммы GET_RB
CALL ZAG_1110 ;вызов подпрограммы ZAG_1110
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
GET_RB ;подпрограмма чтения состояния
;порта B
MOVF PORTB,W ;чтение состояния порта B в W
MOVWF TEMPB ;пересылка W в TEMPB
RETURN
;
ZAG_1110 ;зажигает светодиод VD2 только при
;следующем состоянии тумблеров и
;кнопок макета:
;SA1 = SA2 = SB1 = 1 и SB2 = 0
BTFSS TEMPA,2 ;пропустить команду, если
GOTO P0 ;TEMPA,2=1
BTFSS TEMPA,3 ;пропустить команду, если
GOTO P0 ;TEMPA,3=1
BTFSS TEMPA,4 ;пропустить команду, если
GOTO P0 ;TEMPA,4=1
BTFSC TEMPB,0 ;пропустить команду, если
GOTO P0 ;TEMPB,0=0
BSF VD2 ;зажечь светодиод VD2
GOTO P1
P0
BCF VD2 ;погасить светодиод VD2
P1
RETURN
;
INCLUDE GET_RA.ASM
;
Подпрограммы GET_RA и GET_RB помещают в регистры TEMPA и TEMPB текущие состояния портов A и B, соответственно. Подпрограмма ZAG_1110 анализирует состояния разрядов 2,3 и 4 регистра TEMPA и разряда 0 регистра TEMPB, и при условии TEMPA,2,3,4 = 1,1,1 и TEMPB,0 = 0, зажигает светодиод VD2. При невыполнении хотя бы одного из этих условий светодиод гасится.
Использование директивы INCLUDE GET_PORTA. позволяет включать уже отлаженные модули подпрограмм в текущую программу. Для того чтобы этой возможностью можно было воспользоваться, необходимо сохранять отлаженные модули в виде отдельных ассемблерных файлов.
Попробуем теперь использовать семисегментный индикатор для контроля состояния тумблеров макета. Вначале напишем программу, которая выводит на индикатор HL семисегментное изображение любого двоичного числа от 0b до 1111b в шестнадцатиричном представлении.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
MOVLW 0x0A ;пересылка константы 0A в W
CALL SEV_SEG ;вызов подпрограммы SEVEN_SEG
MOVWF PORTB ;пересылка W в PORTB
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
SEV_SEG ;подпрограмма обслуживания
;семисегментного индикатора
ANDLW 0x0F ;маскирование 4-х младших разрядов
;W и обнуление 4-х старших
ADDWF PCL,F ;сложение W с PCL и пересылка
;результата в PCL
RETLW 0x80 ;возврат из подпрограммы с 80 в W
RETLW 0xF2 ;возврат из подпрограммы с F2 в W
RETLW 0x48 ;возврат из подпрограммы с 48 в W
RETLW 0x60 ;возврат из подпрограммы с 60 в W
RETLW 0x32 ;возврат из подпрограммы с 32 в W
RETLW 0x25 ;возврат из подпрограммы с 25 в W
RETLW 0x04 ;возврат из подпрограммы с 04 в W
RETLW 0xF0 ;возврат из подпрограммы с F0 в W
RETLW 0x00 ;возврат из подпрограммы с 00 в W
RETLW 0x20 ;возврат из подпрограммы с 20 в W
RETLW 0x10 ;возврат из подпрограммы с 10 в W
RETLW 0x06 ;возврат из подпрограммы с 06 в W
RETLW 0x8C ;возврат из подпрограммы с 8C в W
RETLW 0x42 ;возврат из подпрограммы с 42 в W
RETLW 0x0C ;возврат из подпрограммы с 0C в W
RETLW 0x1C ;возврат из подпрограммы с 1C в W
;
Программа начинает свою работу с пересылки константы 0x0A в рабочий регистр W. Затем производится вызов подпрограммы обслуживания семисегментного индикатора SEV_SEG. Работа подпрограммы SEV_SEG начинается с маскирования 4-х младших разрядов W и обнуления 4-х старших. Тем самым из анализа исключаются старшие разряды передаваемого из рабочего регистра W числа. Затем маскированное содержимое регистра W добавляется к текущему состоянию младшего байта , и результат помещается в . Таким образом, производится дополнительное смещение W=0, то содержимое RETLW 0x80, которая вызовет возврат из подпрограммы с записью 0x80 = B'10000000' в регистр W. Если, как было в при
веденной программе, W=0A, то к содержимому будет добавлено число 0x0A, и произойдет дополнительное смещение на 10 шагов. В результате будет выполнена команда RETLW 0x10, которая вызовет возврат из подпрограммы с записью 0x10 = B'0001000' в регистр W.
После возврата из подпрограммы производится пересылка W в PORTB и отображение его состояния на семисегментном индикаторе HL. В частности, если W = 0, то при выводе 1000000b на порт B семисегментный индикатор покажет 0, а при W = A покажет A.Таким образом, может быть отображено любое 4-разрядное двоичное число.
Метод прямого управления счетчиком команд, использованный в подпрограмме SEV_SEG, может применяться для реализации табличной конвертации чисел. При этом необходимо иметь в виду, что данный метод не позволяет конвертировать более 256 значений в одной таблице. Кроме того, программа табличной конвертации должна целиком располагаться внутри 256-байтного блока во избежание переполнения младшего байта
Используя подпрограмму SEV_SEG, напишем теперь программу, которая читает состояния тумблеров SA1 и SA2 и выводит на индикатор соответствующее число.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_RA
RRF TEMPA,F ;сдвиг вправо на один разряд
;через перенос
RRF TEMPA,W ;сдвиг вправо на один разряд
;через перенос
ANDLW 0x03 ;маска на два младших разряда
CALL SEV_SEG ;вызов подпрограммы SEVEN_SEG
MOVWF PORTB ;пересылка W в PORTB
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
INCLUDE GET_RA.ASM
INCLUDE SEV_SEG.ASM
;
Подпрограмма GET_RA помещает в регистр TEMPA текущее состояние порта A. Таким образом, в разрядах 2 и 3 регистра TEMPA хранится текущее состояние тумблеров SA1 и SA2. Для того чтобы биты состояния тумблеров заняли позиции 0 и 1 регистра TEMPA, производится два сдвига вправо через перенос, причем результат второго сдвига помещается в регистр W. Затем накладывается маска на два младших разряда рабочего регистра и производится вызов подпрограммы SEV_SEG. После выхода из подпрограммы результат подается на порт B и отображается на индикаторе.
Рассмотрим теперь программы, работающие в реальном масштабе времени, т.е. выдающие сигналы определенной длительности и частоты следования, либо учитывающие временные параметры входных сигналов. Основным элементом таких программ является подпрограмма формирования временной задержки. Рассмотрим один из возможных вариантов такой подпрограммы с использованием программных методов формирования задержки, т.е. без применения встроенного таймера.
;основная программа
MOVLW 0xL ;пересылка константы H'L' в W
CALL DELAY ;вызов подпрограммы DELAY
;
DELAY ;подпрограмма формирования
;задержки времени
MOVWF COUNT1 ;загрузка W в регистр COUNT1
LOOPD
DECFSZ COUNT1,F ;декремент COUNT1
GOTO LOOPD ;повторение цикла H'L' раз
RETURN ;возврат из подпрограммы
;
Основная программа производит вызов подпрограммы с некоторой константой L в рабочем регистре W, определяющей число внутренних циклов подпрограммы. Подпрограмма начинает свою работу с загрузки содержимого рабочего регистра в регистр пользователя COUNT1. Команда DECFSZ COUNT1,F уменьшает на единицу содержимое регистра COUNT1 и проверяет его на равенство нулю. Нулевое состояние регистра COUNT1 приводит к выходу из цикла и возврату из подпрограммы. Для исполнения каждого внутреннего цикла требуется три машинных цикла МК (1 цикл на исполнение команды DECFSZ при ненулевом результате и 2 цикла на каждую команду GOTO ). Выход из подпрограммы потребует 4-х циклов (2 цикла на исполнение команды DECFSZ при нулевом результате и 2 цикла на RETURN ). Если добавить к этому еще 4 цикла, необходимых для загрузки константы в рабочий регистр
, вызова подпрограммы и загрузки регистра пользователя COUNT1, то общее время исполнения подпрограммы (задержка) составит
TD = 4 + 3*(L – 1) + 4 = 5 + 3*L циклов,
где L – константа, переданная через рабочий регистр в подпрограмму .
При тактовой частоте fosc = 2МГц время цикла равно tц = 2 мкс, поэтому при загрузке L = H'00' = .0 максимальный формируемый интервал времени составит 1,55 мс. Такой результат связан с тем, что команда DECFSZ сначала декрементирует содержимое регистра ( H'00' – 1 = H'FF' ), а затем уже анализирует результат.
Минимальный формируемый интервал времени составит при тех же условиях 5 циклов или 10 мкс. Для получения такого интервала необходимо перед вызовом подпрограммы загрузить в рабочий регистр число 0x01.
Для расширения верхней границы формируемых временных интервалов, а также с целью повышения удобства работы с подпрограммой, можно добавить в цикл LOOPD одну или несколько дополнительных команд, в качестве которых чаще всего используется команда . Для примера рассмотрим подпрограмму формирования задержки времени DELAY_C
;
DELAY_C ;подпрограмма формирования
;задержки времени (вариант C)
MOVWF MOVWF COUNT1 ;загрузка W в регистр COUNT1
LOOPD
NOP ;пустая команда
DECFSZ COUNT1,F ;декремент COUNT1
GOTO LOOPD ;повторение цикла H'L' раз
RETURN ;возврат из подпрограммы
;
Общее время исполнения подпрограммы DELAY_C, включая ее вызов, составит
TD = 4 + 4*(L – 1) + 4 = 4 + 4*L циклов.
При тактовой частоте fosc = 2МГц и загрузке константы L = H'F9' = .249 формируемый интервал времени составит ровно 2 мс. Уменьшение константы на единицу уменьшает формируемый временной интервал на 8 мкс. В частности, при L = .124 образуется задержка в 1 мс.
Для формирования больших задержек времени, лежащих в диапазоне долей и единиц секунд, такой подход неудобен. В этом случае используются
;основная программа
MOVLW 0xL ;пересылка константы H'L' в W
CALL DELAY_D ;вызов подпрограммы DELAY_D
;
DELAY_D ;подпрограмма формирования
;большой задержки времени (вариант D)
MOVWF COUNT2 ;загрузка W в регистр COUNT2
CLRF COUNT1 ;сброс содержимого регистра COUNT1
LOOPD
DECFSZ COUNT1,F ;декремент COUNT1
GOTO LOOPD ;повторение цикла 256 раз
CLRWDT ;сброс сторожевого таймера
DECFSZ COUNT2,F ;декремент COUNT2
GOTO LOOPD ;повторение цикла H'L' раз
RETURN ;возврат из подпрограммы
;
Время исполнения внутреннего цикла подпрограммы DELAY_D составляет 3*256 + 4 машинных циклов МК, поэтому общая задержка составит
TD = 5 + (3*256 + 4)*L циклов.
При тактовой частоте fosc = 2МГц время цикла равно tц = 2 мкс, поэтому при загрузке L = H'00' = .0 максимальный формируемый интервал времени составит около 0,4 с.
Поскольку формируемый интервал времени достаточно велик, во внешний цикл включена команда сброса
Интервал времени 0,4 с не совсем удобен для получения задержек времени, кратных секунде, поэтому рассмотрим еще один вариант подпрограммы формирования больших задержек времени с дополнительной командой во внутреннем цикле.
;
DELAY_E ;подпрограмма формирования
;большой задержки времени (вариант E)
MOVWF COUNT2 ;загрузка W в регистр COUNT2
CLRF COUNT1 ;сброс содержимого регистра COUNT1
LOOPD
NOP ;пустая команда
DECFSZ COUNT1,F ;декремент COUNT1
GOTO LOOPD ;повторение цикла 256 раз
CLRWDT ;сброс сторожевого таймера
DECFSZ COUNT2,F ;декремент COUNT2
GOTO LOOPD ;повторение цикла H'L' раз
RETURN ;возврат из подпрограммы
;
Время исполнения внутреннего цикла подпрограммы DELAY_E составляет 4*256 + 4 машинных циклов МК, поэтому общая задержка составит
TD = 5 + (4*256 + 4)*L циклов.
При тактовой частоте fosc = 2МГц и при загрузке L = H'F3' = .243 формируемый интервал времени составит около 0,5 с при погрешности не более 0,2%. Если необходима более высокая точность, можно вставить необходимое количество пустых операций во внешний цикл формирования задержки.
Рассмотрим далее несколько программ с использованием подпрограмм формирования задержки времени. Начнем с написания программы, которая подает звуковой сигнал на динамик BA1 при нажатии на кнопку SB1. Динамик будет звучать только в том случае, если на выход RA0 будет подан периодически изменяющийся сигнал. Для того чтобы звук был хорошо слышен, его частота должна находиться вблизи максимума слышимости человеческого уха. Выберем частоту звучания равной 1 КГц, что соответствует периоду следования импульсов сигнала 1 мс.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_PORTA
CALL SB1_BA1 ;вызов подпрограммы SB1_BA1
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
SB1_BA1 ;подпрограмма подачи звука на
;динамик BA1 при нажатии на кнопку
;SB1
BTFSC TEMPA,4 ;пропустить команду, если
;TEMPA,4=0 (кнопка нажата)
GOTO B0 ;перейти на B0
BSF BA1 ;подача высокого уровня на RA0
MOVLW 0x3E ;пересылка константы
;H'3E' = .62 в W
CALL DELAY_C ;вызов подпрограммы DELAY_C
BCF BA1 ;подача низкого уровня на RA0
MOVLW 0x3E ;пересылка константы
;H'3E' = .62 в W
CALL DELAY_C ;вызов подпрограммы DELAY_C
B0
RETURN
;
INCLUDE GET_RA.ASM
INCLUDE DELAY_C.ASM
;
Как и раньше, подпрограмма GET_RA считывает текущее состояние порта A, которое затем передается в регистр TEMPA. Подпрограмма SB1_BA1 анализирует состояние разряда 4 регистра TEMPA и, в зависимости от результата, озвучивает динамик BA1 или нет. Необходимая выдержка линии RA0 в единичном и нулевом состояниях обеспечивается подпрограммой DELAY_C с параметром L = H'3E' = .62. Это соответствует времени задержки около 0,5 мс, что и дает в результате необходимую частоту следования сигнала 1 Кгц.
Рассмотрим далее программу, которая заставляет мигать светодиод VD2 при нажатии на кнопку SB1. Для того чтобы мигания были хорошо видны, выберем их частоту равной 1 Гц.
;основная программа
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RA ;вызов подпрограммы GET_RA
CALL SB1_VD2M ;вызов подпрограммы
;SB1_VD2M
GOTO LOOP ;переход к метке LOOP для
;повторения процесса
;
SB1_VD2M ;подпрограмма мигания светодиода
;VD2 при нажатии на кнопку SB1
BTFSC TEMPA,4 ;пропустить команду, если
;TEMPA,4=0 (кнопка нажата)
GOTO V0 ;перейти на V0
BSF VD2 ;зажечь светодиод VD2
MOVLW 0xF3 ;пересылка константы
;H'F3' = .243 в W
CALL DELAY_E ;вызов подпрограммы DELAY_E
BCF VD2 ;погасить светодиод
MOVLW 0xF3 ;пересылка константы
;H'F3' = .243 в W
CALL DELAY_E ;вызов подпрограммы DELAY_E
V0
BTFSS TEMPA,4 ;пропустить команду, если
;TEMPA,4=1 (кнопка не нажата)
GOTO V1 ;перейти на V1
BCF VD2 ;погасить светодиод
V1
RETURN
;
INCLUDE GET_RA.ASM
INCLUDE DELAY_E.ASM
;
Программа работает почти так же, как и предыдущая. Первое отличие заключается в том, что светодиод принудительно гасится при не нажатой кнопке. Второе отличие заключается в величине интервала времени, который составляет здесь 0,5 с и формируется подпрограммой DELAY_E.
Подпрограммы формирования задержки времени могут быть также полезны при работе с такими внешними источниками сигналов, как тумблеры, кнопки, переключатели и т.п. Дело в том, что все механические коммутаторы имеют одно негативное свойство, известное как "дребезг" контактов, которое обусловлено механическими колебаниями контактов при их замыкании и размыкании. Длительность колебаний составляет обычно несколько миллисекунд, в течение которых на вход МК может поступать пачка импульсов вместо идеального перепада.
Аппаратные способы борьбы с "дребезгом" контактов основаны на использовании
В качестве примера рассмотрим "бездребезговый" вариант подпрограммы чтения состояния порта A.
;
GET_RAD ;подпрограмма чтения состояния
;порта A в регистр TEMPA
;с подавлением "дребезжания"
DD
MOVF PORTA,W ;чтение состояния порта A в W
ANDLW 0x1C ;наложение маски b'00011100'
;на неиспользуемые биты W
MOVWF TEMPA ;пересылка W в TEMPA
CLRWDT ;сброс сторожевого таймера WDT
MOVLW 0x0A ;пересылка константы
;H'0A' = .10 в W
CALL DELAY_E ;вызов подпрограммы DELAY_E
MOVF PORTA,W ;чтение состояния порта A в W
ANDLW 0x1C ;наложение на W маски b'00011100'
SUBWF TEMPA,W ;вычитание W из TEMPA
BTFSS Z ;пропустить команду, если результат
;нулевой
GOTO DD ;перейти на метку DD
RETURN
;
INCLUDE DELAY_E.ASM
;
Суть работы подпрограммы заключается в повторном чтении состояния порта A спустя некоторое время после предыдущего и сравнении его с прежним значением. Константа H'0A' = .10, пересылаемая в регистр W перед вызовом подпрограммы DELAY_E, обеспечивает значение задержки времени около 20 мс - этого, как правило, достаточно для завершения переходных процессов при переключении механических коммутаторов. Маскирование неиспользуемых разрядов порта повышает надежность работы подпрограммы. Сброс A.
Рассмотрим теперь работу программы, которая использует некоторые из разработанных ранее подпрограмм. Пусть целью работы программы является подсчет числа нажатий на кнопку SB1 с выводом результата на семисегментный индикатор в шестнадцатиричном коде.
;основная программа
CLRF COUNT3 ;сброс счетчика нажатий
LOOP
CLRWDT ;сброс сторожевого таймера
CALL GET_RAD ;вызов подпрограммы GET_RAD
BTFSC TEMPA,4 ;проверка нажатия SB1
GOTO LOOP ;если не нажата – возврат
;на метку LOOP
INCF COUNT3,F ;инкремент счетчика
MOVF COUNT3,W ;пересылка содержимого
;счетчика в рабочий регистр
CALL SEV_SEG ;вызов подпрограммы SEV_SEG
MOVWF PORTB ;пересылка W в PORTB
TEST
CALL GET_RAD ;вызов подпрограммы GET_RAD
BTFSS TEMPA,4 ;проверка нажатия SB1
GOTO TEST ;если еще нажата – возврат
;на метку TEST
GOTO LOOP ;возврат на метку LOOP
;
INCLUDE GET_RAD.ASM
INCLUDE SEV_SEG.ASM
;
Приведенные в главе программы не охватывают и малой доли возможностей, которые предоставляет даже такой простой макет, как изображенный на рис. 6.3. Однако их освоение, надеюсь, будет полезным для начинающих пользователей
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.